From fb81c77722ea596589be804235762ae4c374b364 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Tue, 21 May 2024 20:14:34 +0900 Subject: [PATCH 01/60] =?UTF-8?q?seed=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 134 +++++ app.js | 24 + data/mock.js | 22 + data/seed.js | 11 + models/product.js | 47 ++ package-lock.json | 1262 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 15 + 7 files changed, 1515 insertions(+) create mode 100644 .gitignore create mode 100644 app.js create mode 100644 data/mock.js create mode 100644 data/seed.js create mode 100644 models/product.js create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..989cf15 --- /dev/null +++ b/.gitignore @@ -0,0 +1,134 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# env +.env +env.js \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..004f1cc --- /dev/null +++ b/app.js @@ -0,0 +1,24 @@ +import express from "express"; +import mongoose from "mongoose"; +import { DATABASE_URL } from "./env.js"; + +mongoose.connect(DATABASE_URL).then(() => console.log("Connected to DB")); +const app = express(); + +app.use(express.json()); + +const asyncHandler = (handler) => { + return async (req, res) => { + try { + await handler(req, res); + } catch (e) { + if (e.name === "ValidationError") { + res.status(400).send({ message: e.message }); + } else if (e.name === "CastError") { + res.status(404).send({ message: "존재하지 않는 상품입니다." }); + } else { + res.status(500).send({ message: "서버 에러입니다." }); + } + } + }; +}; diff --git a/data/mock.js b/data/mock.js new file mode 100644 index 0000000..f56e1c7 --- /dev/null +++ b/data/mock.js @@ -0,0 +1,22 @@ +const data = [ + { + favoriteCount: 0, + ownerId: 1, + images: ["https://example.com/..."], + tags: ["판다인형", "인형", "판다"], + price: 700000, + description: "판다인형 판다", + name: "판다인형", + }, + { + favoriteCount: 2, + ownerId: 2, + images: ["https://example.com/..."], + tags: ["판다인형", "인형", "판다"], + price: 7000, + description: "판다인형 안판다", + name: "판다인형 안파는 판다", + }, +]; + +export default data; diff --git a/data/seed.js b/data/seed.js new file mode 100644 index 0000000..89ec145 --- /dev/null +++ b/data/seed.js @@ -0,0 +1,11 @@ +import mongoose from "mongoose"; +import { DATABASE_URL } from "../env.js"; +import Product from "../models/product.js"; +import data from "./mock.js"; + +mongoose.connect(DATABASE_URL); + +await Product.deleteMany({}); +await Product.insertMany(data); + +mongoose.connection.close(); diff --git a/models/product.js b/models/product.js new file mode 100644 index 0000000..318abcc --- /dev/null +++ b/models/product.js @@ -0,0 +1,47 @@ +import mongoose from "mongoose"; + +const ProductSchema = new mongoose.Schema( + { + favoriteCount: { + type: Number, + default: 0, + }, + ownerId: { + type: Number, + required: true, + }, + + images: { + type: [String], + required: true, + }, + tags: { + type: [String], + required: true, + }, + price: { + type: Number, + required: true, + default: 0, + }, + description: { + type: String, + }, + name: { + type: String, + required: true, + }, + isFavorite: { + type: Boolean, + required: true, + default: false, + }, + }, + { + timestamps: true, + } +); + +const Product = mongoose.model("Product", ProductSchema); + +export default Product; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..e76448a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1262 @@ +{ + "name": "QA-sprint-mission", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "express": "^4.19.2", + "mongoose": "^8.4.0" + }, + "devDependencies": { + "nodemon": "^3.1.0" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.7.tgz", + "integrity": "sha512-dCHW/oEX0KJ4NjDULBo3JiOaK5+6axtpBbS+ao2ZInoAL9/YRQLhXzSNAFz7hP4nzLkIqsfYAK/PDE3+XHny0Q==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "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==" + }, + "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==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bson": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.7.0.tgz", + "integrity": "sha512-w2IquM5mYzYZv6rs3uN2DZTOBe2a0zXLj53TGDqwF4l6Sz/XsISrisXOJihArF9+BZ6Cq/GjVht7Sjfmri7ytQ==", + "engines": { + "node": ">=16.20.1" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/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==" + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mongodb": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.6.2.tgz", + "integrity": "sha512-ZF9Ugo2JCG/GfR7DEb4ypfyJJyiKbg5qBYKRintebj8+DNS33CyGMkWbrS9lara+u+h+yEOGSRiLhFO/g1s1aw==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "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", + "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.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.4.0.tgz", + "integrity": "sha512-fgqRMwVEP1qgRYfh+tUe2YBBFnPO35FIg2lfFH+w9IhRGg1/ataWGIqvf/MjwM29cZ60D5vSnqtN2b8Qp0sOZA==", + "dependencies": { + "bson": "^6.7.0", + "kareem": "2.6.3", + "mongodb": "6.6.2", + "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==", + "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==", + "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", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nodemon": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", + "integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==", + "dev": true, + "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": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "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==" + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/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==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..e91d2bd --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "dependencies": { + "express": "^4.19.2", + "mongoose": "^8.4.0" + }, + "devDependencies": { + "nodemon": "^3.1.0" + }, + "type": "module", + "scripts": { + "dev": "nodemon app.js", + "start": "node app.js", + "seed": "node data/seed.js" + } +} From de043b5b69f71b5099232f521578479e0cfa9912 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Tue, 21 May 2024 20:35:41 +0900 Subject: [PATCH 02/60] =?UTF-8?q?=EC=83=81=ED=92=88=20=EB=93=B1=EB=A1=9D,?= =?UTF-8?q?=20=EC=83=81=ED=92=88=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 34 ++++++++++++++++++++++++++++++++++ data/mock.js | 6 ++++-- requests.http | 20 ++++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 requests.http diff --git a/app.js b/app.js index 004f1cc..ee6035a 100644 --- a/app.js +++ b/app.js @@ -1,6 +1,7 @@ import express from "express"; import mongoose from "mongoose"; import { DATABASE_URL } from "./env.js"; +import Product from "./models/product.js"; mongoose.connect(DATABASE_URL).then(() => console.log("Connected to DB")); const app = express(); @@ -22,3 +23,36 @@ const asyncHandler = (handler) => { } }; }; + +app.get( + "/products", + asyncHandler(async (req, res) => { + /** + * 쿼리 파라미터 + * - page : 페이지 번호 + * - pageSize : 페이지 당 상품 수 + * - orderBy : 정렬 기준 favorite, recent (기본값: recent) + * - keyword : 검색 키워드 + */ + const orderBy = req.query.sort; + const count = Number(req.query.count) || 0; + + const sortOption = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; + + const product = await Product.find().sort(sortOption).limit(count); + + res.send(product); + }) +); + +app.post( + "/products", + asyncHandler(async (req, res) => { + const newProduct = await Product.create(req.body); + res.status(201).send(newProduct); + }) +); + +app.listen(3000, () => { + console.log("Server is running on port 3000"); +}); diff --git a/data/mock.js b/data/mock.js index f56e1c7..be18f37 100644 --- a/data/mock.js +++ b/data/mock.js @@ -2,7 +2,7 @@ const data = [ { favoriteCount: 0, ownerId: 1, - images: ["https://example.com/..."], + images: ["https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg"], tags: ["판다인형", "인형", "판다"], price: 700000, description: "판다인형 판다", @@ -11,7 +11,9 @@ const data = [ { favoriteCount: 2, ownerId: 2, - images: ["https://example.com/..."], + images: [ + "https://view01.wemep.co.kr/wmp-product/4/879/2515748794/pm_ebifv5nrjsyf.jpg?1683280710&f=webp&w=460&h=460", + ], tags: ["판다인형", "인형", "판다"], price: 7000, description: "판다인형 안판다", diff --git a/requests.http b/requests.http new file mode 100644 index 0000000..abccb34 --- /dev/null +++ b/requests.http @@ -0,0 +1,20 @@ +GET http://localhost:3000/products + +### + +GET http://localhost:3000/products + +### + +POST http://localhost:3000/products +Content-Type: application/json + +{ + "name": "판다랑 불곰 교환원해요", + "description": "세종시청에서 교환원합니다.", + "price": 20000, + "tags": ["판다", "불곰"], + "images": ["https://www.wishbucket.io/_next/image?url=https%3A%2F%2Fd2gfz7wkiigkmv.cloudfront.net%2Fpickin%2F2%2F1%2F2%2FHereyhSJRMOmUw7I5uWAxg&w=640&q=75","https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg"], + "ownerId":1 + +} From 2f75548c7dc4f95caf60ecc2c11dce188ac0ae45 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Wed, 22 May 2024 09:17:00 +0900 Subject: [PATCH 03/60] =?UTF-8?q?=EC=8A=A4=ED=82=A4=EB=A7=88=EC=9D=98=20?= =?UTF-8?q?=ED=95=84=EB=93=9C=20=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- models/product.js | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/models/product.js b/models/product.js index 318abcc..dae54d8 100644 --- a/models/product.js +++ b/models/product.js @@ -2,40 +2,39 @@ import mongoose from "mongoose"; const ProductSchema = new mongoose.Schema( { - favoriteCount: { - type: Number, - default: 0, + name: { + type: String, + required: true, }, - ownerId: { + description: { + type: String, + }, + price: { type: Number, required: true, + default: 0, }, - - images: { + tags: { type: [String], required: true, }, - tags: { + images: { type: [String], required: true, }, - price: { + favoriteCount: { type: Number, - required: true, default: 0, }, - description: { - type: String, - }, - name: { - type: String, - required: true, - }, isFavorite: { type: Boolean, required: true, default: false, }, + ownerId: { + type: Number, + required: true, + }, }, { timestamps: true, From 75f72023e200d5c42a27c1f3f13bc5ed537ecb49 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Wed, 22 May 2024 09:40:16 +0900 Subject: [PATCH 04/60] =?UTF-8?q?=EC=83=81=ED=92=88=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C,=20=EC=83=81=ED=92=88=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 상품 목록 조회 페이지네이션 추가 --- app.js | 70 +++++++++++++++++++++++++++++++++++++++++++++++---- requests.http | 22 +++++++++++++++- 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/app.js b/app.js index ee6035a..ea246db 100644 --- a/app.js +++ b/app.js @@ -24,27 +24,59 @@ const asyncHandler = (handler) => { }; }; +//상품 목록 조회 app.get( "/products", asyncHandler(async (req, res) => { /** * 쿼리 파라미터 - * - page : 페이지 번호 - * - pageSize : 페이지 당 상품 수 + * - offset : 가져올 데이터의 시작 지점 + * - limit : 한 번에 가져올 데이터의 개수 * - orderBy : 정렬 기준 favorite, recent (기본값: recent) * - keyword : 검색 키워드 */ - const orderBy = req.query.sort; - const count = Number(req.query.count) || 0; + const offset = Number(req.query.offset) || 0; + const limit = Number(req.query.limit) || 10; + const orderBy = req.query.orderBy; + const keyword = req.query.keyword || ""; const sortOption = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; - const product = await Product.find().sort(sortOption).limit(count); + // 제목과 내용에서 키워드를 검색하는 쿼리 + const query = keyword + ? { + $or: [{ name: { $regex: keyword, $options: "i" } }, { description: { $regex: keyword, $options: "i" } }], + } + : {}; + + const products = await Product.find(query) + .select("_id name price images createdAt favoriteCount isFavorite") + .sort(sortOption) + .skip(offset) + .limit(limit); + + const totalProducts = await Product.countDocuments(query); + + res.send({ + products, + totalProducts, + currentOffset: offset, + limit: limit, + }); + }) +); + +//상품 상세 조회 +app.get( + "/products/:id", + asyncHandler(async (req, res) => { + const product = await Product.findById(req.params.id).select("-updatedAt"); res.send(product); }) ); +// 상품 등록 app.post( "/products", asyncHandler(async (req, res) => { @@ -53,6 +85,34 @@ app.post( }) ); +// 상품 수정 +app.patch( + "/products/:id", + asyncHandler(async (req, res) => { + const product = await Product.findById(req.params.id); + + if (!product) { + res.status(404).send({ message: "존재하지 않는 상품입니다." }); + return; + } + const disallowedFields = { + favoriteCount: true, + isFavorite: true, + ownerId: true, + }; + + Object.keys(req.body).forEach((key) => { + if (!disallowedFields[key]) { + product[key] = req.body[key]; + } + }); + + await product.save(); + + res.send(product); + }) +); + app.listen(3000, () => { console.log("Server is running on port 3000"); }); diff --git a/requests.http b/requests.http index abccb34..41fb525 100644 --- a/requests.http +++ b/requests.http @@ -2,7 +2,15 @@ GET http://localhost:3000/products ### -GET http://localhost:3000/products +GET http://localhost:3000/products?offset=0&limit=0&keyword=불곰 + +### + +GET http://localhost:3000/products?keyword=판다 + +### + +GET http://localhost:3000/products/664d393f71f073e051e9aaca ### @@ -16,5 +24,17 @@ Content-Type: application/json "tags": ["판다", "불곰"], "images": ["https://www.wishbucket.io/_next/image?url=https%3A%2F%2Fd2gfz7wkiigkmv.cloudfront.net%2Fpickin%2F2%2F1%2F2%2FHereyhSJRMOmUw7I5uWAxg&w=640&q=75","https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg"], "ownerId":1 +} + +### +PATCH http://localhost:3000/products/664d393f71f073e051e9aaca +Content-Type: application/json + +{ + "name":"판다 안팔려서 안판다", + "description":"안판다고 했지만 사실은 판다", + "price":7000, + "tags":["판다","안판다"] } + From 7f34ae2c03f65f6e5792c45a3650967dba6b4671 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Wed, 22 May 2024 09:52:42 +0900 Subject: [PATCH 05/60] =?UTF-8?q?=EC=83=81=ED=92=88=20=EC=82=AD=EC=A0=9C,?= =?UTF-8?q?=20=EC=A2=8B=EC=95=84=EC=9A=94,=20=EC=A2=8B=EC=95=84=EC=9A=94?= =?UTF-8?q?=20=EC=B7=A8=EC=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 71 +++++++++++++++++++++++++++++++++++++++++++++++++-- requests.http | 12 +++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index ea246db..0a00cb0 100644 --- a/app.js +++ b/app.js @@ -24,7 +24,7 @@ const asyncHandler = (handler) => { }; }; -//상품 목록 조회 +// 상품 목록 조회 app.get( "/products", asyncHandler(async (req, res) => { @@ -66,7 +66,7 @@ app.get( }) ); -//상품 상세 조회 +// 상품 상세 조회 app.get( "/products/:id", asyncHandler(async (req, res) => { @@ -113,6 +113,73 @@ app.patch( }) ); +// 상품 삭제 +app.delete( + "/products/:id", + asyncHandler(async (req, res) => { + const product = await Product.findByIdAndDelete(req.params.id); + + if (!product) { + res.status(404).send({ message: "존재하지 않는 상품입니다." }); + return; + } + + res.sendStatus(204); + }) +); + +// 상품 좋아요 +app.patch( + "/products/:id/like", + asyncHandler(async (req, res) => { + const product = await Product.findById(req.params.id); + + if (!product) { + res.status(404).send({ message: "존재하지 않는 상품입니다." }); + return; + } + + if (product.isFavorite) { + res.status(400).send({ message: "이미 좋아요 처리된 상품입니다." }); + return; + } + + product.favoriteCount += 1; + product.isFavorite = true; + + await product.save(); + + res.send(product); + }) +); + +// 상품 좋아요 취소 +app.patch( + "/products/:id/unlike", + asyncHandler(async (req, res) => { + const product = await Product.findById(req.params.id); + + if (!product) { + res.status(404).send({ message: "존재하지 않는 상품입니다." }); + return; + } + + if (!product.isFavorite) { + res.status(400).send({ message: "아직 좋아요 처리되지 않은 상품입니다." }); + return; + } + + if (product.favoriteCount > 0) { + product.favoriteCount -= 1; + } + product.isFavorite = false; + + await product.save(); + + res.send(product); + }) +); + app.listen(3000, () => { console.log("Server is running on port 3000"); }); diff --git a/requests.http b/requests.http index 41fb525..c2aae31 100644 --- a/requests.http +++ b/requests.http @@ -38,3 +38,15 @@ Content-Type: application/json "tags":["판다","안판다"] } + +### + +DELETE http://localhost:3000/products/664d393f71f073e051e9aaca + +### +PATCH http://localhost:3000/products/664d3eb1c4d678fe7647c427/like + +### + +PATCH http://localhost:3000/products/664d3eb1c4d678fe7647c427/unlike + From d5dbbdfad93b8cd7fd57bc3113382c74a12998fd Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Wed, 22 May 2024 09:57:44 +0900 Subject: [PATCH 06/60] =?UTF-8?q?=ED=99=98=EA=B2=BD=20=EB=B3=80=EC=88=98?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 10 +++++----- data/seed.js | 5 +++-- package-lock.json | 12 ++++++++++++ package.json | 1 + 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/app.js b/app.js index 0a00cb0..6b0a406 100644 --- a/app.js +++ b/app.js @@ -1,9 +1,11 @@ import express from "express"; import mongoose from "mongoose"; -import { DATABASE_URL } from "./env.js"; import Product from "./models/product.js"; -mongoose.connect(DATABASE_URL).then(() => console.log("Connected to DB")); +import * as dotenv from "dotenv"; + +dotenv.config(); +mongoose.connect(process.env.DATABASE_URL).then(() => console.log("Connected to DB")); const app = express(); app.use(express.json()); @@ -180,6 +182,4 @@ app.patch( }) ); -app.listen(3000, () => { - console.log("Server is running on port 3000"); -}); +app.listen(process.env.PORT || 3000, () => console.log("Server Started")); diff --git a/data/seed.js b/data/seed.js index 89ec145..b2fd350 100644 --- a/data/seed.js +++ b/data/seed.js @@ -1,9 +1,10 @@ +import * as dotenv from "dotenv"; import mongoose from "mongoose"; -import { DATABASE_URL } from "../env.js"; import Product from "../models/product.js"; import data from "./mock.js"; -mongoose.connect(DATABASE_URL); +dotenv.config(); +mongoose.connect(process.env.DATABASE_URL); await Product.deleteMany({}); await Product.insertMany(data); diff --git a/package-lock.json b/package-lock.json index e76448a..d6df146 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "packages": { "": { "dependencies": { + "dotenv": "^16.4.5", "express": "^4.19.2", "mongoose": "^8.4.0" }, @@ -289,6 +290,17 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", diff --git a/package.json b/package.json index e91d2bd..1dec6dd 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "dependencies": { + "dotenv": "^16.4.5", "express": "^4.19.2", "mongoose": "^8.4.0" }, From b26cab1fe6f998b9b522d6f52c4d76030c858e46 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Wed, 22 May 2024 10:23:00 +0900 Subject: [PATCH 07/60] =?UTF-8?q?cors=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 15 +++++++++++---- package-lock.json | 21 +++++++++++++++++++++ package.json | 1 + 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index 6b0a406..723b901 100644 --- a/app.js +++ b/app.js @@ -1,13 +1,17 @@ +import cors from "cors"; +import * as dotenv from "dotenv"; import express from "express"; import mongoose from "mongoose"; import Product from "./models/product.js"; -import * as dotenv from "dotenv"; - dotenv.config(); mongoose.connect(process.env.DATABASE_URL).then(() => console.log("Connected to DB")); const app = express(); - +app.use(cors()); +const corsOptions = { + origin: ["http://127.0.0.1:3000", "https://panda-market.com"], +}; +app.use(cors(corsOptions)); app.use(express.json()); const asyncHandler = (handler) => { @@ -44,7 +48,6 @@ app.get( const sortOption = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; - // 제목과 내용에서 키워드를 검색하는 쿼리 const query = keyword ? { $or: [{ name: { $regex: keyword, $options: "i" } }, { description: { $regex: keyword, $options: "i" } }], @@ -73,6 +76,10 @@ app.get( "/products/:id", asyncHandler(async (req, res) => { const product = await Product.findById(req.params.id).select("-updatedAt"); + if (!product) { + res.status(404).send({ message: "존재하지 않는 상품입니다." }); + return; + } res.send(product); }) diff --git a/package-lock.json b/package-lock.json index d6df146..0f2104d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "packages": { "": { "dependencies": { + "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", "mongoose": "^8.4.0" @@ -236,6 +237,18 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -881,6 +894,14 @@ "node": ">=0.10.0" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", diff --git a/package.json b/package.json index 1dec6dd..03de25d 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "dependencies": { + "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", "mongoose": "^8.4.0" From 3d86d6978b60db3359672063b29f8420516dea10 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Wed, 22 May 2024 15:30:33 +0900 Subject: [PATCH 08/60] =?UTF-8?q?Mongo=20DB=EB=A5=BC=20PostgreSQL=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20-=20=EC=83=81=ED=92=88=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20-=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 57 +--- http/products.http | 52 +++ package-lock.json | 299 ++++++------------ package.json | 16 +- .../20240522062619_init/migration.sql | 16 + prisma/migrations/migration_lock.toml | 3 + prisma/schema.prisma | 28 ++ 7 files changed, 212 insertions(+), 259 deletions(-) create mode 100644 http/products.http create mode 100644 prisma/migrations/20240522062619_init/migration.sql create mode 100644 prisma/migrations/migration_lock.toml create mode 100644 prisma/schema.prisma diff --git a/app.js b/app.js index 723b901..ebff140 100644 --- a/app.js +++ b/app.js @@ -1,17 +1,9 @@ -import cors from "cors"; -import * as dotenv from "dotenv"; +import { PrismaClient } from "@prisma/client"; import express from "express"; -import mongoose from "mongoose"; -import Product from "./models/product.js"; +const prisma = new PrismaClient(); -dotenv.config(); -mongoose.connect(process.env.DATABASE_URL).then(() => console.log("Connected to DB")); const app = express(); -app.use(cors()); -const corsOptions = { - origin: ["http://127.0.0.1:3000", "https://panda-market.com"], -}; -app.use(cors(corsOptions)); + app.use(express.json()); const asyncHandler = (handler) => { @@ -34,40 +26,8 @@ const asyncHandler = (handler) => { app.get( "/products", asyncHandler(async (req, res) => { - /** - * 쿼리 파라미터 - * - offset : 가져올 데이터의 시작 지점 - * - limit : 한 번에 가져올 데이터의 개수 - * - orderBy : 정렬 기준 favorite, recent (기본값: recent) - * - keyword : 검색 키워드 - */ - const offset = Number(req.query.offset) || 0; - const limit = Number(req.query.limit) || 10; - const orderBy = req.query.orderBy; - const keyword = req.query.keyword || ""; - - const sortOption = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; - - const query = keyword - ? { - $or: [{ name: { $regex: keyword, $options: "i" } }, { description: { $regex: keyword, $options: "i" } }], - } - : {}; - - const products = await Product.find(query) - .select("_id name price images createdAt favoriteCount isFavorite") - .sort(sortOption) - .skip(offset) - .limit(limit); - - const totalProducts = await Product.countDocuments(query); - - res.send({ - products, - totalProducts, - currentOffset: offset, - limit: limit, - }); + const products = await prisma.product.findMany(); + res.send(products); }) ); @@ -75,7 +35,12 @@ app.get( app.get( "/products/:id", asyncHandler(async (req, res) => { - const product = await Product.findById(req.params.id).select("-updatedAt"); + const { id } = req.params; + const product = await prisma.product.findUnique({ + where: { + id, + }, + }); if (!product) { res.status(404).send({ message: "존재하지 않는 상품입니다." }); return; diff --git a/http/products.http b/http/products.http new file mode 100644 index 0000000..2914f0c --- /dev/null +++ b/http/products.http @@ -0,0 +1,52 @@ +GET http://localhost:3000/products + +### + +GET http://localhost:3000/products?offset=0&limit=0&keyword=불곰 + +### + +GET http://localhost:3000/products?keyword=판다 + +### + +GET http://localhost:3000/products/8edc68a8-8361-4411-bb9f-dcb1a4c3d0de + +### + +POST http://localhost:3000/products +Content-Type: application/json + +{ + "name": "판다랑 불곰 교환원해요", + "description": "세종시청에서 교환원합니다.", + "price": 20000, + "tags": ["판다", "불곰"], + "images": ["https://www.wishbucket.io/_next/image?url=https%3A%2F%2Fd2gfz7wkiigkmv.cloudfront.net%2Fpickin%2F2%2F1%2F2%2FHereyhSJRMOmUw7I5uWAxg&w=640&q=75","https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg"], + "ownerId":1 +} + +### + +PATCH http://localhost:3000/products/664d393f71f073e051e9aaca +Content-Type: application/json + +{ + "name":"판다 안팔려서 안판다", + "description":"안판다고 했지만 사실은 판다", + "price":7000, + "tags":["판다","안판다"] +} + + +### + +DELETE http://localhost:3000/products/664d393f71f073e051e9aaca + +### +PATCH http://localhost:3000/products/664d3eb1c4d678fe7647c427/like + +### + +PATCH http://localhost:3000/products/664d3eb1c4d678fe7647c427/unlike + diff --git a/package-lock.json b/package-lock.json index 0f2104d..2db532a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,34 +5,73 @@ "packages": { "": { "dependencies": { - "cors": "^2.8.5", - "dotenv": "^16.4.5", - "express": "^4.19.2", - "mongoose": "^8.4.0" + "@prisma/client": "^5.4.2", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "is-email": "^1.0.2", + "is-uuid": "^1.0.2", + "prisma": "^5.4.2", + "superstruct": "^1.0.3" }, "devDependencies": { - "nodemon": "^3.1.0" + "nodemon": "^3.0.1" } }, - "node_modules/@mongodb-js/saslprep": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.7.tgz", - "integrity": "sha512-dCHW/oEX0KJ4NjDULBo3JiOaK5+6axtpBbS+ao2ZInoAL9/YRQLhXzSNAFz7hP4nzLkIqsfYAK/PDE3+XHny0Q==", + "node_modules/@prisma/client": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.14.0.tgz", + "integrity": "sha512-akMSuyvLKeoU4LeyBAUdThP/uhVP3GuLygFE3MlYzaCb3/J8SfsYBE5PkaFuLuVpLyA6sFoW+16z/aPhNAESqg==", + "hasInstallScript": true, + "engines": { + "node": ">=16.13" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/debug": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.14.0.tgz", + "integrity": "sha512-iq56qBZuFfX3fCxoxT8gBX33lQzomBU0qIUaEj1RebsKVz1ob/BVH1XSBwwwvRVtZEV1b7Fxx2eVu34Ge/mg3w==" + }, + "node_modules/@prisma/engines": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.14.0.tgz", + "integrity": "sha512-lgxkKZ6IEygVcw6IZZUlPIfLQ9hjSYAtHjZ5r64sCLDgVzsPFCi2XBBJgzPMkOQ5RHzUD4E/dVdpn9+ez8tk1A==", + "hasInstallScript": true, "dependencies": { - "sparse-bitfield": "^3.0.3" + "@prisma/debug": "5.14.0", + "@prisma/engines-version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", + "@prisma/fetch-engine": "5.14.0", + "@prisma/get-platform": "5.14.0" } }, - "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==" + "node_modules/@prisma/engines-version": { + "version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48.tgz", + "integrity": "sha512-ip6pNkRo1UxWv+6toxNcYvItNYaqQjXdFNGJ+Nuk2eYtRoEdoF13wxo7/jsClJFFenMPVNVqXQDV0oveXnR1cA==" + }, + "node_modules/@prisma/fetch-engine": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.14.0.tgz", + "integrity": "sha512-VrheA9y9DMURK5vu8OJoOgQpxOhas3qF0IBHJ8G/0X44k82kc8E0w98HCn2nhnbOOMwbWsJWXfLC2/F8n5u0gQ==", + "dependencies": { + "@prisma/debug": "5.14.0", + "@prisma/engines-version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", + "@prisma/get-platform": "5.14.0" + } }, - "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==", + "node_modules/@prisma/get-platform": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.14.0.tgz", + "integrity": "sha512-/yAyBvcEjRv41ynZrhdrPtHgk47xLRRq/o5eWGcUpBJ1YrUZTYB8EoPiopnP7iQrMATK8stXQdPOoVlrzuTQZw==", "dependencies": { - "@types/webidl-conversions": "*" + "@prisma/debug": "5.14.0" } }, "node_modules/accepts": { @@ -141,14 +180,6 @@ "node": ">=8" } }, - "node_modules/bson": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.7.0.tgz", - "integrity": "sha512-w2IquM5mYzYZv6rs3uN2DZTOBe2a0zXLj53TGDqwF4l6Sz/XsISrisXOJihArF9+BZ6Cq/GjVht7Sjfmri7ytQ==", - "engines": { - "node": ">=16.20.1" - } - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -237,22 +268,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -268,7 +288,8 @@ "node_modules/debug/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/define-data-property": { "version": "1.1.4", @@ -644,6 +665,11 @@ "node": ">=8" } }, + "node_modules/is-email": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-email/-/is-email-1.0.2.tgz", + "integrity": "sha512-UojUgD2EhDTBQ2SGKwrK9edce5phRzgLsP+V5+Uu2Swi+uvjVXgH3zduM3HhT9iaC/9Kq19/TYUbP0jPoi6ioA==" + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -674,13 +700,10 @@ "node": ">=0.12.0" } }, - "node_modules/kareem": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", - "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", - "engines": { - "node": ">=12.0.0" - } + "node_modules/is-uuid": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-uuid/-/is-uuid-1.0.2.tgz", + "integrity": "sha512-tCByphFcJgf2qmiMo5hMCgNAquNSagOetVetDvBXswGkNfoyEMvGH1yDlF8cbZbKnbVBr4Y5/rlpMz9umxyBkQ==" }, "node_modules/media-typer": { "version": "0.3.0", @@ -690,11 +713,6 @@ "node": ">= 0.6" } }, - "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==" - }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -750,100 +768,6 @@ "node": "*" } }, - "node_modules/mongodb": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.6.2.tgz", - "integrity": "sha512-ZF9Ugo2JCG/GfR7DEb4ypfyJJyiKbg5qBYKRintebj8+DNS33CyGMkWbrS9lara+u+h+yEOGSRiLhFO/g1s1aw==", - "dependencies": { - "@mongodb-js/saslprep": "^1.1.5", - "bson": "^6.7.0", - "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", - "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.1", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", - "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", - "dependencies": { - "@types/whatwg-url": "^11.0.2", - "whatwg-url": "^13.0.0" - } - }, - "node_modules/mongoose": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.4.0.tgz", - "integrity": "sha512-fgqRMwVEP1qgRYfh+tUe2YBBFnPO35FIg2lfFH+w9IhRGg1/ataWGIqvf/MjwM29cZ60D5vSnqtN2b8Qp0sOZA==", - "dependencies": { - "bson": "^6.7.0", - "kareem": "2.6.3", - "mongodb": "6.6.2", - "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==", - "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==", - "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", @@ -894,14 +818,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -946,6 +862,21 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/prisma": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.14.0.tgz", + "integrity": "sha512-gCNZco7y5XtjrnQYeDJTiVZmT/ncqCr5RY1/Cf8X2wgLRmyh9ayPAGBNziI4qEE4S6SxCH5omQLVo9lmURaJ/Q==", + "hasInstallScript": true, + "dependencies": { + "@prisma/engines": "5.14.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=16.13" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -964,14 +895,6 @@ "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", "dev": true }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, "node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -1144,11 +1067,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==" - }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", @@ -1161,14 +1079,6 @@ "node": ">=10" } }, - "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==", - "dependencies": { - "memory-pager": "^1.0.2" - } - }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -1177,6 +1087,14 @@ "node": ">= 0.8" } }, + "node_modules/superstruct": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", + "integrity": "sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1218,17 +1136,6 @@ "nodetouch": "bin/nodetouch.js" } }, - "node_modules/tr46": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", - "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", - "dependencies": { - "punycode": "^2.3.0" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -1270,26 +1177,6 @@ "engines": { "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==", - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-url": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", - "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", - "dependencies": { - "tr46": "^4.1.1", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=16" - } } } } diff --git a/package.json b/package.json index 03de25d..7d7a89b 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,19 @@ { "dependencies": { - "cors": "^2.8.5", - "dotenv": "^16.4.5", - "express": "^4.19.2", - "mongoose": "^8.4.0" + "@prisma/client": "^5.4.2", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "is-email": "^1.0.2", + "is-uuid": "^1.0.2", + "prisma": "^5.4.2", + "superstruct": "^1.0.3" }, "devDependencies": { - "nodemon": "^3.1.0" + "nodemon": "^3.0.1" }, "type": "module", "scripts": { "dev": "nodemon app.js", - "start": "node app.js", - "seed": "node data/seed.js" + "start": "node app.js" } } diff --git a/prisma/migrations/20240522062619_init/migration.sql b/prisma/migrations/20240522062619_init/migration.sql new file mode 100644 index 0000000..6a86190 --- /dev/null +++ b/prisma/migrations/20240522062619_init/migration.sql @@ -0,0 +1,16 @@ +-- CreateTable +CREATE TABLE "Product" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT NOT NULL, + "price" DOUBLE PRECISION NOT NULL, + "tags" TEXT[], + "images" TEXT[], + "favoriteCount" INTEGER NOT NULL DEFAULT 0, + "isFavorite" BOOLEAN NOT NULL DEFAULT false, + "ownerId" INTEGER NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Product_pkey" PRIMARY KEY ("id") +); diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..fbffa92 --- /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 (i.e. Git) +provider = "postgresql" \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 0000000..03d286e --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,28 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? +// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init + +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +model Product { + id String @id @default(uuid()) + name String + description String + price Float + tags String[] + images String[] + favoriteCount Int @default(0) + isFavorite Boolean @default(false) + ownerId Int + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} From 77a4ec5782e2713807c82b9b8be51b8f55fa5064 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Wed, 22 May 2024 15:36:10 +0900 Subject: [PATCH 09/60] =?UTF-8?q?=EC=83=81=ED=92=88=20=EB=93=B1=EB=A1=9D,?= =?UTF-8?q?=20=EC=83=81=ED=92=88=20=EC=88=98=EC=A0=95,=20=EC=83=81?= =?UTF-8?q?=ED=92=88=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 35 +++++++++++++++++------------------ http/products.http | 4 ++-- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/app.js b/app.js index ebff140..7bfa0d3 100644 --- a/app.js +++ b/app.js @@ -54,8 +54,10 @@ app.get( app.post( "/products", asyncHandler(async (req, res) => { - const newProduct = await Product.create(req.body); - res.status(201).send(newProduct); + const product = await prisma.product.create({ + data: req.body, + }); + res.status(201).send(product); }) ); @@ -63,25 +65,17 @@ app.post( app.patch( "/products/:id", asyncHandler(async (req, res) => { - const product = await Product.findById(req.params.id); - + const { id } = req.params; + const product = await prisma.product.update({ + where: { + id, + }, + data: req.body, + }); if (!product) { res.status(404).send({ message: "존재하지 않는 상품입니다." }); return; } - const disallowedFields = { - favoriteCount: true, - isFavorite: true, - ownerId: true, - }; - - Object.keys(req.body).forEach((key) => { - if (!disallowedFields[key]) { - product[key] = req.body[key]; - } - }); - - await product.save(); res.send(product); }) @@ -91,7 +85,12 @@ app.patch( app.delete( "/products/:id", asyncHandler(async (req, res) => { - const product = await Product.findByIdAndDelete(req.params.id); + const { id } = req.params; + const product = await prisma.product.delete({ + where: { + id, + }, + }); if (!product) { res.status(404).send({ message: "존재하지 않는 상품입니다." }); diff --git a/http/products.http b/http/products.http index 2914f0c..c56456d 100644 --- a/http/products.http +++ b/http/products.http @@ -28,7 +28,7 @@ Content-Type: application/json ### -PATCH http://localhost:3000/products/664d393f71f073e051e9aaca +PATCH http://localhost:3000/products/8edc68a8-8361-4411-bb9f-dcb1a4c3d0de Content-Type: application/json { @@ -41,7 +41,7 @@ Content-Type: application/json ### -DELETE http://localhost:3000/products/664d393f71f073e051e9aaca +DELETE http://localhost:3000/products/8edc68a8-8361-4411-bb9f-dcb1a4c3d0de ### PATCH http://localhost:3000/products/664d3eb1c4d678fe7647c427/like From 175c432b2878eddc59bea371d32a1b2275be0a2f Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Wed, 22 May 2024 15:46:27 +0900 Subject: [PATCH 10/60] =?UTF-8?q?seed=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/seed.js | 12 ------------ package.json | 3 +++ {data => prisma}/mock.js | 0 prisma/seed.js | 22 ++++++++++++++++++++++ 4 files changed, 25 insertions(+), 12 deletions(-) delete mode 100644 data/seed.js rename {data => prisma}/mock.js (100%) create mode 100644 prisma/seed.js diff --git a/data/seed.js b/data/seed.js deleted file mode 100644 index b2fd350..0000000 --- a/data/seed.js +++ /dev/null @@ -1,12 +0,0 @@ -import * as dotenv from "dotenv"; -import mongoose from "mongoose"; -import Product from "../models/product.js"; -import data from "./mock.js"; - -dotenv.config(); -mongoose.connect(process.env.DATABASE_URL); - -await Product.deleteMany({}); -await Product.insertMany(data); - -mongoose.connection.close(); diff --git a/package.json b/package.json index 7d7a89b..b61b442 100644 --- a/package.json +++ b/package.json @@ -15,5 +15,8 @@ "scripts": { "dev": "nodemon app.js", "start": "node app.js" + }, + "prisma": { + "seed": "node prisma/seed.js" } } diff --git a/data/mock.js b/prisma/mock.js similarity index 100% rename from data/mock.js rename to prisma/mock.js diff --git a/prisma/seed.js b/prisma/seed.js new file mode 100644 index 0000000..5e36868 --- /dev/null +++ b/prisma/seed.js @@ -0,0 +1,22 @@ +import { PrismaClient } from "@prisma/client"; +import data from "./mock.js"; +const prisma = new PrismaClient(); + +async function main() { + await prisma.product.deleteMany(); + + await prisma.product.createMany({ + data, + skipDuplicates: true, + }); +} + +main() + .then(async () => { + await prisma.$disconnect(); + }) + .catch(async (e) => { + console.error(e); + await prisma.$disconnect(); + process.exit(1); + }); From ca82e288df37d842203d82c100a78b175a5252b2 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Wed, 22 May 2024 16:51:30 +0900 Subject: [PATCH 11/60] =?UTF-8?q?=EC=BF=BC=EB=A6=AC=20=ED=8C=8C=EB=9D=BC?= =?UTF-8?q?=EB=AF=B8=ED=84=B0=20=EC=B2=98=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20http,=20mock=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 87 +++++++++++++++++++++++++++------------------- http/products.http | 12 +++---- models/product.js | 46 ------------------------ prisma/mock.js | 2 +- requests.http | 52 --------------------------- 5 files changed, 59 insertions(+), 140 deletions(-) delete mode 100644 models/product.js delete mode 100644 requests.http diff --git a/app.js b/app.js index 7bfa0d3..ea2f706 100644 --- a/app.js +++ b/app.js @@ -26,7 +26,36 @@ const asyncHandler = (handler) => { app.get( "/products", asyncHandler(async (req, res) => { - const products = await prisma.product.findMany(); + /** + * 쿼리 파라미터 + * - offset : 가져올 데이터의 시작 지점 + * - limit : 한 번에 가져올 데이터의 개수 + * - orderBy : 정렬 기준 favorite, recent (기본값: recent) + * - keyword : 검색 키워드 + */ + const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; + const order = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; + const products = await prisma.product.findMany({ + orderBy: order, + skip: parseInt(offset), + take: parseInt(limit), + where: { + OR: [ + { + name: { + contains: keyword, + mode: "insensitive", + }, + }, + { + description: { + contains: keyword, + mode: "insensitive", + }, + }, + ], + }, + }); res.send(products); }) ); @@ -105,22 +134,17 @@ app.delete( app.patch( "/products/:id/like", asyncHandler(async (req, res) => { - const product = await Product.findById(req.params.id); - - if (!product) { - res.status(404).send({ message: "존재하지 않는 상품입니다." }); - return; - } - - if (product.isFavorite) { - res.status(400).send({ message: "이미 좋아요 처리된 상품입니다." }); - return; - } - - product.favoriteCount += 1; - product.isFavorite = true; - - await product.save(); + const product = await prisma.product.update({ + where: { + id: req.params.id, + }, + data: { + favoriteCount: { + increment: 1, + }, + isFavorite: true, + }, + }); res.send(product); }) @@ -130,24 +154,17 @@ app.patch( app.patch( "/products/:id/unlike", asyncHandler(async (req, res) => { - const product = await Product.findById(req.params.id); - - if (!product) { - res.status(404).send({ message: "존재하지 않는 상품입니다." }); - return; - } - - if (!product.isFavorite) { - res.status(400).send({ message: "아직 좋아요 처리되지 않은 상품입니다." }); - return; - } - - if (product.favoriteCount > 0) { - product.favoriteCount -= 1; - } - product.isFavorite = false; - - await product.save(); + const product = await prisma.product.update({ + where: { + id: req.params.id, + }, + data: { + favoriteCount: { + decrement: 1, + }, + isFavorite: false, + }, + }); res.send(product); }) diff --git a/http/products.http b/http/products.http index c56456d..ee530c6 100644 --- a/http/products.http +++ b/http/products.http @@ -2,7 +2,7 @@ GET http://localhost:3000/products ### -GET http://localhost:3000/products?offset=0&limit=0&keyword=불곰 +GET http://localhost:3000/products?offset=1&limit=2&keyword=판다&orderBy=favorite ### @@ -10,7 +10,7 @@ GET http://localhost:3000/products?keyword=판다 ### -GET http://localhost:3000/products/8edc68a8-8361-4411-bb9f-dcb1a4c3d0de +GET http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7 ### @@ -28,7 +28,7 @@ Content-Type: application/json ### -PATCH http://localhost:3000/products/8edc68a8-8361-4411-bb9f-dcb1a4c3d0de +PATCH http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7 Content-Type: application/json { @@ -41,12 +41,12 @@ Content-Type: application/json ### -DELETE http://localhost:3000/products/8edc68a8-8361-4411-bb9f-dcb1a4c3d0de +DELETE http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7 ### -PATCH http://localhost:3000/products/664d3eb1c4d678fe7647c427/like +PATCH http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7/like ### -PATCH http://localhost:3000/products/664d3eb1c4d678fe7647c427/unlike +PATCH http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7/unlike diff --git a/models/product.js b/models/product.js deleted file mode 100644 index dae54d8..0000000 --- a/models/product.js +++ /dev/null @@ -1,46 +0,0 @@ -import mongoose from "mongoose"; - -const ProductSchema = new mongoose.Schema( - { - name: { - type: String, - required: true, - }, - description: { - type: String, - }, - price: { - type: Number, - required: true, - default: 0, - }, - tags: { - type: [String], - required: true, - }, - images: { - type: [String], - required: true, - }, - favoriteCount: { - type: Number, - default: 0, - }, - isFavorite: { - type: Boolean, - required: true, - default: false, - }, - ownerId: { - type: Number, - required: true, - }, - }, - { - timestamps: true, - } -); - -const Product = mongoose.model("Product", ProductSchema); - -export default Product; diff --git a/prisma/mock.js b/prisma/mock.js index be18f37..b9d8c76 100644 --- a/prisma/mock.js +++ b/prisma/mock.js @@ -1,6 +1,6 @@ const data = [ { - favoriteCount: 0, + favoriteCount: 7, ownerId: 1, images: ["https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg"], tags: ["판다인형", "인형", "판다"], diff --git a/requests.http b/requests.http deleted file mode 100644 index c2aae31..0000000 --- a/requests.http +++ /dev/null @@ -1,52 +0,0 @@ -GET http://localhost:3000/products - -### - -GET http://localhost:3000/products?offset=0&limit=0&keyword=불곰 - -### - -GET http://localhost:3000/products?keyword=판다 - -### - -GET http://localhost:3000/products/664d393f71f073e051e9aaca - -### - -POST http://localhost:3000/products -Content-Type: application/json - -{ - "name": "판다랑 불곰 교환원해요", - "description": "세종시청에서 교환원합니다.", - "price": 20000, - "tags": ["판다", "불곰"], - "images": ["https://www.wishbucket.io/_next/image?url=https%3A%2F%2Fd2gfz7wkiigkmv.cloudfront.net%2Fpickin%2F2%2F1%2F2%2FHereyhSJRMOmUw7I5uWAxg&w=640&q=75","https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg"], - "ownerId":1 -} - -### - -PATCH http://localhost:3000/products/664d393f71f073e051e9aaca -Content-Type: application/json - -{ - "name":"판다 안팔려서 안판다", - "description":"안판다고 했지만 사실은 판다", - "price":7000, - "tags":["판다","안판다"] -} - - -### - -DELETE http://localhost:3000/products/664d393f71f073e051e9aaca - -### -PATCH http://localhost:3000/products/664d3eb1c4d678fe7647c427/like - -### - -PATCH http://localhost:3000/products/664d3eb1c4d678fe7647c427/unlike - From 8000c77d46f42d1fe0eefa56a5129e38ae5318bd Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Wed, 22 May 2024 17:21:49 +0900 Subject: [PATCH 12/60] =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=20-=20=EC=A4=91=EA=B3=A0=EB=A7=88=EC=BC=93=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 79 +++++++++++++------ http/products.http | 2 + .../20240522094218_init_article/migration.sql | 14 ++++ prisma/mockArticle.js | 12 +++ prisma/schema.prisma | 12 +++ prisma/seed.js | 8 ++ structs.js | 12 +++ 7 files changed, 117 insertions(+), 22 deletions(-) create mode 100644 prisma/migrations/20240522094218_init_article/migration.sql create mode 100644 prisma/mockArticle.js create mode 100644 structs.js diff --git a/app.js b/app.js index ea2f706..3340c31 100644 --- a/app.js +++ b/app.js @@ -1,5 +1,7 @@ -import { PrismaClient } from "@prisma/client"; +import { Prisma, PrismaClient } from "@prisma/client"; import express from "express"; +import { assert } from "superstruct"; +import { CreateProduct, PatchProduct } from "./structs.js"; const prisma = new PrismaClient(); const app = express(); @@ -11,9 +13,9 @@ const asyncHandler = (handler) => { try { await handler(req, res); } catch (e) { - if (e.name === "ValidationError") { + if (e.name === "StructError" || e instanceof Prisma.PrismaClientValidationError) { res.status(400).send({ message: e.message }); - } else if (e.name === "CastError") { + } else if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") { res.status(404).send({ message: "존재하지 않는 상품입니다." }); } else { res.status(500).send({ message: "서버 에러입니다." }); @@ -65,15 +67,11 @@ app.get( "/products/:id", asyncHandler(async (req, res) => { const { id } = req.params; - const product = await prisma.product.findUnique({ + const product = await prisma.product.findUniqueOrThrow({ where: { id, }, }); - if (!product) { - res.status(404).send({ message: "존재하지 않는 상품입니다." }); - return; - } res.send(product); }) @@ -83,6 +81,7 @@ app.get( app.post( "/products", asyncHandler(async (req, res) => { + assert(req.query, CreateProduct); const product = await prisma.product.create({ data: req.body, }); @@ -94,6 +93,7 @@ app.post( app.patch( "/products/:id", asyncHandler(async (req, res) => { + assert(req.body, PatchProduct); const { id } = req.params; const product = await prisma.product.update({ where: { @@ -101,10 +101,6 @@ app.patch( }, data: req.body, }); - if (!product) { - res.status(404).send({ message: "존재하지 않는 상품입니다." }); - return; - } res.send(product); }) @@ -115,17 +111,12 @@ app.delete( "/products/:id", asyncHandler(async (req, res) => { const { id } = req.params; - const product = await prisma.product.delete({ + await prisma.product.delete({ where: { id, }, }); - if (!product) { - res.status(404).send({ message: "존재하지 않는 상품입니다." }); - return; - } - res.sendStatus(204); }) ); @@ -134,7 +125,18 @@ app.delete( app.patch( "/products/:id/like", asyncHandler(async (req, res) => { - const product = await prisma.product.update({ + const product = await prisma.product.findUniqueOrThrow({ + where: { + id: req.params.id, + }, + }); + + if (product.isFavorite) { + res.status(400).send({ message: "이미 좋아요 처리된 상품입니다." }); + return; + } + + const updatedProduct = await prisma.product.update({ where: { id: req.params.id, }, @@ -146,7 +148,7 @@ app.patch( }, }); - res.send(product); + res.send(updatedProduct); }) ); @@ -154,7 +156,18 @@ app.patch( app.patch( "/products/:id/unlike", asyncHandler(async (req, res) => { - const product = await prisma.product.update({ + const product = await prisma.product.findUniqueOrThrow({ + where: { + id: req.params.id, + }, + }); + + if (!product.isFavorite) { + res.status(400).send({ message: "아직 좋아요 처리되지 않은 상품입니다." }); + return; + } + + const updatedProduct = await prisma.product.update({ where: { id: req.params.id, }, @@ -166,7 +179,29 @@ app.patch( }, }); - res.send(product); + res.send(updatedProduct); + }) +); + +// 게시글 조회 +app.get( + "/articles", + asyncHandler(async (req, res) => { + /** + * 쿼리 파라미터 + * - offset : 가져올 데이터의 시작 지점 + * - limit : 한 번에 가져올 데이터의 개수 + * - orderBy : 정렬 기준 favorite, recent (기본값: recent) + * - keyword : 검색 키워드 + */ + const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; + const order = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; + const articles = await prisma.article.findMany({ + orderBy: order, + skip: parseInt(offset), + take: parseInt(limit), + }); + res.send(articles); }) ); diff --git a/http/products.http b/http/products.http index ee530c6..6700304 100644 --- a/http/products.http +++ b/http/products.http @@ -50,3 +50,5 @@ PATCH http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7/like PATCH http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7/unlike +### +GET http://localhost:3000/articles \ No newline at end of file diff --git a/prisma/migrations/20240522094218_init_article/migration.sql b/prisma/migrations/20240522094218_init_article/migration.sql new file mode 100644 index 0000000..78aea67 --- /dev/null +++ b/prisma/migrations/20240522094218_init_article/migration.sql @@ -0,0 +1,14 @@ +-- CreateTable +CREATE TABLE "Article" ( + "id" TEXT NOT NULL, + "title" TEXT NOT NULL, + "content" TEXT NOT NULL, + "imageUrl" TEXT, + "likeCount" INTEGER NOT NULL DEFAULT 0, + "isLiked" BOOLEAN NOT NULL DEFAULT false, + "writer" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Article_pkey" PRIMARY KEY ("id") +); diff --git a/prisma/mockArticle.js b/prisma/mockArticle.js new file mode 100644 index 0000000..2c61221 --- /dev/null +++ b/prisma/mockArticle.js @@ -0,0 +1,12 @@ +const data = [ + { + title: "판다인형 구매 후기", + content: "판다인형 구매 후기입니다.", + imageUrl: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", + likeCount: 7, + isLiked: false, + writer: "판다인형 수집가", + }, +]; + +export default data; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 03d286e..0f30792 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -26,3 +26,15 @@ model Product { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } + +model Article { + id String @id @default(uuid()) + title String + content String + imageUrl String? + likeCount Int @default(0) + isLiked Boolean @default(false) + writer String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} diff --git a/prisma/seed.js b/prisma/seed.js index 5e36868..23c5772 100644 --- a/prisma/seed.js +++ b/prisma/seed.js @@ -1,5 +1,6 @@ import { PrismaClient } from "@prisma/client"; import data from "./mock.js"; +import article from "./mockArticle.js"; const prisma = new PrismaClient(); async function main() { @@ -9,6 +10,13 @@ async function main() { data, skipDuplicates: true, }); + + await prisma.article.deleteMany(); + + await prisma.article.createMany({ + data: article, + skipDuplicates: true, + }); } main() diff --git a/structs.js b/structs.js new file mode 100644 index 0000000..4fa99f5 --- /dev/null +++ b/structs.js @@ -0,0 +1,12 @@ +import * as s from "superstruct"; + +export const CreateProduct = s.object({ + ownerId: s.number(), + images: s.array(s.string()), + tags: s.array(s.string()), + price: s.refine(s.number(), (price) => price > 0 && price < 1000000000), + description: s.string(), + name: s.string(), +}); + +export const PatchProduct = s.partial(CreateProduct); From 16a5a58ffaa40a0df1170843c68c34e4c8caa82a Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 23 May 2024 08:08:40 +0900 Subject: [PATCH 13/60] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=A1=B0=ED=9A=8C,=20=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=20=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 66 +++++++++++++++++++++++++++++++++++++++---- http/articles.http | 8 ++++++ http/products.http | 19 +++++++------ prisma/mockArticle.js | 16 +++++++++++ 4 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 http/articles.http diff --git a/app.js b/app.js index 3340c31..a14b669 100644 --- a/app.js +++ b/app.js @@ -72,7 +72,6 @@ app.get( id, }, }); - res.send(product); }) ); @@ -183,7 +182,7 @@ app.patch( }) ); -// 게시글 조회 +// 게시글 목록 조회 app.get( "/articles", asyncHandler(async (req, res) => { @@ -191,17 +190,72 @@ app.get( * 쿼리 파라미터 * - offset : 가져올 데이터의 시작 지점 * - limit : 한 번에 가져올 데이터의 개수 - * - orderBy : 정렬 기준 favorite, recent (기본값: recent) - * - keyword : 검색 키워드 + * - orderBy : 정렬 기준 like, recent (기본값: recent) */ const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; - const order = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; + const order = orderBy === "like" ? { likeCount: "desc" } : { createdAt: "desc" }; const articles = await prisma.article.findMany({ + select: { + id: true, + title: true, + content: true, + imageUrl: true, + createdAt: true, + writer: true, + }, orderBy: order, skip: parseInt(offset), take: parseInt(limit), + where: { + OR: [ + { + title: { + contains: keyword, + mode: "insensitive", + }, + }, + { + content: { + contains: keyword, + mode: "insensitive", + }, + }, + ], + }, + }); + // 좋아요가 많은 상위 4개의 글 조회 + const bestArticles = await prisma.article.findMany({ + orderBy: { + likeCount: "desc", + }, + take: 4, + }); + + res.send({ articles, bestArticles }); + }) +); + +// 게시글 상세 조회 +app.get( + "/articles/:id", + asyncHandler(async (req, res) => { + const { id } = req.params; + const article = await prisma.article.findUniqueOrThrow({ + where: { + id, + }, + select: { + id: true, + title: true, + content: true, + imageUrl: true, + createdAt: true, + likeCount: true, + isLiked: true, + writer: true, + }, }); - res.send(articles); + res.send(article); }) ); diff --git a/http/articles.http b/http/articles.http new file mode 100644 index 0000000..78651d2 --- /dev/null +++ b/http/articles.http @@ -0,0 +1,8 @@ +# 게시글 목록 조회 +GET http://localhost:3000/articles?&limit=10&&orderBy=like + +### +# 게시글 상세 조회 + +GET http://localhost:3000/articles/b66f0adf-0bc1-4bf7-a8bb-6fc8141fa56d + diff --git a/http/products.http b/http/products.http index 6700304..610fcb3 100644 --- a/http/products.http +++ b/http/products.http @@ -1,19 +1,22 @@ + +# 상품 조회 쿼리 x GET http://localhost:3000/products ### +# 상품 조회 쿼리 o GET http://localhost:3000/products?offset=1&limit=2&keyword=판다&orderBy=favorite ### - +# 상품 조회 검색어 테스트 GET http://localhost:3000/products?keyword=판다 ### - +# 상품 상세 조회 GET http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7 ### - +# 상품 등록 POST http://localhost:3000/products Content-Type: application/json @@ -27,7 +30,7 @@ Content-Type: application/json } ### - +# 상품 수정 PATCH http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7 Content-Type: application/json @@ -38,17 +41,15 @@ Content-Type: application/json "tags":["판다","안판다"] } - ### - +# 상품 삭제 DELETE http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7 ### +# 상품 좋아요 PATCH http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7/like ### - +# 상품 좋아요 취소 PATCH http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7/unlike -### -GET http://localhost:3000/articles \ No newline at end of file diff --git a/prisma/mockArticle.js b/prisma/mockArticle.js index 2c61221..54630c3 100644 --- a/prisma/mockArticle.js +++ b/prisma/mockArticle.js @@ -7,6 +7,22 @@ const data = [ isLiked: false, writer: "판다인형 수집가", }, + { + title: "판다인형 판매 후기", + content: "판다인형 판매 후기입니다.", + imageUrl: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", + likeCount: 2, + isLiked: true, + writer: "판다인형 중개인", + }, + { + title: "불곰인형 구하는 곳 아시는분", + content: "불곰인형 구하는 곳 아시는분 계신가요?", + imageUrl: "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg", + likeCount: 3, + isLiked: false, + writer: "불곰인형 수집가", + }, ]; export default data; From 30b29804f8c67c3ad94dc35133084fb4bf5ec25e Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 23 May 2024 08:28:47 +0900 Subject: [PATCH 14/60] =?UTF-8?q?=EC=83=81=ED=92=88=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?=20api=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 5 ++--- structs.js | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index a14b669..7fd7f10 100644 --- a/app.js +++ b/app.js @@ -2,10 +2,9 @@ import { Prisma, PrismaClient } from "@prisma/client"; import express from "express"; import { assert } from "superstruct"; import { CreateProduct, PatchProduct } from "./structs.js"; -const prisma = new PrismaClient(); +const prisma = new PrismaClient(); const app = express(); - app.use(express.json()); const asyncHandler = (handler) => { @@ -80,7 +79,7 @@ app.get( app.post( "/products", asyncHandler(async (req, res) => { - assert(req.query, CreateProduct); + assert(req.body, CreateProduct); const product = await prisma.product.create({ data: req.body, }); diff --git a/structs.js b/structs.js index 4fa99f5..ab716f8 100644 --- a/structs.js +++ b/structs.js @@ -1,10 +1,12 @@ import * as s from "superstruct"; +const PositivePrice = s.refine(s.number(), "PositivePrice", (value) => value > 0 && value < 1000000000); + export const CreateProduct = s.object({ ownerId: s.number(), images: s.array(s.string()), tags: s.array(s.string()), - price: s.refine(s.number(), (price) => price > 0 && price < 1000000000), + price: PositivePrice, description: s.string(), name: s.string(), }); From ee6daef67f45c7a57534dffae7a770e907a08145 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 23 May 2024 08:46:08 +0900 Subject: [PATCH 15/60] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D,=20=EC=88=98=EC=A0=95,=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 48 ++++++++++++++++++++++++++++++++++++++++++++-- http/articles.http | 25 ++++++++++++++++++++++++ structs.js | 7 +++++++ 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 7fd7f10..f9b6758 100644 --- a/app.js +++ b/app.js @@ -1,7 +1,7 @@ import { Prisma, PrismaClient } from "@prisma/client"; import express from "express"; import { assert } from "superstruct"; -import { CreateProduct, PatchProduct } from "./structs.js"; +import { CreateArticle, CreateProduct, PatchArticle, PatchProduct } from "./structs.js"; const prisma = new PrismaClient(); const app = express(); @@ -15,7 +15,7 @@ const asyncHandler = (handler) => { if (e.name === "StructError" || e instanceof Prisma.PrismaClientValidationError) { res.status(400).send({ message: e.message }); } else if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") { - res.status(404).send({ message: "존재하지 않는 상품입니다." }); + res.status(404).send({ message: "존재하지 않는 게시글입니다." }); } else { res.status(500).send({ message: "서버 에러입니다." }); } @@ -258,4 +258,48 @@ app.get( }) ); +// 게시글 등록 +app.post( + "/articles", + asyncHandler(async (req, res) => { + assert(req.body, CreateArticle); + const article = await prisma.article.create({ + data: req.body, + }); + res.status(201).send(article); + }) +); + +// 게시글 수정 +app.patch( + "/articles/:id", + asyncHandler(async (req, res) => { + assert(req.body, PatchArticle); + const { id } = req.params; + const article = await prisma.article.update({ + where: { + id, + }, + data: req.body, + }); + + res.send(article); + }) +); + +// 게시글 삭제 +app.delete( + "/articles/:id", + asyncHandler(async (req, res) => { + const { id } = req.params; + await prisma.article.delete({ + where: { + id, + }, + }); + + res.sendStatus(204); + }) +); + app.listen(process.env.PORT || 3000, () => console.log("Server Started")); diff --git a/http/articles.http b/http/articles.http index 78651d2..0b128a4 100644 --- a/http/articles.http +++ b/http/articles.http @@ -6,3 +6,28 @@ GET http://localhost:3000/articles?&limit=10&&orderBy=like GET http://localhost:3000/articles/b66f0adf-0bc1-4bf7-a8bb-6fc8141fa56d +### +# 게시글 등록 +POST http://localhost:3000/articles +Content-Type: application/json + +{ + "title": "제가 아끼는 티모 인형입니다", + "content": "버섯 농사 짓는 모습이 너무 깜찍하지않나요?", + "imageUrl": "https://cdn.011st.com/11dims/resize/600x600/quality/75/11src/product/5575072075/B.jpg?51000000", + "writer": "티모매니아" +} + +### +# 게시글 수정 +PATCH http://localhost:3000/articles/7a640d97-ba35-4bae-bf9e-b6f30bf0ebb0 +Content-Type: application/json + +{ + "title":"판다 대박이네요", + "content":"대나무를 잘 먹네요 ㄷㄷ" +} + +### +# 게시글 삭제 +DELETE http://localhost:3000/articles/7a640d97-ba35-4bae-bf9e-b6f30bf0ebb0 diff --git a/structs.js b/structs.js index ab716f8..b550f0e 100644 --- a/structs.js +++ b/structs.js @@ -12,3 +12,10 @@ export const CreateProduct = s.object({ }); export const PatchProduct = s.partial(CreateProduct); + +export const CreateArticle = s.object({ + title: s.string(), + content: s.string(), +}); + +export const PatchArticle = s.partial(CreateArticle); From d632f32471f1275a1a96ac1c90f527caf8223700 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 23 May 2024 08:56:24 +0900 Subject: [PATCH 16/60] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=A2=8B?= =?UTF-8?q?=EC=95=84=EC=9A=94,=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EC=B7=A8?= =?UTF-8?q?=EC=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 62 ++++++++++++++++++++++++++++++++++++++++++++++ http/articles.http | 9 +++++++ 2 files changed, 71 insertions(+) diff --git a/app.js b/app.js index f9b6758..8f98a0f 100644 --- a/app.js +++ b/app.js @@ -302,4 +302,66 @@ app.delete( }) ); +// 게시글 좋아요 +app.patch( + "/articles/:id/like", + asyncHandler(async (req, res) => { + const article = await prisma.article.findUniqueOrThrow({ + where: { + id: req.params.id, + }, + }); + + if (article.isLiked) { + res.status(400).send({ message: "이미 좋아요 처리된 게시글입니다." }); + return; + } + + const updatedArticle = await prisma.article.update({ + where: { + id: req.params.id, + }, + data: { + likeCount: { + increment: 1, + }, + isLiked: true, + }, + }); + + res.send(updatedArticle); + }) +); + +// 게시글 좋아요 취소 +app.patch( + "/articles/:id/unlike", + asyncHandler(async (req, res) => { + const article = await prisma.article.findUniqueOrThrow({ + where: { + id: req.params.id, + }, + }); + + if (!article.isLiked) { + res.status(400).send({ message: "아직 좋아요 처리되지 않은 게시글입니다." }); + return; + } + + const updatedArticle = await prisma.article.update({ + where: { + id: req.params.id, + }, + data: { + likeCount: { + decrement: 1, + }, + isLiked: false, + }, + }); + + res.send(updatedArticle); + }) +); + app.listen(process.env.PORT || 3000, () => console.log("Server Started")); diff --git a/http/articles.http b/http/articles.http index 0b128a4..37bcd07 100644 --- a/http/articles.http +++ b/http/articles.http @@ -31,3 +31,12 @@ Content-Type: application/json ### # 게시글 삭제 DELETE http://localhost:3000/articles/7a640d97-ba35-4bae-bf9e-b6f30bf0ebb0 + +### +# 게시글 좋아요 +PATCH http://localhost:3000/articles/7757f3a4-0075-47e0-a9e5-b38500948b8e/like + +### +# 게시글 좋아요 취소 +PATCH http://localhost:3000/articles/7757f3a4-0075-47e0-a9e5-b38500948b8e/unlike + From 883250b00207cb1acde3b608509c3540a0d26402 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 23 May 2024 09:38:53 +0900 Subject: [PATCH 17/60] =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EB=AA=A8=EB=8D=B8,?= =?UTF-8?q?=20seed,=20mock=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../20240523002157_init_comment/migration.sql | 24 ++++++++ prisma/mock.js | 55 ++++++++++++++++++- prisma/mockArticle.js | 28 ---------- prisma/schema.prisma | 33 ++++++++--- prisma/seed.js | 13 +++-- 5 files changed, 111 insertions(+), 42 deletions(-) create mode 100644 prisma/migrations/20240523002157_init_comment/migration.sql delete mode 100644 prisma/mockArticle.js diff --git a/prisma/migrations/20240523002157_init_comment/migration.sql b/prisma/migrations/20240523002157_init_comment/migration.sql new file mode 100644 index 0000000..645652d --- /dev/null +++ b/prisma/migrations/20240523002157_init_comment/migration.sql @@ -0,0 +1,24 @@ +-- CreateTable +CREATE TABLE "Comment" ( + "id" TEXT NOT NULL, + "content" TEXT NOT NULL, + "writer" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "productId" TEXT, + "articleId" TEXT, + + CONSTRAINT "Comment_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE INDEX "Comment_productId_idx" ON "Comment"("productId"); + +-- CreateIndex +CREATE INDEX "Comment_articleId_idx" ON "Comment"("articleId"); + +-- AddForeignKey +ALTER TABLE "Comment" ADD CONSTRAINT "Comment_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Comment" ADD CONSTRAINT "Comment_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "Article"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/mock.js b/prisma/mock.js index b9d8c76..43c170d 100644 --- a/prisma/mock.js +++ b/prisma/mock.js @@ -1,5 +1,6 @@ -const data = [ +export const PRODUCTS = [ { + id: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", favoriteCount: 7, ownerId: 1, images: ["https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg"], @@ -9,6 +10,7 @@ const data = [ name: "판다인형", }, { + id: "d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9", favoriteCount: 2, ownerId: 2, images: [ @@ -21,4 +23,53 @@ const data = [ }, ]; -export default data; +export const ARTICLES = [ + { + id: "2c027764-d7ef-4a94-8399-f15ffbf8f4da", + title: "판다인형 구매 후기", + content: "판다인형 구매 후기입니다.", + imageUrl: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", + likeCount: 7, + isLiked: false, + writer: "판다인형 수집가", + }, + { + id: "7c8b9d2e-5d45-4c9f-9b4b-7626f3c9c9a9", + title: "판다인형 판매 후기", + content: "판다인형 판매 후기입니다.", + imageUrl: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", + likeCount: 2, + isLiked: true, + writer: "판다인형 중개인", + }, + { + id: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", + title: "불곰인형 구하는 곳 아시는분", + content: "불곰인형 구하는 곳 아시는분 계신가요?", + imageUrl: "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg", + likeCount: 3, + isLiked: false, + writer: "불곰인형 수집가", + }, +]; + +export const COMMENTS = [ + { + id: "1a2b3c4d-5e6f-7g8h-9i0j-1k2l3m4n5o6p", + content: "판다인형 너무 귀여워요!", + writer: "판다인형 수집가", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, + { + id: "2b3c4d5e-6f7g-8h9i-0j1k-2l3m4n5o6p7q", + content: "판다인형 너무 귀여워요!", + writer: "판다인형 중개인", + articleId: "2c027764-d7ef-4a94-8399-f15ffbf8f4da", + }, + { + id: "3c4d5e6f-7g8h-9i0j-1k2l-3m4n5o6p7q8r", + content: "불곰인형 너무 귀여워요!", + writer: "불곰인형 수집가", + articleId: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", + }, +]; diff --git a/prisma/mockArticle.js b/prisma/mockArticle.js deleted file mode 100644 index 54630c3..0000000 --- a/prisma/mockArticle.js +++ /dev/null @@ -1,28 +0,0 @@ -const data = [ - { - title: "판다인형 구매 후기", - content: "판다인형 구매 후기입니다.", - imageUrl: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", - likeCount: 7, - isLiked: false, - writer: "판다인형 수집가", - }, - { - title: "판다인형 판매 후기", - content: "판다인형 판매 후기입니다.", - imageUrl: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", - likeCount: 2, - isLiked: true, - writer: "판다인형 중개인", - }, - { - title: "불곰인형 구하는 곳 아시는분", - content: "불곰인형 구하는 곳 아시는분 계신가요?", - imageUrl: "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg", - likeCount: 3, - isLiked: false, - writer: "불곰인형 수집가", - }, -]; - -export default data; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 0f30792..4b24178 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -14,27 +14,44 @@ datasource db { } model Product { - id String @id @default(uuid()) + id String @id @default(uuid()) name String description String price Float tags String[] images String[] - favoriteCount Int @default(0) - isFavorite Boolean @default(false) + favoriteCount Int @default(0) + isFavorite Boolean @default(false) ownerId Int - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comments Comment[] } model Article { - id String @id @default(uuid()) + id String @id @default(uuid()) title String content String imageUrl String? - likeCount Int @default(0) - isLiked Boolean @default(false) + likeCount Int @default(0) + isLiked Boolean @default(false) + writer String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comments Comment[] +} + +model Comment { + id String @id @default(uuid()) + content String writer String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt + product Product? @relation(fields: [productId], references: [id], onDelete: SetNull) + productId String? + article Article? @relation(fields: [articleId], references: [id], onDelete: SetNull) + articleId String? + + @@index([productId]) + @@index([articleId]) } diff --git a/prisma/seed.js b/prisma/seed.js index 23c5772..92f7f42 100644 --- a/prisma/seed.js +++ b/prisma/seed.js @@ -1,20 +1,25 @@ import { PrismaClient } from "@prisma/client"; -import data from "./mock.js"; -import article from "./mockArticle.js"; +import { ARTICLES, COMMENTS, PRODUCTS } from "./mock.js"; const prisma = new PrismaClient(); async function main() { await prisma.product.deleteMany(); await prisma.product.createMany({ - data, + data: PRODUCTS, skipDuplicates: true, }); await prisma.article.deleteMany(); await prisma.article.createMany({ - data: article, + data: ARTICLES, + skipDuplicates: true, + }); + await prisma.comment.deleteMany(); + + await prisma.comment.createMany({ + data: COMMENTS, skipDuplicates: true, }); } From fe528aa9633fb92df3a301684e4d732c8f0c3e95 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 23 May 2024 10:06:42 +0900 Subject: [PATCH 18/60] =?UTF-8?q?=EC=A4=91=EA=B3=A0=EB=A7=88=EC=BC=93=20?= =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C,?= =?UTF-8?q?=20=EB=93=B1=EB=A1=9D,=20=EC=88=98=EC=A0=95,=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 86 ++++++++++++++++++++++++++++++++++++++++++++++ http/products.http | 30 ++++++++++++++++ prisma/mock.js | 61 ++++++++++++++++++++++++++++++-- 3 files changed, 174 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index 8f98a0f..0fc92e2 100644 --- a/app.js +++ b/app.js @@ -364,4 +364,90 @@ app.patch( }) ); +// 중고마켓 댓글 목록 조회 +app.get( + "/products/:id/comments", + asyncHandler(async (req, res) => { + const { id } = req.params; + const { cursor } = req.query; + console.log(cursor); + let queryOptions = { + take: 10, + orderBy: { + createdAt: "desc", + }, + where: { + productId: id, + }, + select: { + id: true, + content: true, + createdAt: true, + writer: true, + }, + }; + + if (cursor) { + queryOptions = { + ...queryOptions, + cursor: { + id: cursor, + }, + skip: 1, + }; + } + + const comments = await prisma.comment.findMany(queryOptions); + res.send(comments); + }) +); + +// 중고마켓 댓글 등록 +app.post( + "/products/:id/comments", + asyncHandler(async (req, res) => { + const { id, cursor } = req.params; + + const comment = await prisma.comment.create({ + data: { + content: req.body.content, + writer: req.body.writer, + productId: id, + }, + }); + res.status(201).send(comment); + }) +); + +// 중고마켓 댓글 수정 +app.patch( + "/products/:id/comments/:commentId", + asyncHandler(async (req, res) => { + const { commentId } = req.params; + const comment = await prisma.comment.update({ + where: { + id: commentId, + }, + data: req.body, + }); + + res.send(comment); + }) +); + +// 중고마켓 댓글 삭제 +app.delete( + "/products/:id/comments/:commentId", + asyncHandler(async (req, res) => { + const { commentId } = req.params; + await prisma.comment.delete({ + where: { + id: commentId, + }, + }); + + res.sendStatus(204); + }) +); + app.listen(process.env.PORT || 3000, () => console.log("Server Started")); diff --git a/http/products.http b/http/products.http index 610fcb3..36dcd96 100644 --- a/http/products.http +++ b/http/products.http @@ -53,3 +53,33 @@ PATCH http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7/like # 상품 좋아요 취소 PATCH http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7/unlike +### +# 상품 댓글 조회 +GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments + +### +# 상품 댓글 커서 조회 +GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments?cursor=c45c56cf-d7d4-4592-885c-abcb56661bb5 + +### +# 상품 댓글 등록 +POST http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments +Content-Type: application/json + +{ + "content":"판다가 너무 귀여워요", + "writer":"판다사랑나라사랑" +} + +### +# 상품 댓글 수정 +PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/512b432b-7618-46ea-a500-579daacc0d02 +Content-Type: application/json + +{ + "content":"판다가 너무 귀여워요 수정" +} + +### +# 상품 댓글 삭제 +DELETE http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/512b432b-7618-46ea-a500-579daacc0d02 \ No newline at end of file diff --git a/prisma/mock.js b/prisma/mock.js index 43c170d..64ec75a 100644 --- a/prisma/mock.js +++ b/prisma/mock.js @@ -58,13 +58,68 @@ export const COMMENTS = [ id: "1a2b3c4d-5e6f-7g8h-9i0j-1k2l3m4n5o6p", content: "판다인형 너무 귀여워요!", writer: "판다인형 수집가", - productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + articleId: "2c027764-d7ef-4a94-8399-f15ffbf8f4da", }, { id: "2b3c4d5e-6f7g-8h9i-0j1k-2l3m4n5o6p7q", - content: "판다인형 너무 귀여워요!", + content: "판다인형 너무 귀여워요1", writer: "판다인형 중개인", - articleId: "2c027764-d7ef-4a94-8399-f15ffbf8f4da", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, + { + content: "판다인형 너무 귀여워요2", + writer: "판다인형 중개인", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, + { + content: "판다인형 너무 귀여워요3", + writer: "판다인형 중개인", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, + { + content: "판다인형 너무 귀여워요4", + writer: "판다인형 중개인", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, + { + content: "판다인형 너무 귀여워요5", + writer: "판다인형 중개인", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, + { + content: "판다인형 너무 귀여워요6", + writer: "판다인형 중개인", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, + { + content: "판다인형 너무 귀여워요7", + writer: "판다인형 중개인", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, + { + content: "판다인형 너무 귀여워요8", + writer: "판다인형 중개인", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, + { + content: "판다인형 너무 귀여워요9", + writer: "판다인형 중개인", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, + { + content: "판다인형 너무 귀여워요10", + writer: "판다인형 중개인", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, + { + content: "판다인형 너무 귀여워요11", + writer: "판다인형 중개인", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, + { + content: "판다인형 너무 귀여워요12", + writer: "판다인형 중개인", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", }, { id: "3c4d5e6f-7g8h-9i0j-1k2l-3m4n5o6p7q8r", From 2de35b2aac43e865b7c0f91ac4a8db8379a99384 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 23 May 2024 11:39:52 +0900 Subject: [PATCH 19/60] =?UTF-8?q?=EC=9E=90=EC=9C=A0=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=ED=8C=90=20=EB=8C=93=EA=B8=80=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C,=20=EB=93=B1=EB=A1=9D,=20=EC=88=98=EC=A0=95,=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 96 +++++++++++++++++++++++++++++++++++++++++++--- http/articles.http | 35 ++++++++++++++++- structs.js | 7 ++++ 3 files changed, 132 insertions(+), 6 deletions(-) diff --git a/app.js b/app.js index 0fc92e2..1a02c69 100644 --- a/app.js +++ b/app.js @@ -1,7 +1,7 @@ import { Prisma, PrismaClient } from "@prisma/client"; import express from "express"; import { assert } from "superstruct"; -import { CreateArticle, CreateProduct, PatchArticle, PatchProduct } from "./structs.js"; +import { CreateArticle, CreateComment, CreateProduct, PatchArticle, PatchComment, PatchProduct } from "./structs.js"; const prisma = new PrismaClient(); const app = express(); @@ -370,7 +370,6 @@ app.get( asyncHandler(async (req, res) => { const { id } = req.params; const { cursor } = req.query; - console.log(cursor); let queryOptions = { take: 10, orderBy: { @@ -406,12 +405,12 @@ app.get( app.post( "/products/:id/comments", asyncHandler(async (req, res) => { - const { id, cursor } = req.params; + assert(req.body, CreateComment); + const { id } = req.params; const comment = await prisma.comment.create({ data: { - content: req.body.content, - writer: req.body.writer, + ...req.body, productId: id, }, }); @@ -423,6 +422,7 @@ app.post( app.patch( "/products/:id/comments/:commentId", asyncHandler(async (req, res) => { + assert(req.body, PatchComment); const { commentId } = req.params; const comment = await prisma.comment.update({ where: { @@ -450,4 +450,90 @@ app.delete( }) ); +// 자유게시판 댓글 목록 조회 +app.get( + "/articles/:id/comments", + asyncHandler(async (req, res) => { + const { id } = req.params; + const { cursor } = req.query; + let queryOptions = { + take: 10, + orderBy: { + createdAt: "desc", + }, + where: { + articleId: id, + }, + select: { + id: true, + content: true, + createdAt: true, + writer: true, + }, + }; + + if (cursor) { + queryOptions = { + ...queryOptions, + cursor: { + id: cursor, + }, + skip: 1, + }; + } + + const comments = await prisma.comment.findMany(queryOptions); + res.send(comments); + }) +); + +// 자유게시판 댓글 등록 +app.post( + "/articles/:id/comments", + asyncHandler(async (req, res) => { + assert(req.body, CreateComment); + const { id } = req.params; + + const comment = await prisma.comment.create({ + data: { + ...req.body, + articleId: id, + }, + }); + res.status(201).send(comment); + }) +); + +// 자유게시판 댓글 수정 +app.patch( + "/articles/:id/comments/:commentId", + asyncHandler(async (req, res) => { + assert(req.body, PatchComment); + const { commentId } = req.params; + const comment = await prisma.comment.update({ + where: { + id: commentId, + }, + data: req.body, + }); + + res.send(comment); + }) +); + +// 중고마켓 댓글 삭제 +app.delete( + "/articles/:id/comments/:commentId", + asyncHandler(async (req, res) => { + const { commentId } = req.params; + await prisma.comment.delete({ + where: { + id: commentId, + }, + }); + + res.sendStatus(204); + }) +); + app.listen(process.env.PORT || 3000, () => console.log("Server Started")); diff --git a/http/articles.http b/http/articles.http index 37bcd07..8b518af 100644 --- a/http/articles.http +++ b/http/articles.http @@ -30,7 +30,7 @@ Content-Type: application/json ### # 게시글 삭제 -DELETE http://localhost:3000/articles/7a640d97-ba35-4bae-bf9e-b6f30bf0ebb0 +DELETE http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da ### # 게시글 좋아요 @@ -40,3 +40,36 @@ PATCH http://localhost:3000/articles/7757f3a4-0075-47e0-a9e5-b38500948b8e/like # 게시글 좋아요 취소 PATCH http://localhost:3000/articles/7757f3a4-0075-47e0-a9e5-b38500948b8e/unlike + + + +### +# 자유게시판 댓글 조회 +GET http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/comments + +### +# 자유게시판 댓글 커서 조회 +GET http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/comments?cursor=43d35ef2-42f0-43be-b85c-f9614195bb39 + +### +# 자유게시판 댓글 등록 +POST http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments +Content-Type: application/json + +{ + "content":"판다가 너무 귀여워요2", + "writer":"판다사랑나라사랑" +} + +### +# 자유게시판 댓글 수정 +PATCH http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/comments/3c94cbe4-bd70-4c32-969a-225af0dd1e20 +Content-Type: application/json + +{ + "content":"판다가 너무 귀여워요 수정" +} + +### +# 자유게시판 댓글 삭제 +DELETE http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/comments/3c94cbe4-bd70-4c32-969a-225af0dd1e20 \ No newline at end of file diff --git a/structs.js b/structs.js index b550f0e..1050ee2 100644 --- a/structs.js +++ b/structs.js @@ -19,3 +19,10 @@ export const CreateArticle = s.object({ }); export const PatchArticle = s.partial(CreateArticle); + +export const CreateComment = s.object({ + content: s.string(), + writer: s.string(), +}); + +export const PatchComment = s.partial(CreateComment); From 4d09d8c3d0a0e206749db3f30c31d6166c04d19a Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 23 May 2024 14:48:32 +0900 Subject: [PATCH 20/60] =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=9C=A0?= =?UTF-8?q?=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC,=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index 1a02c69..55feaa0 100644 --- a/app.js +++ b/app.js @@ -12,12 +12,19 @@ const asyncHandler = (handler) => { try { await handler(req, res); } catch (e) { - if (e.name === "StructError" || e instanceof Prisma.PrismaClientValidationError) { - res.status(400).send({ message: e.message }); + if (e.name === "StructError") { + const errors = e.failures().map((failure) => ({ + path: failure.path.join("."), + message: failure.message, + })); + res.status(400).json({ message: "유효성 검사 오류입니다.", errors }); + } else if (e instanceof Prisma.PrismaClientValidationError) { + res.status(400).json({ message: e.message }); } else if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") { - res.status(404).send({ message: "존재하지 않는 게시글입니다." }); + res.status(404).json({ message: "존재하지 않는 게시글입니다." }); } else { - res.status(500).send({ message: "서버 에러입니다." }); + console.error(e); + res.status(500).json({ message: "서버 에러입니다." }); } } }; From 5e3948a9ce0f8e0c9e00585c360fd9aa8b03cb0d Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 23 May 2024 16:20:39 +0900 Subject: [PATCH 21/60] =?UTF-8?q?writer=20=ED=95=84=EB=93=9C=EB=A5=BC=20op?= =?UTF-8?q?tional=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- http/articles.http | 22 +++++++++---------- http/products.http | 16 +++++++------- .../migration.sql | 6 +++++ prisma/mock.js | 16 ++++++++++++++ prisma/schema.prisma | 6 ++--- structs.js | 4 +++- 6 files changed, 46 insertions(+), 24 deletions(-) create mode 100644 prisma/migrations/20240523072342_change_writer_to_optional/migration.sql diff --git a/http/articles.http b/http/articles.http index 8b518af..ad5c723 100644 --- a/http/articles.http +++ b/http/articles.http @@ -4,7 +4,7 @@ GET http://localhost:3000/articles?&limit=10&&orderBy=like ### # 게시글 상세 조회 -GET http://localhost:3000/articles/b66f0adf-0bc1-4bf7-a8bb-6fc8141fa56d +GET http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da ### # 게시글 등록 @@ -14,13 +14,12 @@ Content-Type: application/json { "title": "제가 아끼는 티모 인형입니다", "content": "버섯 농사 짓는 모습이 너무 깜찍하지않나요?", - "imageUrl": "https://cdn.011st.com/11dims/resize/600x600/quality/75/11src/product/5575072075/B.jpg?51000000", - "writer": "티모매니아" + "imageUrl": "https://cdn.011st.com/11dims/resize/600x600/quality/75/11src/product/5575072075/B.jpg?51000000" } ### # 게시글 수정 -PATCH http://localhost:3000/articles/7a640d97-ba35-4bae-bf9e-b6f30bf0ebb0 +PATCH http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da Content-Type: application/json { @@ -34,22 +33,22 @@ DELETE http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da ### # 게시글 좋아요 -PATCH http://localhost:3000/articles/7757f3a4-0075-47e0-a9e5-b38500948b8e/like +PATCH http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/like ### # 게시글 좋아요 취소 -PATCH http://localhost:3000/articles/7757f3a4-0075-47e0-a9e5-b38500948b8e/unlike +PATCH http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/unlike ### # 자유게시판 댓글 조회 -GET http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/comments +GET http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments ### # 자유게시판 댓글 커서 조회 -GET http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/comments?cursor=43d35ef2-42f0-43be-b85c-f9614195bb39 +GET http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments?cursor=4f9cd26c-09fa-441c-997f-2fdec0fb443e ### # 자유게시판 댓글 등록 @@ -57,13 +56,12 @@ POST http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comment Content-Type: application/json { - "content":"판다가 너무 귀여워요2", - "writer":"판다사랑나라사랑" + "content":"판다가 너무 귀여워요2" } ### # 자유게시판 댓글 수정 -PATCH http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/comments/3c94cbe4-bd70-4c32-969a-225af0dd1e20 +PATCH http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments/1a2b3c4d-5e6f-7g8h-9i0j-1k2l3m4n5o6p Content-Type: application/json { @@ -72,4 +70,4 @@ Content-Type: application/json ### # 자유게시판 댓글 삭제 -DELETE http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/comments/3c94cbe4-bd70-4c32-969a-225af0dd1e20 \ No newline at end of file +DELETE http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments/1a2b3c4d-5e6f-7g8h-9i0j-1k2l3m4n5o6p \ No newline at end of file diff --git a/http/products.http b/http/products.http index 36dcd96..1126069 100644 --- a/http/products.http +++ b/http/products.http @@ -13,7 +13,7 @@ GET http://localhost:3000/products?keyword=판다 ### # 상품 상세 조회 -GET http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7 +GET http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 ### # 상품 등록 @@ -31,7 +31,7 @@ Content-Type: application/json ### # 상품 수정 -PATCH http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7 +PATCH http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 Content-Type: application/json { @@ -43,15 +43,15 @@ Content-Type: application/json ### # 상품 삭제 -DELETE http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7 +DELETE http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc ### # 상품 좋아요 -PATCH http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7/like +PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/like ### # 상품 좋아요 취소 -PATCH http://localhost:3000/products/69c4bd5b-1281-4d6e-99de-fc18feed6de7/unlike +PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/unlike ### # 상품 댓글 조회 @@ -59,7 +59,7 @@ GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments ### # 상품 댓글 커서 조회 -GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments?cursor=c45c56cf-d7d4-4592-885c-abcb56661bb5 +GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments?cursor=f81aac65-fb44-4973-8d6d-3789c6ba39d7 ### # 상품 댓글 등록 @@ -73,7 +73,7 @@ Content-Type: application/json ### # 상품 댓글 수정 -PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/512b432b-7618-46ea-a500-579daacc0d02 +PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/4db38f1c-53c5-40c4-98ce-bcaa0ba7904d Content-Type: application/json { @@ -82,4 +82,4 @@ Content-Type: application/json ### # 상품 댓글 삭제 -DELETE http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/512b432b-7618-46ea-a500-579daacc0d02 \ No newline at end of file +DELETE http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/4db38f1c-53c5-40c4-98ce-bcaa0ba7904d \ No newline at end of file diff --git a/prisma/migrations/20240523072342_change_writer_to_optional/migration.sql b/prisma/migrations/20240523072342_change_writer_to_optional/migration.sql new file mode 100644 index 0000000..c2d04be --- /dev/null +++ b/prisma/migrations/20240523072342_change_writer_to_optional/migration.sql @@ -0,0 +1,6 @@ +-- AlterTable +ALTER TABLE "Article" ALTER COLUMN "imageUrl" SET DEFAULT '', +ALTER COLUMN "writer" DROP NOT NULL; + +-- AlterTable +ALTER TABLE "Comment" ALTER COLUMN "writer" DROP NOT NULL; diff --git a/prisma/mock.js b/prisma/mock.js index 64ec75a..0b4e46e 100644 --- a/prisma/mock.js +++ b/prisma/mock.js @@ -127,4 +127,20 @@ export const COMMENTS = [ writer: "불곰인형 수집가", articleId: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", }, + { + id: "3c4d5e6f-7g8h-9i0j-1k2l-3m4n5o6p7q8r", + content: "불곰인형 너무 귀여워요1", + writer: "불곰인형 수집가", + articleId: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", + }, + { + content: "불곰인형 너무 귀여워요2", + writer: "불곰인형 수집가", + articleId: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", + }, + { + content: "불곰인형 너무 귀여워요3", + writer: "불곰인형 수집가", + articleId: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", + }, ]; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 4b24178..56b0da4 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -32,10 +32,10 @@ model Article { id String @id @default(uuid()) title String content String - imageUrl String? + imageUrl String? @default("") likeCount Int @default(0) isLiked Boolean @default(false) - writer String + writer String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt comments Comment[] @@ -44,7 +44,7 @@ model Article { model Comment { id String @id @default(uuid()) content String - writer String + writer String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt product Product? @relation(fields: [productId], references: [id], onDelete: SetNull) diff --git a/structs.js b/structs.js index 1050ee2..74e0e00 100644 --- a/structs.js +++ b/structs.js @@ -16,13 +16,15 @@ export const PatchProduct = s.partial(CreateProduct); export const CreateArticle = s.object({ title: s.string(), content: s.string(), + imageUrl: s.optional(s.string()), + writer: s.optional(s.string()), }); export const PatchArticle = s.partial(CreateArticle); export const CreateComment = s.object({ content: s.string(), - writer: s.string(), + writer: s.optional(s.string()), }); export const PatchComment = s.partial(CreateComment); From a758889835369a4165a80381e09c81f97d9d8711 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Mon, 27 May 2024 12:42:48 +0900 Subject: [PATCH 22/60] =?UTF-8?q?[#M10]=20feat=20:=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EC=97=85=EB=A1=9C=EB=93=9C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 33 ++++ package-lock.json | 153 ++++++++++++++++++ package.json | 1 + .../migration.sql | 23 +++ prisma/schema.prisma | 16 ++ test.html | 17 ++ uploads/image-1716781093102-30560313.png | Bin 0 -> 62686 bytes uploads/image-1716781277009-379093839.png | Bin 0 -> 62686 bytes 8 files changed, 243 insertions(+) create mode 100644 prisma/migrations/20240527032014_add_product_and_article_image_model/migration.sql create mode 100644 test.html create mode 100644 uploads/image-1716781093102-30560313.png create mode 100644 uploads/image-1716781277009-379093839.png diff --git a/app.js b/app.js index 55feaa0..37ed8b3 100644 --- a/app.js +++ b/app.js @@ -1,11 +1,44 @@ import { Prisma, PrismaClient } from "@prisma/client"; import express from "express"; +import multer from "multer"; +import path from "path"; import { assert } from "superstruct"; import { CreateArticle, CreateComment, CreateProduct, PatchArticle, PatchComment, PatchProduct } from "./structs.js"; +const SERVER_URL = "http://localhost:3000"; const prisma = new PrismaClient(); const app = express(); app.use(express.json()); +app.use(express.urlencoded({ extended: true })); + +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + cb(null, "uploads/"); + }, + filename: (req, file, cb) => { + const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9); + cb(null, file.fieldname + "-" + uniqueSuffix + path.extname(file.originalname)); + }, +}); + +const upload = multer({ storage: storage }); + +app.post("/images/upload", upload.single("image"), async (req, res) => { + const file = req.file; + console.log(req); + if (!file) { + return res.status(400).send("이미지 파일을 선택해주세요."); + } + const imagePath = file.path; + const imageUrl = `${SERVER_URL}/${imagePath.replace(/\\/g, "/")}`; + const image = await prisma.image.create({ + data: { + imagePath: imagePath, + }, + }); + + res.status(200).json({ url: imageUrl }); +}); const asyncHandler = (handler) => { return async (req, res) => { diff --git a/package-lock.json b/package-lock.json index 2db532a..1a2d057 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "express": "^4.18.2", "is-email": "^1.0.2", "is-uuid": "^1.0.2", + "multer": "^1.4.5-lts.1", "prisma": "^5.4.2", "superstruct": "^1.0.3" }, @@ -99,6 +100,11 @@ "node": ">= 8" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -180,6 +186,22 @@ "node": ">=8" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -236,6 +258,20 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -268,6 +304,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -705,6 +746,11 @@ "resolved": "https://registry.npmjs.org/is-uuid/-/is-uuid-1.0.2.tgz", "integrity": "sha512-tCByphFcJgf2qmiMo5hMCgNAquNSagOetVetDvBXswGkNfoyEMvGH1yDlF8cbZbKnbVBr4Y5/rlpMz9umxyBkQ==" }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -768,11 +814,47 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -818,6 +900,14 @@ "node": ">=0.10.0" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -877,6 +967,11 @@ "node": ">=16.13" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -931,6 +1026,25 @@ "node": ">= 0.8" } }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -1087,6 +1201,27 @@ "node": ">= 0.8" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/superstruct": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", @@ -1148,6 +1283,11 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -1162,6 +1302,11 @@ "node": ">= 0.8" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -1177,6 +1322,14 @@ "engines": { "node": ">= 0.8" } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } } } } diff --git a/package.json b/package.json index b61b442..52e3a0a 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "express": "^4.18.2", "is-email": "^1.0.2", "is-uuid": "^1.0.2", + "multer": "^1.4.5-lts.1", "prisma": "^5.4.2", "superstruct": "^1.0.3" }, diff --git a/prisma/migrations/20240527032014_add_product_and_article_image_model/migration.sql b/prisma/migrations/20240527032014_add_product_and_article_image_model/migration.sql new file mode 100644 index 0000000..55bd59b --- /dev/null +++ b/prisma/migrations/20240527032014_add_product_and_article_image_model/migration.sql @@ -0,0 +1,23 @@ +-- CreateTable +CREATE TABLE "Image" ( + "id" TEXT NOT NULL, + "imagePath" TEXT NOT NULL, + "productId" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "articleId" TEXT, + + CONSTRAINT "Image_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE INDEX "Image_productId_idx" ON "Image"("productId"); + +-- CreateIndex +CREATE INDEX "Image_articleId_idx" ON "Image"("articleId"); + +-- AddForeignKey +ALTER TABLE "Image" ADD CONSTRAINT "Image_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Image" ADD CONSTRAINT "Image_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "Article"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 56b0da4..f586145 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -26,6 +26,7 @@ model Product { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt comments Comment[] + Image Image[] } model Article { @@ -39,6 +40,7 @@ model Article { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt comments Comment[] + Image Image[] } model Comment { @@ -55,3 +57,17 @@ model Comment { @@index([productId]) @@index([articleId]) } + +model Image { + id String @id @default(uuid()) + imagePath String + product Product? @relation(fields: [productId], references: [id], onDelete: SetNull) + productId String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + article Article? @relation(fields: [articleId], references: [id], onDelete: SetNull) + articleId String? + + @@index([productId]) + @@index([articleId]) +} diff --git a/test.html b/test.html new file mode 100644 index 0000000..55b802b --- /dev/null +++ b/test.html @@ -0,0 +1,17 @@ + + + + + + + Document + + + +
+ + +
+ + + \ No newline at end of file diff --git a/uploads/image-1716781093102-30560313.png b/uploads/image-1716781093102-30560313.png new file mode 100644 index 0000000000000000000000000000000000000000..16137a61fb1ea45310228c387e52cc308aa8708a GIT binary patch literal 62686 zcmeEtWmuG3*Dx(1g3>55f^-bsF@zv814wrd-Q6jnBHcrGcXx<%ccYXv(nEgZd(QKm zUTf`Dd{mH=#>FPbMnXcum3b?vh=hb1goK2$gNcE7f)*9X zjfC`A%v?f3K}JFXpx|I@Vr~URLVEi#PVJGpQa^E;R&-?K7z*ZFtX3>4MU=N#nL#U0 zC23wGi+^OtSKj}b6<|q%GdHI46rBk`Ojub>f6=C{pfJ-DpyM8c(sanQ3Oj-cKHO~& z`HrLrUXD;8P08E!{LofL^%HvU|C(nmot=k2NNg7aEd#lr11Hhm9d4-VmNq*`1L3m;+qaMNk|1c!9v-Q30T}y*8rDizk;ZcrpWMbHZ~zY zBvLRcaciDRFi)E1J!Hhdd56zlL0EYmF`2fgfQ-mpUiPf63lB-*4>~6fxq%`j`ne`D z;)YPiVE5)YP6lvrA^zp33F>UXOu$uOB(Oe&G}l;0;u+yZ!7E@ot|NxiE0-URs9gY_ z4}5Q9pOcksOmcn@dlC8_TPz+@QBqeEn%{+4wVewhejOp7sW*Xmcrl^}Z zxCdZZMxWta&lHRAoj16Yo=F7D5c?}}P}kSDq0<1Dq0x^xN(*5O1BTL17T)GmR$Z|G z!ihoy?uf3{4T4|OtD5U2Cy4UtSvkf>5)^*D!KwNoK?v{Ebk}yjwPT%w`iI7`6;St4 zJ{RF5X#)Th*j-Ds0PjMTcD?XPu6h~2{UEfrshN1mOR#}4=*AhUbAq!TYxL_YN&|rC z+AX*NAfWq{PB(TK_lxS+Kp^UOKU@?f)VBtZM=>BC{JKk?vo66m^7v~gSbb3mAx6SmDeBy>}{}L0m@mQCUl7{>w z9y1Ljb%l4Nt?tgYqOA_Sdq|@+Zs%m~`@lrDlOY{^ok7DMNeX)W3gfA@J?he<%dYP4 z(|D?;DIYx_kE}Nfe`m-HJPx%>9g}Ggey`39XBfa7!#WR)ZG8K{PSQX$<hIEyubMH%#*(yv*o?3Q?_aBe#dQj=< z1g;ov{@MUhd>6gN717Y3Jx#Sp@knW-zs5#Wg07l%q`gj~eQIJt#HMa1jnBqMm9~x< zTpd%5gH(0*<`>+9fO?e|f4S~xsYMj&*ybfEDc?ydjx~mUx}et`p6|9*qTQYX`r48~ znzCZSn%#U5Qv0*rW60#AZyhh@I^cY$ybTd>e-J))7D(tV27&&WhFz*`2O%5k5IRl9 zV`kLiPLB#KD|Ermmlc#;e%WiU`A}H{2G;}{aMa{U+>oz31dqwY@SllG{0tQ_3{a=K z2<7aO^oj(%e(~{5bQITXf~T((jWIaz7$j5ydr>TJxvTK_!%`$is44oaH(pHywn&L& zlD>OW`<{9Vo8lwKdt&n7Z`tePU?&dE4Slu^o0myFwtZW znEg@M$I422X7s_1*K^DzgiO6f6`CbjBHP94bTgm5zkcMSFkO3MhaR$q#fO(3Hrhq9 zzV|EDO?c&#UJvCD?<-!EFZypQ=-i(1eW?5Z?jjV&%1o(9wF|W)Z-%A$IjacXzEte{nyu2`$6dWx=q zq%fhFQlUL(rC4mHVnW~2j@!gs+3dwkL*aP2%%8E%#v?mgx96)eK@i z%eEQSQYFoZ9n$5Lk-XENr#}~e=I`h%NLpK3hr86dBwf5ba5)g6V4)yMl}s%ZAQI?x z5^!eMVbTe=DLYhLzH8!j62;{t|3*$rT4$zyP{Gu_vWGi+I!W*|Zg+Y|XZ9v%bPR85 zbX>1&HN$rmiMN6?ls(a~VtlPe?8xrmyKc98w`|A}rB5$DcMWG4cZyBJbj5JRYTq3F z+*_-fk)N^e%PY$&)9veiF|MzF6Q*?{pd`rbXN)n4*?vrc@i}Txeb5YgmPDQ$ocIn> zpI8U;;i=}4WneAUO)TfIWk0HBs|>A3G%?QolLoeodXwg$%ih?K1A>twAAtB*S;orl1!g0fa(wbplvPQ3s`KZ+t?No=< zI{syfTy91uH zURr)_Q)?r9NPK917$e`P#v|*ozXLbo1-3?nc;XzN$*2Sp#^NdP{R3 za=ThBJkL2#hf?9U<~QMY0V?hI&~fgM7cdmS5oi%`9iS7K|0o^v)rSv3%y^Cc>_3kA zrc>G!F2|BGOAV$f8Y<2WBDxN`Xud<9nn{{{9SHS|ijT_b3#P~K`KU?eEV>}z;cym3 zY6x}$zZsgGdtb?EIQngTo%Y+oCr^?i%66`Mn*c}vS0>GSVRr6HfnVN=povd8BbC&> zBQHGJ=K>ONrv|WWe)j6QZnkOS|?ug=K{_g}mRiBGLu!Z_xs=8VSN7%ISTnZh$Y5 z@v(JG2ROW+w0aKYw{z6;E`QCnaJP_niQY5%M099Xh#xa|3mUzVa?Nwy8W>7rUM)E( z(S4=WpnJtA_}WwH;wGgag@PZoQKr$^ozdOgJ>-pM){FOhuh(Ui=$u0jdT4%(^rywB z$sfjikg40IhOeJK$Eo=q;RTzLy8e7-kSTBQ=6eXkN2Mp==@iD~1)gD>g)H;YPXV8N zVBzxH5ZfdJ0i(mP5Kaxw`XO?0<7u-4s+aE2G!^8} zQB~R0`ly9dFR~opaIkMXv|3dE+zPmO?;K(#y*)CQS~`6=J>C4+m8De7GKX8ZS;N<16BgaS6TTen&!qmvY zsQ3F=Hw#1;5)#h$a^8OG%&dn!)kro%DST8^WK4T%$yeMf>(Y3uzn6tT>oASnb63+6 zYu4FX8$U4ghFLCVuIl)TP94tZ`u5)`u0taR zArwXe;d;MX9ZoDdra5Q%W?6M3T2}0-zke%*74iz&{<3vm9cjJWmHVDL>bku|y~Na7 zZr^_E|2?os)as#N&uLHSf^E%UF}p$9mGbmuyIb_bhV1NZeog-7C^${URnV340Bg7L z)@$jsjN}JNx~J^@)NS=i?(krsFZ^zLhPSSKFK%PHW3R{dY<1sl@1!nQwCSOq2iSKbbVf4COyqN?Ih?7dZ4yg4q5GLTYld6oD|=YMjKv^gu#>?h1{`6fixD4 zoY8$s22J^KO9u@7F~lgnCTh?__Fi`hsUYa#h`sgrXp0ufv%YhkWJ*mQ9gvIxYIy{b zj(AxVXvz(5R8$Q;eo?`HVd_O}y!pp@i^gr|euQ&hf_^*}f|E%O^WB>Qcf4%wN zD^(n!4idK3h%KE&{yCYy7ytX^-wTC+zbXG0C;npd|2#$TSp-`M_}?=V!6sw<-id?+ zLXwdbQ+7k%Uq)|vuCmba{gQTeFPM;#&@9u8!KP<fJqNN_+qp`$rsGx7J zl|q#pgiUBM<*Czln&#vX<4GO!aY^Pxw0(t^O!yQ`Yr4X3IuZ-Mf@r@r5c9R(BMhxFfHe$*g^pKp&p{qqDdBFqGVG(X!F&l~>%0tuN(-vaw1 zHk|d}5Rg!M7(u7whRdf`y#EFJ8=O8G$`rwg@V{_CVDm}MFS+Z-@}(93A9Dd{L0(w@ zMiAs~FRuSK8J=+YH2+`^*zR;XBocqY%6 zAE^JMTUY0u@vSZLyxm(64<$KaYnGJwU#I2YMci<|DFxRzbTqIv{yJm+<)^hR&%$ZG zH}Be%a6oW98Q~f%P7F*u{XSzw`>W@VNfYbY_Os0b=6Hv)+P>8J(5oVM6tGvh9RvM4e?dQlA@5K zw6V8oeDj9Q`>{EwETE{svfFN*tG$k6dSQgrBz>NL3&wG2$DkgOJgz}W>hUgbPwQPJ zm^7XYIiTw=Fzqn?12_<7EaSapfoW9oZAH7RHWKJF{rYotOPTtfDe2!rV63OVkY38+ z`QBxep{ku|r}X=xUL#Uk8o;ra06-r`*L_@rzQPWXs+F$Ler+vxUCh8NlF}CeWo^-T z^cRRm;y%fAw8jy~yxIKv!AShRV5Cbz6NxyeroX(e3qeNhzz@;3sK!-cnp~CEoYm0o z+>)m9nmVq*mXGBFKg=m*-ju(p8uE~SCj+pT=lGKMc~X8zz%|2_wax!u`qF@qNhe6p zheGTj?Z{gT)$T0Ojmyijm?nNvnT#6oU6NZy)H*WiQ@U2#>UK8}Imu|GK2)9oOSO-K z`UxZvy_6*-F2h98u{x(r#e@~yKq{z6=~?MD`mE3r-`!QbU~uo##It!TGfC-(FkCnk2`uXS^`&fJR)TYi3LoZWB#Au5PPKcH)a?l1__ zF$0y&$Ykhu9Xxwh{qqu-V$68W;P#cqvgol_l?o!;c|V_r9~0IA-Tk<|u+XR-)AH#!-nVl?aQdr-1_y1=3_K znBCI7>Iw9`h&9ScI&Q&}sa7JTDOk0Tk!0S(jqL>?YZ-z2uu~tWy~&RS72K^lQsNrC z>bpLtUg7(C;^&x8v{(UqFjF1@vCNC1qEWkKlI$dzT8+z4F)@uywU3o%gt#{t7r1=| z(*Y-0jgOR32R6Z=7ORM70bRy=gx~&aPS61$hyn7xWV?-cbfm&N$nc`B7H-TrUYiWY zlNa>f*JtscK4DLSYo?rDRwr}umQsBt0mi4gth~73k-F;ec~Ct&v089`HHF+>4#mSdRL z=5f9_eW6*%UF$7p!3NRu<$=GeYe}Q+m?|r%C3cJ|JfCVYFU@O<=t~}MUNPeLeBWz5 z?dPhWuDY|_GetWxTl%c9%&hiwNQ+9*7R3@*^LdPIa*VfLtH|ZVp2Mny(Pqy2lLU(T zWe!GLrTjZuQAjfLp{PW?+~mwj7c?ld+U5>)*qVHF{@#5R7Um4_F3%0 zw=wTT95CB;oq3bM;F}m-Q!*cKgo|5K4g8qY`bq+${~hY1P`SyuG19cWwl*=FmQ5S@ z+WKf$cM9(&6zZ@bBR!z1Wo7ut`?6d9T{X>v*BAFZS!rDhhxwy zD(}04ONX7f*};Ng-e^aubo`guV!9GW^gwx$n<}B(E6(rsQMNX1_wO`Xa-_%;#K95S?6BLWfqGyQvt|PXUD*bN4inS^@-sfhVC~J`aLUepn zs>GS|vH!?30R28QoJzO+9y7hgy0Ao$jeavPc`rYmb|4T>get}-jsA3-h3&GFJ4y2^ z$Ig6q$YYA8q8A>0VjNbr1{`0NU+mY5eZ&I1(d8XxQ-WM)uatX!EHO>i5NYM&q30eX zH}~lPI^9fsc@U%{VWqMN)MMK+D8ZV zAr!aUOYR(prI*HJN=$EmJ1Y}Je0{OA9uHnOIh$o7TLW0wwt_|CXFqI8a*)6K^TLV; zXsw&26y)a1n7y7hR5pTHJ+eCMP$r-j#V?s|GFHzUF^|fBm?h@3%uugBBMV=E4}mAehM7qy z4jXh#S@Us{Q{C3N6XsR!x9@v5;0fRQkv)$Xn~$neDK0iRfv$Zcv4!pP1~BU?|Ho_) zDem*bX{EYl3r_dr%6w=V+-ErXF258mV7Iy~`M{;)eOG$&oi05D#as{XLUD1C|f0GzZ=HbnyBFET1F{^Js{! zWL5EKTQWV|jD*ngr2#0tuY+_(cjzdfr`Pa=)d7Sd0chDaek`fHR+wLMvk>^P=6zsU z^5Dczj=Af@$({)b#3(bf#5nJM`RK)Sa?*9*+H{U{wZhWk>Kkb~_%7^d!&Avf_J5B3 z>6m8o&uF2VnuizlHS2!4IPE{?F~-R|E_S942CY6*nO@mz#r0<`sFL032ewi^?4l07 z$>+Z@uy{m4t$W8ZR;k&&3a4>(XRRn|q_lxeOCTErHjWnAj0lnO*i~pd-=lN5FK{Js z+NPDN{9LImKI0vh4tY!pxbrxRZ4!mt$PnbJob9vT4G}fp@zBQ=``A_tGdRAMnDA%kms)w3a6v$YD2Z!xS=O$k=r_12BZ7w0IiEuJwr~Bkwy)9GR z==xUhmQ=tvw1i7PqcOc;e#MoLOT`G97hf@TYi_|#*LUu?Et_O+NW#n%mpO=G9J*ug zI6+xBOY9LhxlpIKT{lO0-_K?mB=lv^2S(>G+6>A2__@y| z4{NX~5XGU#XY(S8JpF!x>L~dJt2Rlt@w>JsNa5lIS?m!6vX@QCQrh&Z=|nC?{%8`W zkAeY7_qnfaC4pFGr{vUvuX&xOU-4kJ+|2B4_)DkNPz<;HTD`Q&m%4+P(s~}%1@1R4 zhL2c%S1To&)D(o&FWLLLxs~v0cHiCiK2&Gd@E5Q6Hq4M0J15r6Eb0AR`pnnM6*7e+ zJ!z`vMJ+HQGb(Cdf6B96e&l;5I&a(^HBoMBt0X~D!R@FixSfMLqa{6~Ze7q?uXwaK z>9-)`A-`tOoA#=>tSVaD84h=;a3RjU>EVx0H795lx#_a3%k^^^sqST69DHL`RvVM< zHk4VlC%4#F4Qyk*6vD^WCSVD%M>ymlD&&JVx0!eX@qvz10bOpVmc`WDmGYWT_JY=< z0t55tj))gMUG*lbWIQqHUPS^?(1PGq`PhJTVemG`H9Z>S%V%O)C5b?+<7c6Gz|}PqAFow z*TVB#17=+gtt|&@6hd3{%2&9adhgwsB-xgoK;YE}k93Z()O*mfmxqL-m@asp+K|iO zL^I@l+&*(>sZwnBvr3aH&9<4nrC~W4!DE?dSL@&!<{my9I%!Xuq0&ogU)`!(c=?9= zp*x=UQrJe5aWKh~i9mRg{R?DpzGMNcj4IKJr(k)L=Ifra-|DGlSAR3I*k8cH6Tgrw zFpeZ2<3hXcL{E_Pp6=&3`PVjYk9qxrEkVkPm=yQjN)F>=5PW<1A*w%*!KfsM+j9X; z1(m^?(Y+drs`k-vA3$Zh`Rc^-jU@&5vi)WEh025H&q`BC%T2D@^xh{!-+jy5e#uS9 znWXGL=0tWiR+yVuFud#!2>QJL`ty)|slPLD@=P#}Yb&c-QZRjd?dU$FcLBOzcUs2- z07Ln~pAlJ)*U!clrDr(qkZa@@I>ZLYBxM4{4@wth)Y`}B)%LY)ZcxVzK0_j}A`%t_ zgdFqMiICf|@d>Y;M+x=YRDUWx^Z1qy$1T-UrsgymjsINUEJw_&X(sm}kmEidtLmYw z8J1^A#Nm1`M0RsBSXcd7)iDd+Zrc{sT-K=i&Qjd^uD0+SJ^?s4+G5D|R8-HJ&|5h$ z#sX~0{NPc_UgU^>kg-`AF~r81G`XReKl^+l;<*a#V4~kURA%e6B;9wwiZJc^ElEn& z%+3tmB(Hm%Qz1!$C7#4l4_Mxo_qvKW_lIjf9F}8_`is7ljjh%Ts_VI!(Zz+F#fNiO z{_iz78!L~}E0|ngj$}q~ky==kjI^zNvIE33yIwbZJcr~nB-|aO^NcM)drP6P_ppWe zqT*u1k^5`d(ZGSLsB!PzLDlI--Gh+v%i`nI6rV#q$v{}2Q)r{>as3Xbct3^|NyMqcn%(@qB5y6^5ho){`!~M{kmmy&s3nOtCbB^&0PsWOHSmwL z4w3yxkXuJ}fhRU~7Gv={O^@@p=ZJGDZ;jC@-jTvn~62_>tu0SxK$s|(dKH(szb}H7M?f_3DImp#)eAb>s*yjrL^>R z*=|Z&FPKjHO>r^H8^80wU`ld)T^P9AsqR_Y-rc1DwJ0iY*wxGGT%%pyR;#Ko znfd6DWss#gEX94Gk~XyI+XdV8j;Y?8;kGvS*ns;3*Pk+5@0nUR!eM2f$d5ws7L1iG zFAp2GU%6if%3B|mB?DXY8Q;UnSb|J6+q(v_Bcy zeNk`90hXn8OF=}0>T8D)LoxdQH864V<9gOLMou6~B=@@={sLbdQ zqEs|Kdy>1wPJz5*5TJLUb8z%1cF}xFa{JV1qL&^J+({Xd|ogfT|FvRqYM|=9@&PNw10{4g2pGx6%7}qVG#^$w|OrK|H!__^%*hS_* zXl&cQzjI$dz%%Z(u8$2d6iQHlweFtcEau-FHFRpf{&lZo)-F_@zUr}!I!;^J#FC%t zmgD{SgU60=3ZBq)EN(}-*Uu-5Q!452=k!smAlGwP5Z|Fh2D)_nC~r#mYFt7ZQ$mWU zfJ3BrId{M>MPtxaAHir43`PFdy=uw%D4VAvB87IvfixUpmibVwe`2x_q~=^MUb3go zrM3k!fD>q2mnF3@Xm%y^2_{jbA6U5}(#CcMA@hYardM93J5^Gm`q;X@#DybUC!hTA z2~TMHKKi9Gj_}|GPAeN`HR?kfm3dSKYDsioUxs;Wn;@lY(@%SRB>w|PX=bv>P+0aaC^B(20RQgZn8Owrl!?f!5E3!jN}QKeqvHXRyxziYKzjp zUdPBj`sVRm%TFWjl-T|j{=uQI#TSO~^1W|P>aijg;tz(x(OKPJu`sL}HBR)|94=zQ zg_%#Xy~~F)xdGtV8r1k3ux&x*1TiAba1HJrdDl9`Ny%-FSMZr+Hqj)7`=av%2a?9E z0;A25n;gHO=;IS>NUd1*6?3dLkRX`Kk3NHc&=f34#n|zNd5mu7lBB$vOGnNJ01Rb z9C6-s=ArHuD^jg)``s+PMhTXCmrzUDV~QrAZiSbtz&HL12w+nrO`LFM9r zX1MlzOQdMUVaA?rj*(e7N*8*pkNV7FqCoB8!Twh+59yRW%~tuul4*`iAk39cQqsl6 z?Bt>58(1(7zITdS)#3CyTMauT*(A<1`B6{3{Ekp*XCvkNqvgrskjd@Z0n?aTg76E= z{##SrJ*sj)sWLGf*4ELAl?^7s7kj9OUoI!q$K1c9gj~Kt_MU5*(X~O})wi58P`uQC+LSJwJ0fGulvXMakt7>5r+Z-@Axq(Nr;;EUK5})lTf|6qx#g({ zwII0U5bk+dadbE_eI|Z8Y6+|+LAt*=45?F9f*nQwu9fhjge=cg<_5#y(U9y?AFhri z6E`h8GXBwZN&-SDkK+|R6dF;vrR1K<;f7#V->d!oDSV*6f?VziCh)PV!Y z@^IeGb#jtp&b-jRv}NfJ8r&zSc@p7egO_oBh^PRy3^=s@qKwC1$9OGoaF#XWh>v!P z4AQb`{)pXFbV(m(WpP}y^+~MJ>L^?+bELd;vL;tJa@X4x)dN;`o^U@isy)U?w@T7v z3o7Tcn2fp4Gq*@hl0K5rHlC^O!#9f&Xm;KbHDxM>5WDI&D?j1pPDtKLMmisP;2Fpl zg_+Ifu;v*herH0nf~1S!$XH&I52qfrf@4Mkd0FFXA7N~S*OPC`u4gP(1Sef&2@hDG zzHj#9dl=>sYb1WR&|H*91on}iYXYls`&aUmPrK2b?3$hY=@C{u*Qa1sCvR^F*?T#=7FP75#5_UKWB6`4g85r9X{5S1Hd0@DvD@~NtpY(USZPP8T( z6W>r~(?k0gEA3w~Qj3`hnxw}yOxjv3CZ+S?M#gF9<3t{K88K%!Wbk>iw0)JpIOVO$ z5!DlZXWq`l`%S9SG2h0-Vi`jG-N*gkdbR0M|IYma5T!ZNyfsK3dJT`2j1x2y_gfnW zo|34&MW9us2gpT7&@4G7S+nR9YaUO<=h9LK6d-O5mscUXz2TQanaPFD$_LBnMs^e+ z%$3uqw$YX?E(bXVLpEPD@^&D52H)aK%Ed{cjOA2~RJr%WE6w%1QMQREma2%-!t*5Z z2?r%2*S1Eo))_RfgP0K|1A(TGwJm+-=V_w(c^nRIHTGpVLkt=RsIK;P-H zA6E>7788DSWpb0B&IGQ=7S>mV0b~PT;wqoLI@z)hzDN^FrPY`KnJT2$X|@_q3a&o~ z>((%sRpr1nJB8LqW$wV`#&~J54TVLVrEMc`E1p;rd#HxpkW+6*c%|=mo@#a%BIgNM zI9M>%Vp%!A=@2TZmvrGkhS%_y(z;niF*s_5)z2^oA69Fxa4}8iHN5_B;n%;51W|{* z^Q!pg-yY>zEoR5bxzipR~*h71DX@JQE6n!0XwG{Fik}q53Y=f z1yMvB-r{r#ui1*(mpm8$18#F9Z77QQf%#O;ZOsvNy;NXV+Vr(LF7BCl#O#gmWT>o6Rg#!>REgo}|%g<*$-aq@}+Mr`E>9OIe?0 z>9W(f!E=?Q&jWbrU}?@qE?~T~yHG0&@yj|+3giQ!<5+81NJP>WncEICeSZsi4ldWQ z)VZ!`y?+=+)V13u<@*|V!K|MGuNZF1`Ofw77Wd57UKJOxNeEU>+R@~dD)peKk-*9r zw_~&!Vepsi7;EakO>^;!mkG(tOGkNzGLMfa1LLa1lM#EtQ#-<<#_Y9Osvt9q%EMadIaoS1E)6;Aw^(SAbA*Tj9t z<{m%d*z5SvgD>&=HgDql*VDNMc_))0wuzb2G?F4^R76RB3`8}-U_r%sw>ZCj5i0uS zp;qVrNDIA{e>V?Pj4i|$z5U+Y)`fomi*>!TRvB?D3)mMIQEz|MAsjTX08L^?KfABz z-?D!eV_H9Ov;}v&-fvM}jI)@o!|+4(NazDhHW#|&iSv=h!2T}366W|_baVmr~Lwp1GErXkojn6<3IYPL2zZJSnXbB^SQY99h8MYL%ZSvE5n=C%24x7 zsfnge6n}R{%__j zpkZP!GP{NRZg2Q+R{~)wl9<8xfddce-?RP_P%}j3+Nyeu;@?vN3Qh=g-_#Gz>;G55 zelN;^AiSF40M~y(MMNRvSonm*%dDn>|DcHg?azZKuk+xn{MCf;A1vO`=~L>q>vslZ zE!zDrL_nag7(ttxo9h3d{68bYOg~)g;-aEYc9Z{CqsJk`hTwld|AiD`C4$PQM_xP> ze^3da|Nj$zGwS~ZdqCd;yUg3=68e?$;Au{sT|tP7r*aanum92MJB&YN!U`+a#ISQa zO;qZe$X$!j=~r)uk32DTV0$n1_SXT;s(naR7YNTXK8zU zpa1^7H{GiaoPIBT<=Dcj7TySwDyx@k8GkJOhr*nQcQ`9tjWkmZh&+19LYHnAdwYI@ zv$-)j5<{2fp(}D@mcp!2B}oj_rGh|)Wq7Xc>U!MmT;!1(%A zIN;EYqHa*hqh2gdVmMXOlJn^YsRw2U-|^hJ-e_39)Y8(*&B=Lf;dO&I8s4f`gS8)u zTOZZtebcv1*=|7BxOw5Z0Zh=N?xpZ9(DoSTKQLYA{KFnZCZLoBc7d&QbaYZ%ZY}8h zCN{lK`nRikww}{zpN$CGFfCeFLx;=<1_zCvM7+2VkSNAwKS_%?p%*uy>W55u(~4%jT% zDy?5l;2ddG7lG>)e6u}lasM$zPCHP6p(6d#)1v_^PtG%?(bsljG=^Z9R+>^&6QiWX zW~e>nB?ZiGW%VKP74PcIOv~94&bPOx6Xc_PWan*?h^m-3o{$vJst2#2CM;55?|yNb zcfp{3**%?t=l+J0nxykT4Mcxc`T;<6#WIGeaKp1v8NoxBj8mSi;uX`Y&XDvz(FgC4 zmdpFzs*}jhlatekf!c?w`X%pG>Z(26kO3%3I(74YOY0fJZ|~-CS#_4yfX4k?5H`)? z4k_PiIXJ%FR9hXG-&%Q7`by}>80y9;u)S_?)%&P>L$O+fuJ*{xgitDW?1;m z!YCID&7XD^&Kl{U;5HQXXwX?LB8obkAEN64O?lz{we#fghH^eH>44qB(h}M|?DDL% zax#b8L0-fq;-FyjNKKdOGq~g8E8=e5G1W1CNORi|tvZ;|l4LQtv6k+S*Rp!XJp@-! zB^SI|^}0#5sz3E{;lMpEyI-U^=?&A!oB8!vs~dj%xx63yPVhprXt5?IuXLxNI!(Pi zKh-@mOk|UftadZ6Qi}8O9|pM($A9j<3buym=GScNqim0M-5X^U6`Gr)=4P+UJ2ZZ~ zhgRcliu$J%d4)Ax^!0Z)n*7^CF`H4nY0I1n4@ zaUUf+-LvWx9e8fHUk77sv;5Ai{Ud)MUF@6}gcgxbtAPy>rC)(p1ulM%s*`$n8(1EQ%3ulEAPFmE-7L#DJz{39FvZb$m%f z*U1R;$&YHh!N*G3d`4R(#}!Ia=|BRXR6gOwG2g6+nTJqK;_PGNn@Mu$;C-(wxA9{qaxr(9Sf&x&QP z$n$!gE1b&IYYFN1+-J3hG(j{`^C6thZOV#lav_|S=-M5?F=%)8H}`_5-|Src^Zt%qncdnr8|_G^1b*wxN=_iR7jNB!g7|Mqpn ziRt0?6R|S}Os-ZQJI>j)B;y#9OxtpTR@DBWjy*#Tf%J=K0?+}jB!L571|}x%h-~$h z87TqbOsO)fi+z3$%Zv1=K!KLoG$n3)+W$+ne`T<(iuH;9L4yJq<-TBmiPpZ3=nn=S zM`HfH+RjSFV0m_JbOgGxk@{?>L?^>rbCx#dA6pfJsr>v}=?U0+ zb@PBD3KzdN#Q}{-P(26gJP_bHisqI(%Z(6vkOxN*T`nRxdCQ#9`zcK_J~?I*Jf&@R zAQ{7dQII6RKcbFibv!d=1swQ^WkLH4sz*zxA;pfVa6#0qYx4Y#K2mNz!9m8{k{%QD z?n)RSFG7Tg?l5fr$RSBHTt2Cf7)9f0pK?-M;ifT^T7w=%gz&Gwt|CL3Uqx~w1EH$# z#0+F*nIJP&bvNpEuW-zmEQLXnG6JHdwUbYcR}6_NYKil1Pm<|xS_atlDsd1y-|+e! z9D)6n2isx;#C7-(T~#eubBx{*y$XX9CIu@qLx|?)NI7`iNJ}5J!aho@ch5bp{*9m# zAns()S)oAfT`hL{2PBjg^km@~RkzepPq`!l|E_0aC$fW;$^=loB13QlNE*2unm7v= z*z$XYNth2}gr?tQRK#g^{kRpVoK7Mf3*?-hR7_37;YeD-VJ=oj*A$91(%oWE)vJ5% z?}pg(moaHL=mLEy-l!~4T<%?U`=q)=6lRX*dfM*Uo31_+s>mY01c#wPp~9`tJ5TAc z5#&@U=L4}Nd7k-C{a(g^7F1{&!2g%D9)I>ra0CNSub`g&f4B4646@IPy~;t5N`?#^ zmgcNBi4XXny92b1I3DM4LCZHCr3ii0V#xbbm#`HOkra|EBMiZVf5~eD5u$OIsmJMG zj}QSCGNN!pye0>Y`BQ7^5$a)+oA~4p^`{3R!Y-7hLaS&0h6`9zMJReH;pCr6icXJ6 z@%RbGL4LQ(`~!Rmv0qc1p}@Z$A!0uygzDnhZhH5wnB{jQ3w&4n~v0h|7G`V5c@5^WB*@)sUL!9^aiE*|HSft zIcEQ#$$#_pJnFByvf+(s_Xldw&kR3!y#Bropj+b(jEeMyHBh2yXUHq#!tlJLc{5`Rj z`Pqq3Y!Le_(X->C%sh)XpdG!R0;{D3B2OVke> z_#mebpWpHf1ks|?-*6Q6SK-?MLG#-yj3i19E>Sp}LK-29V=&3=;@2%6WcwJi~y zRud(~uF*Q63uzKPDRMnDd2t6DBN$f<@Cd;jevnHe_6V!CI8nE;O<8=f1!MHA8DSvF zVklyZfq`gOo@_{qxk$2%b9|8B+|5p{m252i&9fc0C&)*LP`CQKmGYJG3MH3&MeD?6Vx$%-}ln1s?wT6Qb1HF9=j`tsai^2TP$5GI2 zjJ!iMwZAcXHV+Uo^OXe=Y;t1~#)1m;!+hJzU;)(`pgB@B2YSRYN?54|fj%Hy5;Q5g zb{hKq4T`n;Y0J|ww@ad3|KfFot&gPemu!8mD4R&(82`x+8{xzVgECGL#0iXwI1HzJ zm$o?8)zs7^Secz#z(!m;#$0mxLA#|vDj5bdvI$L#oSB)CF)~sb`t?{63Bh*{?dj?1UfkQ{Sz)FFd_biV+F&DyOws%65P;(P_`iROEYyWzyXX3o0q!e=Sy1KFP&F*l2;Ud9&iyt5cb3+{zk$!#cF=;Glk85ya zweyR-JjwOO93F;*Qi;IEu$hg}-wNSlLAB-(eNH^*PIa9DpBoi)JjvlE95#0$&K?}=sx1jCk6s_Jv_U&--mZ;jS>$JC zz)IZ4rPclX(sSqD$Bf_wcj%>6_g8*>W`vtKad+sU=UBzha1)KiF4B&m?(0g3{CooZ zh~4zWJkcVv!R$R`fzHL;_|;)aZm!tQM6Q6j{#=R_OJ=ph!Er#w*!UW^8p`$1kW(3t z2~#@xy8_BBeGzS3*r>T%Mk89+^2HtD}pRJg}3twSFq@7 z^?(nbbleb)k>@9BqH2w;wUu`Vjb4+>`@Z8O`U-dQ)GINrllpzQZSB~{AYv%wbiXjfICue_fO^vaI{*d9Z z65;l9mZjgimyYtH9p1Rw=e&($x9@Z>0(gY!MznTy&Y0jP643Qk1YI=V#1y^#^E@aW z+xW-a;8zZ>0f{>Nz9OVvIaPNJJ`{U&4*PwmA(=g=`d4a9?9Xo7mfM62ucVq}j`Ut5 z&dmbFA9URd0c21tj5%>}yXUdG{JtI@Fe>g+5wXr}()GvLVd0>U-dW#VT3p9Ot$~Z_ zq`}y&1^cd7`r_hP7^qtsrW8`ST%ZIoalj%9MTDp?n#4gwYox?UOB{5~@ZG+%si%C! zts%irxBd4QJFb3J<#XX5M&?(-d-YCEXh`_K=-j^^eGb)Qy$G*&MmU~Mlg~XZE%&mU zI%aXsu4m`1VY0Haxmj647P0|i2l0Y36(%QX`;|oRalZT#^Cb-EJhK!sWKI^t{D6Ko z_t{Iq^Jl}UG#w`*pZLBvd8@QV2rh5gp$#5i&o}a?T-ndDMapr;%dGC(^Bk__&jM*2!{9f+xAAmUy7)ir zy=739-`g-M2nYy*prUjrDc!vR5s(&?F6mafLj+X1n@x9j?G1volypmX!=~XZ{_(s& zoOwT-nRC89%)o5!x%ai|>RPQ1dL~BTX6L@VYQULn7;ozu?K~DgK_Q_XmF5juODn{Y2D=k?DYHk?9rHB87oz`*o}R-J16rCpCZ_;uV>BeS&fdt2T{J*om4<@ImUqre1SPpI((5rlcw{ z)lV|sqL<00x+|4g@QO(2POQ!oG$Z8{g%H6mc%X-@s%kU}=Fv&|X7_Ib>Yi2`u~=yc zEH4#?WhTKs!TQQT{wotfSY;=NJT`VIlp)nyLrraddXtkDOUv|V=8(gj{AJA_l*6&X z2h1F6jxR3+ErOW0EK6pjbXoM0oiRvfe;`N9!Mu4Y^v1P^S7-D5q z;PXHf_$-y>_dNIsTV*t|YOsT+h8Bs-p{S*0Qt@X|Y=tEJWyFw+=tQ}3HNq!dXyaQx z;$xIqny$>dz%>}=DwPU7{ox*SVKO{ldvwD{Xp2oiJFlpyf*@i(2*g4|sF+2p$^r!U zMmj&Dyag)FMvgcb^b5s}db6?m27G?5B!-SDDCvN(#n3n8)s_`&m<#LfNA8t=qkMPX z(D|1Sgbk^<(yTK&q4(rfdu+liCUbjOZ~BwxC^mF|md_KrFIMa3Nj&%bB$h+UnBV#w zdjR2de~Y9GzUd(i6Tds&gD>4z>ZOe#$GL_R851$CJlb-I{-_MH%JW9BMtX(%QWRk@ z3Cf(j%9tNBW{H#A0z`@{|Fswnbi&-Y?C#$_O4o0t_+X>?1-S+OrVnZDyu-tXJpF33 z)A}19Tj($WCTNrTix2lJ*j$3iOm_b)53b*FwT9Db_>z@DRZp^p9vN9Wmi(c_+qLn; zSg7;@?8Pud*zK)u~X!KaJ&^Pea{;{ zinPHVD^Z5ZfH}tDE;tV(x+f%6_}-g97cm@-$)v)S2OyGVRkqT6@paZ@$}X8I!C2T0wzioo6^FoR$5s+ot6>Ow88 ztioPMn^~~Lc6DkLh?^tj<52Z1e~Uv)s;sm}oXXb0>*`K$MuVdyxLX>Sl;nSb`01~^ zu?EBK|E{j@710qUMwjmW3>hx-Ii1e39P)V!hiQ>9 z_my0pyNH5r5C853@b10&NxfYzSEKN$(qw!d&Y-azVCd;D40R;%{R||)K}xkkwBGH1=`o$>o|W@9r|gR?`UtFGhwWJR3PAhiA)WE~0rS zf0^suV1h&ATZG|Ad4J67@t9gc8DK7ir?7mBB8_#SjO)zMQLwzqq%j%C#7c@#5}rBF zo-F1RK6@idp6r$UYIvB_;KDVny?i9YoKdnWoJ(oAi6wy%xnWt$)3Hp^XN^<%*NQwq z>0dhp;7`Jnc|5xFvT_xmi`3&iqGmNS>9Bx2t*!I(^D97;a1kZUtIXNeD)i;L+wtB~ zHiLENKm{V7a!C5w;(4}OWsFg*)j|4k@B4S}3@%AORG)rJ3{GJIL|zJr?n7>da9|m; zdyA+JvY`$F!D6WMLE}c!BS@%1h4!XU^)s36rDn}&QnLTLFHZqA#}r;ljK`=(r?8aD%e9%YSJm+e z^7hCTezkh#T&raMgQ>4m&hUjZMG9l=5viCZeN4}NcEYF8F)`zECi}>KGL)fr!A=m9 zmt&%Q0OF+;q8Exwak40lOHaJfa~UvxAFER3?Uu75e;NhQFC-!NB`n{jdFxdbQJMw8 z(0nHnZ(LrMfFD^tX%Hii0Uv6IdPD3VlAM?buVLgmG=;APTT*hf4kZ@;c913GO*}?_ zRPTjAFCc*!mbWSJr{oqD9U9)_XoX*oU-jYxmMh>o5_rduY!*oZ__)G$JM*6e%h^_0 z7}5=~=ME+Ytwb4i$1N>GA**vW6YQoA=9}f01-~yMXxdwuAmb{Vvv;Z**>8lh(yZ_X zHSJ*^{A<@YF5^L~gL3=wMj_qF;y$H-&wuVB^FI0LLfvB&3e~p3zTg3p z=Z&K5dL3Hd{5WNkVak2Oq5H;hW#4Q!u_u$mtATLw2CyzqQnuv&7)1dsr2@k=r%hK=!>ezE67!Od1u0Ob*mfo_)!Sj5V><8nL(Cco0`Qr%?UA(2*Z*qMQ)V8ri4 zMti|!S_AL4HU%Xs*a{sHU77J)(?G4O1ibTqeAS4+$1vip7YX?*4Wz71)`)+aJnjXBIOnC+SZ(iMru-=1ub zeq}rWu7wq(AT`{M&>J0w{6Lo##n-tcV!~JvN|)ZpK9t2dE}6P)vGn%cyH0nx@jFIw z&I~E-iKMO*VjlqEE{*8RLrp=^C&)hOg5PAHgaV5Qu4(2tQ-_Yp-zQYaY2MDx$vN(9 z;L9~Suzg}r!eJeun02R7*y61VSk&4nD>t$> zz>Dt*&uRtkTa9STOqblxem^dJCQ+BxZdbmOmg%+4CZwuTT$ar`>F;bCQ3+ArG( zcFU?Pn(7G$%@}d835&=s4XZxe3=9kcj=1UV2_p~IzZH@C--H?f>c>odrNixr1{+;v zz;9iP;+td)-Q)BpRT=moF9#dqT6O<&CIO%fp;Uat;#^`n7!nCgo-*rezWKfuScN_N zGK3r->`t7*VIP}`&^pvTEG%(V_Qb_zJu|CMnmjH{rW_Xq69Nh0wQSp(vJUH_{?sX_XrTKNi!~r4RCzK++Uh1@QH7p;xV>kJPSSDx3Q!qETKu+N=Pup?+0?uGDy$V zlx42&NY^1g&}bi?^M%3iIkNLh1#N9Jeuv)?3WaJR4R`SAiHR)O`@6dKGc?wSUBkL1 z`S9_{6*9mC#p@QvEp!08I{m#P+yuI9vs$>e3V%ciNt!cskBS}ZHimE@&Bu&l{@RHs`_Q>-1+=Z5|$+)GGx zhS%sYEkG!kGAW~-`LZj6s-vNm67Zy#uJK!k>30mFWXEro4sVVRRlD@ej8)Ij;?brWy!lnfDX5Q07rDTP|gZzhq<#WLS8FfsWU_&yj@ z+5@h54OI`vPM~(Avb}B~GE(@|2O@y9!t9NQpdoHOXC#U`P`z~eBN(Z3n z3FUto*~~L@;8DUl;uy&lNs2gJEK8+0M8~jf%ks^l#=gTT{v_=Tp8CT%S$&di^UDPY zAV{HB=x29iO-^(M&fw&<9HF@te(TTARmV^D%|Y{)`+a&ChVL@0oPFbPFaxKW>&(je zABRK6bxh0nx9ej?9)I`p$yf(5r#gF^XpD>dNlLdb!IU2bWYrOj;BK!FGOh)33nMu z^xD>31x1GU!UT!dE8-8oyt@W9TYt16_g~XgR{6zin_H%6fBY0IO|tVS1@V-#JvV|f zMEGBk`A|(jWwj5L$U_;yFczI>*0q+#yjR^syk<20S3i{!0?j^VdqW2c7?o`Y%*+|= z&fY4C&1H0)Ch0YR$Rj@zP0nC0u%0bhayb2#*#g{)TPk;l78FCIHR?+_LKnxBNbrEc zNf|;W*alb|FB`#soLEaM0+tWOJeC`CYzjGX!g4{yaq^e=Gtq+y#FVIeiMzgjIU~H#@H^KmBOX=ZF`_I)Hi^Ac;_rnfL9CXgG!@1-N8cX zdnz*>vRFu49nEW>INDZge1QAU68rTO##8S*$QY=HKb1oom6?lp4qj;TPyx4mDxhLf z($|zAE}D%6OjyEF>nBsC@txdiR8*xX6>aiR=PcM)v!K+$T=7lQN~O4deFi%h;P=d+ zNl}qWNZ8mc%|70H?cg=w(dkma#ksaOs+$l|Mb>8wA~XN;Vt=Q5*iivS$r8V;75FUb zxgC>H`@8q$p?pGq?Z6+V7>G);AgDCJ-uxp3>2wpz|Jf$y;T3)FwYCI2G@G&X!9_S;cOUkVVFe0m;M_^zppP`_W0K1yl6mFQr_Yh(2xG{{E;7sO6qM&R3ZN}+KIb+ zlh^PqDDKueyqj@BR5I|gnZgw}AQZR*;F(0@_mGvc==GJ$9cg^eS!W^JqiH~x^JLggSb(*B}n)Qb)pz-t`s3M`JxnNqH;!Ovy#jrYKR{DdGW#W?BMoU)|*T&n|Z zvGk6&7U_;aS@I~5GS0B`4!2~Wvys=^E>OFD_<#5TuFY=YvE4?tMLDk&7RQl- z+k~(SlCV>E959~UCOjJ&pmXz^kK6`v0zmXT)_=jeO&_%&WBXSUr}=FVZUDq;y_Tro zZ8V+&RI}V0&v_dJ9Dq2SW}*=L2Xz3F-Ui5RYupom3k1^aO?Hk|Oen=IU*UJxup@x2L_q2Hp%j+;dF|J~+)bHD%H=6|H7 zc>jNh&8eaUv{Ik$DkTZEwzB`H%cB~BWaUd~`?CV;I}DJNCRELPzAuQAP_N$U9srU6 z4G(wU20O=PmpmT-S8j~A8{S8a;7r^{c#oF{3A`H4RGYR2)+|Kx2Kf(e6cR<`7o@>2 zm=9hRM&bZ998dD-MB3gZ5oj4%UXwPz>=mBUeiAhOg~f`Cg!1aJN#@BQA0i{!vUR^B^4!$239CjHu_bnv(q1_z zV_FtT!9}gO_-*rY_|#ib<%(y4ho#zN`}Bjc?{rk!7&ij0z) z)73zjK1vx?%AO`m?C-e|3MxL~PkQ&Bppl0vL%JE6E5G!9raLFb(0(W>3lvyR=B(G` z5y-jG?sU-1^>3ziG}Uoax**a%i(0V`=Xfepe`=o#7Fkuta%vwZn+CF5D=qaK*Z`j0Gru(1d2Qrl3bT_$obpsBW%ZnAmD87UQ>kNQd z2YQ*(=l#&2mVZ52&!^%AtN=j-&&34(UacgEFR@?$E{Y3jml!9I_nQ+3`kcz44$>Vy zd2)P1=t@fexCIS9LT2n)2go;FeAR@O?1Cl(Ea*g_kS;|gL{Z@0M1op>+(Tib4BZ#> zeWu26|8|-t?yfHo5X=sD<8CWIe89I=VmqaFJC79v|38b~1pjaAYj(kafv(h)zrV$> zn+R^W?HIPfZS7~37_jEvPsW9}`8e|pA1@^W*G2sEIdD+{H^D-$`mM4KBpsj%o_*j3 zsSW>>94WQ{27h}}CFMWzsqY}efns&oYDJF!PrzOvVJ?H@(G`zgxErE%6vOuVsCu?j zW!5d`V|+*0peK~#+I__b^iD&p5iC}(d4BQliRIPMCOV$oT`{mG_1xzL9iXIn#$$9s zVyxS*aUJ8AmyMhkzZt*MkwRa5n*tix30)lqJjfr?FV3nOc>o&cMzyuI#d`AfTK--z z8`&%urmrZuQirO`HXWuS#TsjsudW9WuJm-&rzvKz^d~97oQgrHZ_{}&oGxNo^ zUG7!zPc2YY+2Q5oVJx;Jamy2{!W);{Tq35Jwg%Xz3I70gw z99*28mX0$t{97eK1sqN(7S%_~X}&9#j)LU;R*m*UY{$ZzD7n@I7t@X_jf>5V7g|*l zHte~11(7N`*TsiBjRgg;<=q_TcGzjKa{QioVQrnj?(SF){=!X1Jy|Yw9j0ftm7A55 za&NV?9&<92fm*euhSP(k&~&-z`@MpKW}GV53$yzZpb#Q2A1e$)`0{0Tvc2Ar(qw(l|~Z=$@3r#|_&pGaDMFu3lTP*l5Ky>ZS@9 zF%={l1Rr%MtEey&gw(!4OuDL^iXS92??^7%0E;pU^(v8H-s<8wNiksBA%W3gvCe#Q zUw2l}F-o^Y)2i;sO2a{1)D{Q~7{S5C@j6J@{19W` zlR$?~!=kEGFkAY_jd9Qr8c|!n?Jl`|!K=c=do9DinjRvYzG?f>spme@D5vk;dj-1Y zXrR<5L!~%*|1?IYyCgOLmF414ZsT{f_vVGA>LLtg!eObQ zT(0tT*tg*bah_I5Y7IMpU+gaY>?p8vx&{q#-iV7kJMl;BSdBjzWVz$5c^`|E144OS zXP5iHSg%qqzaxP;q|%dF;MA+(s(Aqc)BZ@u%zz`GZCx?qreoVssLwQ%=rXTZ)h1>> zNTp<2GDK=E=xP_k$UQrjc!IXcdh|mA+NEimHYK!GGfk^zT*$fEny?TeBvWU3Pu^#`$Ssf0n3;WkZ4l_V>))+C zp1D??VUg{u_%mgnZJB93D@05t3dXUNFQd&8m1$iPsk^2z>lTvqL|N|tk#_Qj`&x2GhZ$_27S$hEvdjnQN6FI7AP zY{l-Nj!b+YfL%_#CTHPO+5+u4F$Iw6FG~i_s5Vgm#)ny^X11qBbH?{JF23P4Tl1Bu zUNIl1J?CIq|1`P&NA5?MrFC0xpl=ZpnLK|=Py=@|pdayugkk1@D zMn719XXN>uo=c{2KFM+EF+cC!QTBVs`ufnQZ&}XqGweB1@@`ZSPm;~C$f&R3bJjLT zI?N9XdsZj2s}I?K7@ucU5`-`oZq-~0<8*9}dv+COy%$ZWH04_uT1fxgfH(J&JJWK9SyaqP@*e++;Qtk|?xosDmCNL__E7SjZf7{* z__HfB+nWgi^$>;?`2@}OH<9k8%1`}(A1_Y_yF2@H&bRio#IP@)%EQYuaMvU5S)vvhs1 z-8{h`gL$rk1C#bUEe6M0j-eixXYqG!V{@^;YAKje(PMDM#)YG{L0KLdgboO?$jt?T$^FXPKSO3~!Wc%PVQ@wc%)BY$cfn=Oo zFQ|FbNA3^;^?yE=2i5!g!8B#P4Y>{Q-J!c_vg?u{5CYlJnRfCy`nmRUSW(wibFgLu(m(jwL&Lm{^vMw{-f%+wg7#;%N~Fr=ROi zX*tX(oxuH2ds-#~97LQdQ#XV>%qyC^7`CfA^gQ4RWAIr)6`$8{*O8+d zV)#UV&f4K!L!EngXypAO5c63%&J~aNs%b+{SI-NK>|};?dEVX!MDQ~f4JlpWpQpu_ zr|Mi?@VW_?(*)j~ArBUgAlE$%4Y8B zzP+Fk6c^XAtjWPM+2h!AWU4{pL0;dH_d~;@al!Pa{E>^|&o3BeB5@-CDyl-|Rtd(1Dm!WZ??YzJN$5DowKH z!FRh_;#RDT+;QLiRx4qX^(&EclB-z5u;b6i2oz(|!ptFtW|t^c{;C14t$4dh&K;1T zLeW1xmB8I^*JQW;EVX$+ZKaZX>Vx?>l=~QG9m6!n9TDm|>rl5LDgeRYiTb-L@asDGrF|i8`p1iE(#nEUl{JJ-=YB0uAxTJ+cmddhGl1?j#y9 zW$}G0>kIocTnx&{L}3#0jeq2dQ+m-XE9P9%RLnWnF8wBg&uj;k3!5uWw};F9u~>hM za4$4EQt#~MCA9^*ulwetD8yuQZ}3a`{J@vvS3$5;hWnsBD4}Vd;Gdh5c9pivveh>4 z5%l*bw*QVzo}}l(!Ux+o$8Y!+;la8!n7{RH|2xBB3>}V#axg%2j>{>3nNW2G7IN z)HK>y$Eh{g5sgW`VNCO4ywzh<&ulCyi^Jum`5@s|(x+#G6HQXu9ukSp&f?^Q$m-=R zW(Ts1+Jj0CwY9Y4(~-U|B5xZvcX|iI}%`~WzNLqT7tVLrQP+~PL>MrTTtJD2{JiFSAM=Bvq3BgO)uz)rDSblxYQdW&LL?uzW|^X*{40{itST4ab88M9$9iizX&F7P6EuABrp(PNni#*5 zxcg@0&qup^L)0@7RrMD(-Cz7oWnG{%f-TS^*@CR(F#J{2a0vO(vxo;fGq8M)SmP32 zDJW}Rk0_3iE?F)Y3~8ftTe=voSL7vEoixld$Xl$wA-o)Jn;5cxqSV)&CY~zCTQPnF znwMdR*v`D-YCSmPpMM#kg2G0Za$G!n(bwpxYOv^tIE~RRKc3{n2O_u-+c8||&05;Q zYksnp;z)Nr%o*}fg+DY(a^lg3<^@7S(V%mRK6~+sd89i==QFi0$aJ6tZ6{^qV(sx@ z$0J&djw2PFC)-QxHi__2_24WX9JkRd6Q6rHt0gi?JAC+KrV2Soi4KXMT4WtT(=E@j z^V15hy+rm8j+&{*6f@_#hnHj%0j7&M-h%+I8=1c$rgTCK^!WQ?<)2Ih}6YMk#DlWM+y8NMTM%R?>=7lLt zN`qQi%X^@nISgN(zi%YiL^fI5?%ObH&1a|FK4Z&=OoN;KC>?tGeiQix zzDM$JK9024g<~RP9=C1USd@94Xl82Ezp5^2-vTR|a(d5#>z2Ko0?cKQ!1+&G{{MDi z2zc?{-!Gykd$h&rpB;YpD2h`FnW*EVV+gvA42YkY$hp^54NTp=o*qU-oT+|KdH;<2 zwSI1HE_)vhu?1NOtHH@@gqm4rvecLmncM58V&tCX0j48t>`x)(2JO0a3kxLaQ1`t` z(0+Yzf8E@=bI0>n=sOjX4+l>Bs|QQ_jatk!#I~_IQk?`KSNZS+Bi2~qr>otYvIT~j zy#<4&Zl^AACDG^y0!h1zimIwNTJG*sWrG_|g3DyC^J>ofz)BA&hDY7hRi}5u&-FfA z2$-o1Nbq2D_bET82*p9B8-4^o{y|f=Hc}serqKsGF>^XU{POX-MJ|+cgy;p41w7(n zp>6UN4hxN-*@IY1$8ntz;@YUqvg6eK=I(_=MFeNkp5xS|SK_Db7iAv@KHM~%NVHi- zWraFFtrQg^4>d-<|I3!|h}Zi@00{OX#&*z8^_qX~zJJb-Hb??peL8GNrW<@+48M}2 zr|()~R?((O@2mZ}T-Yig7WM@KzrX6});^6>)}Bo2lMQt*b^eH$-!*!{562@Bt_!tm zQ$q7|ylaiA3hAQ@;n}uxy~_ODA}H)V%1Yv1t)9D;6TenYSt9*r0vVfPhwy zmF<9C2?GlHYxuKkcOKWUmF79`29c)hn|kEZW%`b=_K;|x=a0*Ng0HGGd<4#hu9d9* zDgA1ats0G;2KjCH&cpMotz)6cfOgFn5!o^kmxvizk3^PEv`;#2r?Rixt}nVD)h7Zg z3nUiuDHH7t{)BF^T-{^|U)i*Bg1+dETdY|)U8L8b$bNoou%~5F!=gtsO`m0)HQvIl zOy8+%NQd!2tYf;cM*~ZtP?zn@z(C=- z*cQuom%*;Y7UmQ&8V=8R&vtz_%T95;Me+KPx6bn0I>yuGBQ2|EL~pzS9tl_e|HhBa zr!#u>ie;UzHzorFH7u&LVQ*YIQH`JA2~NKKi5w8~GAy8%h|zJzEh*8aS75bgOKZ>%+KB# zv$}ssFZr!DM${aMYVfC2<5-A!QE9w8$?o-L5~>$*Yn5N0nE(Vm92Xs2L-gmP_dU%i zrtNKqPmYcl+uK$I7~2niB>j0nf$?PadHwl%v6Q?KO}e09IXl1352Lzz(CxO7Ps_cR zZq38}GS=*f*38Y3<)>wscPZ=DP+sHXvf>WAKHVx~4h^>~V`alI zn+AV#G6Uk^r>wt?KG{Y_tt2r8-|>D!({J3%Ya!2#Ctl_O2=Ro}b$ZZ<=(>GYouV&< zt>e(mFkppbHQ&pVkHN$V?(6i% zNXp4X5E}!BcFU`Jhpi7T!ucdQj^<_@TwG%>RJ5(TU)IJpl7eZ6qc2)K>LQnU>~U)U zMOZ+-v37poJ|jybunB3nY!*!#`vWMKV`0@HJ1c>&eaSq}T3t;K^Kq%KK#z&TgBUlo z!K;Div!`c$mOcc}Vx3|w(e2QYZ7Mb^uOGr4uP(~v5n>4HPoswSdvW7#4(zB4--9O!t2t!GWu_Rxaafw|4!^kT9W1Kb{N-EK3f%uRmHys# zy}u>A^XzH_tkd?FP{Lz8=+-mskKU(K>^wt$u!|Zp?IL8sz5b*sxU0A4`4)}`XH{@B z^gPE3`94n0PsPFj(D3d^IJUy_PYd7}D50RYaBEf5I*=I5Ok3$Le}MOmo?hbTq0p zXa$>N+Za!;*AeK_`RYloAcBI)g*i->f-7@pBn^Mxt(W~+bEMXmM&qY!(>o{IvHGjy zBktL~#=8XSP1jHGW;1P#%`I|{#auprgPA>l@<~kjNWu#uL6PEIuP(C;P`zBsVQk_7 zuWs>4p`k0<{h+?Xz>(o$=as%|QjaOW+A>s;mX0H=E=4gf$P4_Z2!yM{RHyNzEi-(b zIM{Zgji_K_g|qXN_bj9ltSV~l^kIzXyz{;HWd@1}3lwVk`U-p~4XgM3<-#O24l|5$~mz%U+s~^R&fd(lYH@>%2 z8Z+t+y0lK+JHu*yp`vNM&Wo|^L|idTDrAi)A^Vp-J{UQ7w<7psFFffC=`HnFWCocgsJbciq$obSxg8AM}mUTVLG) zMA(deXmei!bkGsIlDFL$zRQ%UoUVBo+=*~AboIatS|L%@Ll*yJOWpq`@rs6wOk<3W zM+zDfTE3Sfc6{t#CMc|qviDiKs4B@pxCsqMeTCTbwFK`$=ohejx&l0{ReG z`7$cCk7o{%V~`7D40eglc&~Gnvd^61XMPk&$WgB$`6Lf)Y=?x;PS{=dmPWVE$vn%V zR5W{;>i@_zI*F(D$yco~Xb9{yy@{ahN?`Dwm{8ZS+52I6W!1QWwDCJLK+8qMVz1Jo zuboYrajub$Z!_umBF%*1Wpzc8<47lbRA-5nLmQeAx}87pDgEk%>S}vXlnXP7kO-DO zw6lwY(v=A5A((ZWt?R!Sq?vp2R=dY}eZH=j^9%dCe%u&Pt8E(FoBqEu^_{PiMr%)rY_kHEc~Iy-doAkpVi&T- z(i^zKe+vqWXzKywM>{+zbU=CFq?HZQysRf{;q zYX9fue}6C1>&|OE402nHe?#~mU`ucAq?c%#``L)x9)lJMDXk4jCT#Z5r1RV2S=5pXX|b zV&-A`0+mEiF#m@`f%V$Ra-*K%_iu!HsAbK{B%p3HGakoc8=T!TTuObULP3Gu;2xO) zbq$TezQpprkEHj&u{`w_opGP_xK77*pI1BIK8IS&T-j>4yTdrStH<)K8Th{JN`$(5GI{T+C35ehuzi=tBTnZ?-Q&|bli@DWD|Khdxefn>bJA%H(@wJRga@JCj5l13bY)4 znDQ8f$ClqmdPuuCoqa$flW0=E)v-MV9K;L06 zVI~bEB_3mOSTGyheLRPSB`P8_CHI9-1*+DRtV%ZW$W72KB;A=i6 zrr#2{Jew${dQA;&6G9@a+ce_<)6^RfHMo-yJ_J9M&l()wZFiSf##E%x?JkFM}6wjJo$MEZYZC0;*L}nv1K?MO_!+t`P@Pbq_v_fT7-Qd z#CjD~S$)w#`FoA=}fJ9|>F6)HX*d1GvCsAehL$@bh4P z8&Cc}jrC)wG1}%ye4J+tGG=D`jSKDaCCP)!r&%=|{^Sb7H^fCPANN6w3EoyUwkSM< zLI0KT#bCJv4iUG9TVie&=h{;wWZaHH+M$+QURgG*yDyY+4RP0F=YP{>ek&nx5PV#W z<2uUhwf8&Un$M>Mgvma?jqmt+!!OYNtZ0N>-{5c3^m5Ax950RfjSq8AS%Hfj+}u** zeF+G4``{;eAeNqZKFlr!NaQU(`uX-?x#OJSXf0~8QPm3qGK06uGA0&rDEsOr)HRmRyw$f@R6C^vzl>vv7JAhj^`4L4b=1_y#y+|d&#m=M zntC<65F)@rqt8|&)QFp7gv^G_sm$@Q|2gwjTiK7x+@s{1P+`G1}mHmUc#yXoW z8#H5$(b~A4dr?sy-f?7JVM@^aQX`)F)cSi3#^*$#F2VbyR%N(Q?eNf=u$ z;tm4>uqGsFsr<}@twfoj>_v8G1v7Il)+=N{R%G6PmSTIze?{lJFmcR=f>#&i$Y&j) zk-yv8{GMS6CpS*TMc^S*;tto#=ZDr6vz~G?lHW%{|B3#{;1Tk}+Y-oD^K$L!`PtfqaEgC~*?xeHCp`ZUHN%Ot}N&5I5S2gBs z$w(dtp0hnfQ2bZg{~Ma}Lm)`$^DL|$-<~O`!wqaUpxgvR^UnctD1khFr#wDI|9{km z8$jL$;Cbh(G5_0hR1imD!OYJot9|#^qB_Czh;Jo0x96Dh9bNa)dqqRr{C|#l!|pM3 zA5r7$0oM3W%>?rJVH0gZTG#UXzZUfzzlm0cx*6ciKNsswPYIM5@u;3cz@PsKNRnD% zaw6XC>)$(%oAU(u@X>o|SzG8oU%#O(TrdEVuh?IY^L)V`R}OI;W87XBIV#x9M+!VB zw;!jd-z@ik!T;Yj=TQ&s#W|D}u^`_#HdeZ@{~^~Fety;7&?_Z#0V2rbjvAjm<=Mxe^#+j4l~5 z*at7U&jkPd{`B~Iyold&BZSQJx0=Jb*72mEqo(oXW=TvC5%trEBcxx_IUcFe&=o`&5ZjT0Tlx&$~JmF}| zg^|gf%JyWZHY?cPKG$o#yaQ@bueU=b5$E#ov2xo?IbwhEM=9KWxnkTH+C#QL_7}|! zi;_nw)=bbdjAs%gFFi|g7(wN7IV7uE+2)^^4|q@pRKH9E$DO+&W8bn9^&_Zd_xHG` zU1G4^FHAMegWeUu;Y>@saSuGM#Vo$&x-gde+K;IB96IjKwNGw2&RC1}@^w~?n<;_n zOLw%h*-;&rUoMBM$&3v1e^I9$E%I8su~ALW4eP;L)mRbPJc zvC6Co8Ca`;91%zki@MyKByhMKCOBQ#C@lAzZM@84n9S%lH10r+X^)t8y>3BtbCYU5nvDzl6>&q$e#l zv=(4N7@cpe^89x}e4v53r{QaI^ zK*5^aX{>Ku_-*;JZ1?k88qb5jc##+$y5XZ_!9_g&>oirI+3k7@<9j3})rAdbehwfR zZxVDX)sq*piRqazKNDs9wm9Rm;@+6Am!bZ{ZtVp@`LWOm4^7L*;>!osG|6tg&|==8 z1dEE~gpe^^(Crqkqov%U7SR$RFKj(pYqNwWM0Az8W8bj8e_$geNBGwnJ(dS&bTX>r zc}}DvKdtCbrmIzFS4sf&=QOc3Fbj@2u{E045~>wft*#Q8yUmH2=we5^lv~R9&RCHM!$a z!Fweyqx|1q0L!sG%L&De(;s_UxeU98B4-KQMj6r5Q`0cd0)OTjCt9z!PA)Y1tA<#W z?qHmCU|o0MHtbDEyL}(k_Uztv|D$J(1?GZ&{SD(;I`H^;gYbFXjFYnH5w+DOLiobu zj9B7XmIRq+9b^5kaEI+UnzrJxVx8HOZ2I|ovpZhsV5`JH3BLmk-7^#8mYj(DzEC9gJaaRR@F~V?zrhn*M&^4 z;N$rhKhQKmx=v~iOTXH^-)X`cCku5OA<7X+j-ZjR;vAi%91FVc;*k;X_z|jP34(_= zmd0O5mW~gQY#G_GI;ood5_Rr(KyMk56?{;Rf6c^G5@uHnJIT2`UD3I63T2us7GnN% zWM6$^a6IeoQwU%0+EY5DI5T{&+TCX^uu-w#j$T-s94Es?^$J?{zXRuwiz~%Aa&v-W3EVXQ7?OFWQK8C$jFBGebK*yzrsqT>Q z95G2&U=8K9JS6j+2w-kpF8}QTV$^Sq@>?y#TVgp3<>lJ{RxN^GljEiD2I=j@UcE)d zrifCErNdHpN+~QKF&km%`JUOilI+<_=P;kUaxx>>!zhEr_S8SoKD^UO=5a9ZT%fW) zFWO&QMUOFrb$xa|0`3^{uXA>P|KZ{U<5{2O=8#GGF9D@Cj&ETg2_#K6iEnsB$GY%m z3tjav|H(#i<2ZWtyeSYK2w1TCA+@SA2TyKg<*+9{>zMrU=+*)r{IT?z?Z`7RLKW;ur2f2p_-LZAtnHhp}0OU3enZ~~R7 zz)yXd^e<_UK>@U0G%WwW9{(@+8{PH)_svm&E<3HZfUa;Op!*6a8%RC)13J0k=M)x} z07IqK;1tHpINMW<4csokfc(Wd&Ow?sZ!AKcQ-G&C(J)b>&SSAtliH zuBEZL#FM3>jAOW6F^2NFO4UW2PBcX+g(&8;!;vPH*)$JZxexR?O@) zFO;Je>oANHKQ}Ym#jdZ1!5|C%Q7Gjo*?2p8hpxG0)LShA)1B&MoK993j_~)G$ZS{| znacdU!DRA?9Db5^tTcD=Q~WVP?6UGG zi=Lun1WJDTN-61$unD9lL6zI@2=j{JU-_e;Pb#h;q@?BX(2zhptRo#0-KjR9|Dm^t zDypcGUp1}Zdl!f@(lif!_+kWz!P+l;4iweW)QUktuej%(v&cMB{+YO1g2YC4C3M$M zQ*VC-HqAtaj56T^vB)u=+h6gY;Dvp@6U>7bfIzxzF z-~FO)W|Xw&xbI0@sumQZlN!j$k@f7SN>)TjkXy-dvt+RiANd`b5G-VM;sa~DP0E{? ziXZs0Ev$iuw`*;NPP&}}H%kk9(8H1V!;};+9y(RKUN2p{YqkuDKLl=R&XXPr90OFW zB#UzUkKLvnVr}`*nXJ-fFcujiPP3Q?C$m&ZzCxbHVcE*v6KyMur0{0xtzub;oGVny zc<_pRwu&=SF?L6s4_C)3QwHNtHtpc|RMi_cT85i)*^B&jH5?y3eZ`MAdy%^hHUIm~ zkhJL~d0%bH|KhcLEP!)9(5#&zL?KsDL)q7YGt3@FiTnKiuUV=<4_Ig>Wsm(W^A!m_ zk^+2@t>Dr3zwJn6U`Jw2;>qqxQjHq7p-g@d?*N z1-YlE2Q-$CFU8{ItdtAhQ#1VX%Ag)Eme1a7WFw#PeS!?&40sCs1qdFEoMMT0zuLZ@ zAgH{oh)G1o4pBf;l$7j6{Ny(s+vzH}_QP^H&h^ifWJp-- z|HIx}zg5+Jd&4(d5Trr6k?xL7hjg`Q&>v!MTwW_AXLAkb5oI_@fz;yi}o}yhd3ju z0#>|W$LRWqV0`T_1Aln)Uhwl<0a*Ia*%@9qC;wY@_7{Nd&`=CUXw2sVvIfOqGc2KcwE)8hA2W8a(#w%}5PO;HSCkM``$sFv`TJ}=f5fMScDjtN-$%cwHA-hN2 zIyesPFTVY4+gq{~6G%J<|B)BGI!bBsob~=;EIPkjI;wNq;4^)(W7n=`iHbIsae)*l ztz~kKf*Qp%eUcUzFE~AFB-(Mn^K}RfIU2$1+&aPUdOUFv*pvKWRzxwGnmr~>r4P5VNTFiTup98eko)@FB|LbU6!{|iO)5&H79 zP{l1jjtSXZ17!NHoy`6yF;*gv)9Cbnn%wwb^PuOi8cZ0UW7X>*<#Q7f#w61Ps}4Nx zN*<{0VTQ1R(yRnbM6+0_W2AG%UlbUrGA2&uiw_Rg(#AzdH3_^Fo0e1XiDFfxX_!DeL~6># z4)7$Fa2ibu&<>n%N%$(_Cm=Z2ohwjfxYm{-sRY`|zLu`RjqA)*j^QJXd{aYD24Y~M z@ll&T{PHQOg|*==5@1QWW*dv~exQ_rDNeaqN@%2tj2r!IU6-iT$nYJzyn{ozfKc(j zsXQzSG-HRzfPwIE_&#P{_Y1G`NII!pd|=Kn4`U}@0O*#YNub!4(W_ zu9@aLP*;&2Ao86~;r%RC;CDm98H@Z3))c6;nw-c5?6H)hBLaW;M0g0U0O}DB=3rqB zvx4E%mw6d$B@l8_EL=NXx;F7n5gB zH6>uB@R1qs@_%?SdqunA05qDOWZ=UnCI;(iSd_(6QfAAwJGonOHa)oJTP#8K~0U?onU=4%n5r^p*B^&GG!OrTZD zC<%X=q4|0q*Swel&Gtc8LY#>#FeP%$1p7*!v@Gm>CJaI1o5(nBWFS7F1@?+?rf@Pb zCy*cfZrivq(VXCY;toT`pZtautc^b=R__0SV8=h{$p4g)1Gy95)_$N0)d-psdrDbn zoQWFjkJh*IS))(?@T@=M2QHe*KTE>wjZ<6G#S+G?3JZH1Sv!`?!b+MI)wz$Q47D}`lx z8FNF7=VkH6h4>kIOWP!w*UTw6c~DxaE%iyfQWB)N#0p3BkmS zZwW&4^blLQo4%+dAxZ_EEysy9XtjGHUK63;BHW6^CQYOMjbIuJ6lYHx4}l!> ziIJpnDL96_wB-Vi%s9V`)Cg&9U1lpC=&YW=2ma0TF!F~G8H}VjTAe(YqF8Qnm2STL zkgv9WyJtL-5{8~{L*^5+BQ_In_Ae%_rVdDe7K#H?|98+89k_P{m(fZ!8w%(y1-lR| z3EvEKGe>3H!NH+fkzdR;kGt*$TclZN@ese4af|jtLAaf5 z#~;tm5Nb*5WPpU%>Q{&sGp`!&XmMr%M-Yh2G*g&DQT>yvY|L4+zBpGnv}o_0Zz%mb zLOoVZ$V{v~A)yH$t%L*HJv`M>$#eo|BWgFBzAGG>@mr9|j4tYcp?KPQV@M6~gr>b@o;CqLyPu#uwC03rI^icEjGr*!jW#bEX>M82nRMuen7xY}Wg zSiyH_@JS-JE#s^SX%^eaXZUwSiBfIQDBz=Xdi$S`vRu<^_mh^vj{%x>O=SEq!HsmJ z2*t_*MSWHf0=qSFF)aRGdkJT@R2_t(!Qg(a}$a8I>k~U~^jHK`V)t z6*?sGNINpoxmZwE-WuY&Iv;wtUO)1mBTNchY#=3W7`M;+K7`Mv0o_DkF7?%miX#m7 z^@)%;ICCW{h>GN}l}US|NJYCgc6WD|Iw_ZIge#v#M@Nq^XQuLUBHqf%nw-*JigE`7 zaL7&b>7N$ck#a+txN znMXe}Ub3LW8$P0|r7g`w@qPsrrHmUdSZsW7W=BtZ21DmNW6AjKALVf_=AnD`SjO$+@*!_ zKq$C<*8jE<<@d{7G3SzGq6dFKgTKnz?rEg$VIGQxyeSyyCQleWZmDTtLD%v?hPoNr zN|S*A_LWqn`1>Ed8-^c~RG!8kvPospp&g@oIx_Q3FEEB}H#j&HIJsoXtotE(pS3f} zi-o5V;l2E&f(?}f(VLr_zqVWIEwADOwVf?OPydnkpbkgWm>7Z*XgPwj_gJCQI}r@M z2_34?%*Y|7w3&p%Mr61!vGPWa{AsylzeXkPu4xo}6wNAO9qtth7eSCtRU5-eNJnaW z1|_qsq>kJ#@NE)ueu;+HaOkylFxAlqvC0++3cYboyvq9gXT$I)%@GMaB3}Ysdj?i_ z-r`-7PJ*)g$O?_TZWeYE=xTpx^Z4`r!DmBajw8TqM;avQyolT$6?7UYw$NHSzCTl; z(i19ZL=}Ew7}#2B2VKicaNI*WTzr$mx2=<~M|k$iLp^?I+K)OZpRTW(Y?#NgXX~p! z@>QkT$wVF1n{Lw8%!>6-Icj;<>PP}G|#}WKRxN3Y_ zNkUp)^}E9$t9TT(#=)^sMG zptAOF&-0)uYcz6V$E-H(7MlbKtLjgp^Bms8i>z_(qXNe(IscOvebqd6+K}y=$wn=3*v9eRd@XD_W7OM7@g$zDw*tF8x()>LT66Zlm^5OFY+kd4mf?-sZ0qQ##rS%oB`Zj^ zLL0F)l)b#Pe-*|lSd-XuzP%L|hLbA9OishV)cUQ2_GA6I5j8fi#kZj|$s*elR&adQ z*!SnbG9SBzUS?7Qsil|+ewkKriD5o>guMQj$*Czg z*@bMx)w;?cb3Z-pWUWwh0R2N3 zb!ZC5eo;`2pVuj+#ejFAIa_a{J^I8IRA@-rh^Eo7hxPXt(+IPGYc6z99=K7G=bc9O zGDnrDe^^z~@-DR|DZ_J#T~)zbrO7~N;I>vi?@F1s4Acu*EB=j#8y8=SN1>($dDW+e z!8?t}KDs2Cr|!p!QYr6DJqw>kI_@kt|(?kOuL9Z0bHq(wrz`Sw~{XIUJ} zY=T=1gsiM2)s@1J$rWKv4|V-9d-qkFcinJ9LFz31i{bGr!5{4^%|i%I$(p2+BxHVl z!7>zE3kTxY^-y0HuxrHt!+U3Aut%7d!KbE)V}^@{*LYKd6Sd_@c%fW!9f@L4I$X@I zNPE=)zv0n=181datrv=sIL|gs~Nhq%Ok-AX6rrzGDyY zm22f7qf&b>Rf^WvfoEi1f4m|7G4CD<#RbTcz{rIKSu3?qDPpphy}+7QfTYSzm|ka> zN|u*^t4uJmMOO+VVXDf$I}2TcWy@6jANoWw;93}CZyWTjlT-HgtmK~rB2^mTU3P!* zWQ_`y{q8BYpmIR;w`9YK&@5KeY40z!?pB;Q1iWFPfw*yIUNle{M zceR5g%ZIV5A<4*JDB1|fJMwToov~IZo7)#>VEeWKAMEBNTXijl$mH3Q`o)`y6geTz z_Vg_^y)Pm!TKu#EO2BmyBy5SFOKuv5_(8#5T&!HRp`6vOsB60Rpk0nAd*ojCu5Xo7 z^&J;w|5;m;T)6|0@14%cgF2-y)JqLhzxd3mBw+m2S}#+DtNXDY9XSl}V(cp|rmhqM zDRZP8<$A*d)sqRbD~Ew`-QK5{d|EV!Yo@L`tv$!c$F3_IBfI zA_X!2hwjw4bs1);vjMQk=KXShrryz<^H3dKXKkAEe+bHC$Gr8Ee^!bwW~tzf95!+rU;+L5LJ9$o|*a{dojI>>shDI2|3Zo-!z*<2Q&OF+7?8;skP5 zfW>~GM)QtDeZcPkwDZco%g8W&;g+aD0(lXAe7om>Z3{#a}zI39L0@nrVxO`MkkP z1Sr-&ENoB9@;bO%9NG4jW4;%%ba1$avohrh8aTO`m@IUgTfwc3-ZRb+)i+!=6b`UJ zZx7U@%9k1U2v`$0Q3VC8sphF2A~Rr~%Jo;R(EAu5`EBsu{T%X6S%=uZ<)aId5?(l| zcQp>RN@JW2{iN5z2cAp_FD9gE*pNuy2b<;{+-)@UkcPbBk_Dj=0L7ZF zCbT9uEv>C2ggX{jF`S+i1xfAZa7qc?D>{cd*MV23lmOl+?+Mx^9pdPNadc_5a_;VI zPQGk(qtiWkVYT~0wWZ0|n7>R`zJMqxUUknHgv=WL-b#O<-q)JnOD|tAZe6)ddVm#} ze|O5qsr8nKprx{AnX&ROp$1q#7`;%XvE09m>l?9Ix+YLR}-b8=x~`Sk+6dG;>46gUv3D`EUV|7vHHv!zuBSWQ9y+nH>IyBr=jJN+kAoC2>YU| z{4}O&%8e9zw{O=L0j@G3u2NLl(d?>}Z_CT;;98?)cx^YGn*S*&H=*IR9_W-8^|Yir zo_=!vXukHletKb2iI66>mR_c>KK%kfzV&)<)r$6lM$-z^vBt}bHr=DFS6hL2Bh3{N zF;-zj%(VhEeF&Vk=@&r)ZAeMgkn~mSVNZYI714uCZpW%r5`I7!l6@}rCJpU#15eRd z<093z-aw>;fP?Rz8knmlihb%!StGhCfd|bW{PhP)T1|C!FJb27ph5;*_D=+T1%cD$ z6}e9RjkncAvu72!+hfwcL2*GeVW~zfC&d+4J^7 zN!e$`Ef-RfwB56zrElxPP=d-rdiuNHj~G%S+FiwZloh(b@LZfZ97n~1Vgc8d3q(dW zKSpCC@0k28cT004p2BNyrdDk{J<+#q;dRZkV9!^%KDr%a&2J@CG?P-HOP94ILm5~T z$G}=J(%eg7&?v=BU)pcOEEJbx3wxPWt$umlzLXMjeiTvUL=p#Rr4iq_VomFCUZJMw zu2T-7qQwBq2&JLvmFIpGF!GuDea2DmnDnm;4k*1U>!52{x{=?E&22U9k8nG#tqW-4 zB|h=jL7i;lg#%R|TmVabO7PWw9N*11y~Y@gr2z7H3m$+jwgMsXzAD1eh^VkE)kuBLN-AyxpBD4O}GwaBtz%r>+)p=J$XO3b?(0i(^*_dF#L@?LII?bL16^tFBV7=4lvGX zDTXrWFXR#agm}heV*C$e`X8PzGc_>I281{X`LBiOf1y*MWdMOdXRQ4?=I6@@Kh{(v z8l&rd#I5hpF&dOzdaf9hUUiV6N!CG_&bT!On|ZJyjb>bd%e3TlC)U zZqclNvWv&gMCrf_oy~*U*;)N}9g#Y_Km$tx7MmIl#$Zkp5n{gEh{5LS_^qZj)?va1 z2-9-DbnEnNz8MNT>jCkSw{Ns=zO!+yym`H|3D&BRgKbGYz$M?&Kr$kfl@ezc_jTv< zB^t6a(8<@YviKw*D?R<(oFqLc#_tmDGeW~^P04^#lNan&x~%e_BuZG%Wx5Q=BUH4r z*<0T;siiwUF**PON1BE!QsE57SJ+k$2>NFV_}o6W*^C~}Oc5lmUvg@cR#oM3o{p6x zG3jsySDJ`s0Oh{KVjXKE_AvRak*v)88vFYn$!sl?%A8xqs>QZ7rI3tr?U)VQ6t}4S z8fZ7^l0g>3bUC?xEn^{ZbrK$MAf*9(f*apZbv-Dhw&xig5lQWPdL0oY(knnx$qR(A za%F4hK#WlhcVH&gU+?q_fF|p?Uub#%6=We#=yMdc&EHgXTi{(2ngkF~{q?TRf!M%U z@16TA_E^(_*pt(z4*83Rt4RXHSm(8y;9uWD1VG0(7@t;H{VOI37Y&DF5V6qEZDHWnFQy#ag3DLsW0J$~-JdO?RL zDeiyMMlhX|U%6X>eCjGlLMY#mlx;6}^7ojJl)frhv5CDq1DI>7w3u=v}+ud+KAq5t~Poswp!GDDopI_09x@3RkQ zfVM9Qx${T4`AB%p5F7;%ZkSu~4uSh;t*Jp;_`qYjNJDA`LSNxq*T(D9BHL$)g}wmT zIY4XrU@1Y6`3BFv&)k5l7;@)-Xgd&j;0KJL374+E{1IuO;P$ye8y}6K%N)aiSQ`(= zPkiK~lnBV9HqW2D?W7XR$GNG-l>%h`#2aGk6~U3C$MhHpPk%o@`K^XT?;*bp_4K0@ z?Tr)dmJAgzAGFD$(8(f`(&_84YMJ~N^V1JfCMMntug@*Ey6`{;DpF7bMdtH6nabft zTwJ7KR+iV;t(FBpx8A3}m&!vfm?c_cmlxvv@f<+aK|D)>k6P|1cCRixJn~vUXf5*l z0NAv^vbh*-_|$pd6d24XmD`F|ax&tz7zBOe5lD;f0}b4lr7;89E1c;|&zs5}fJZj# zRDZKkB7qr!!O6y=F&O#~A-K%1g*f||b@K2YWXfV-UHEZAoDn@nvnetrW@gusH2bZt zrWg2ewE88Mbh*X;+?dbE?mj2HpC6T>B$xJ?t|Xp-yo7ggA)nIXCQFkTzg!Zg>2P6r zK~P3c>_}kWr})v2_I2U!Bz&sbGF6ba{~jIHJNgiLC`GabB+ZJ&qZG{>r2y@qXx^M< zdm!hZV2hW`dd;Pml&A{T4zYL7K=wix53x0KuZ6I;PmNeXTH8GrT7-HbS}E2rmGasj zKVBzuAf$f2)O==Sv~D%j|E79sNlMEljj;@7&Ib?m9+@Ck^ zhq6I4F$5>z(mw}NAqA1(DM&<9%QDBXdW?}#CdHPPRDul9UpRq_0~4akMAqbnO(>l( z_FrT?K6DQS)6z;9Ycpig63hE5VKE1e$%<}(#o{$gn|g&436Djjwzhh;ARJu)Y7Dxj zJjM^+CxV??oTHLZfGu>T^TUA(2y6 zqKUJ#5@w*n*82yEt9g>&2i^c;je1o?|K2$h9|LvplT-%`eGo3e3`imWx2y;W?Gw#= zEfNq}@n4sqZD!yg5>-}%Qvc6p@Sp!61Ki3mk)k1g4dYG#9B7nCSAVg%X^?{zqdQYf1G)kM)6b}G@0-Sy{d&B18`VS-#1tRb?>?>k^{^t< zGz)!WSR$ZA{uLW=-fwgH5SH`niqFaapb+Adh-iJ-T(|_h9eQI+O+F6+tZIQk_Q}xfNPyg6t!&YB_?@dIfk&hU`Y;_vd9EF6~8=r0UV&`?rn@b1+e1rk_WSTI-nO;2q%-FokoM9~Bb{>8la8bA3# zA-Uwk6wJx}l)w8d3^opd+O3=g^zbEzHw+=~@+lO@wBELb?E~y|yO)jK@5tv5yu{yT zINeca*c=9$`gqTZQ%I)<)GgPYVH?eP2rZeT9yEttq`_in1|E0w8Xq=AozAxVu#P7Btf{ms9oDFb$2S>;AUe85Om{-ND(`i!wlQl)pnGRjR zQgnUyRc-Y{lf%tfo7cd3`{y?ky(WI^2Xz}ood=J^5=<@qLus%6HQtO45N*_EILz{R`NE7Xx|V%~+Nz@I zaF$j8AH|@DH-Iuk@)i)Cd0w^R%uDzkOfW9ddo8VNfEP@>p55wgsPW2NdCh8*0^x11 z!YR=(+_R7wJJdodTaAdu0ng7OP**kBozhnz2+6of~r9FSP zH5<)xn%sFbc^z$TT-1pk)w8Hex9`qpIJJ7rd_!zz_4dyVEaS!B1wKxa1}z-axMc8V z2h6(x{kQ+PCzLzpU(Ckz?ob{__yq#y$)pR;hL!(>mim8#=2`abC zaEjP%7NqIRd-45Lh$CRBPzT=16gQ0nL@o1x?JVEI@;!^=x49U>+D0%{6_!UJh40Vh zx?9eLS}@g*X04r`susZ^Kn?UoaMpXfE#m+%UOgE#%q1Uu10ljm$Q zYSl`YT_e8w@;>=GJd$$kH4TtD9*8+>D3S z&Eug<`(&q;CL#+CE-hI#y;e)LdKc&sWH+sz3*&$k&b)d5NA&3FEp=d&Uv{CRB98{~ zREB$@pE;(XRo->$xw{XZ2zIc~?Wj|D5MW3ey|UQ(jQHCYRr}~8R_mjlpYOJKpwR%- zQr1!|OAsC`vH6S7DWgJ=2aJ6Q-nPBn-E&zeD6J~Lf{LA~iUZ-H@7iNoq10pQx6Y9` z5l?|F?&?A=Y5oOrh*MXXVz@YC96)Gf-dGq=18BE?o1IbH5SXr7@k6dx!*cdXXH}@h zVs9$EVu)lmUTSjnuBq>sxMWS=uRsSm1-jG%ZkJ*i<*wfcc*Z{VhtpKK)IgyhA;<+k z2Yl-Pyhk{y%nAxIv2bT)LMkD}@vIP+kSh=G}e1RsD2?4XJw~e$iRi;=&hovKIW45euLXgm6;h=*VVFHR?5y>f=S{L zyZf;*CVxCD;lR@!SEGX!HeVC@*4Z5(3Y9qz{Mtsnn@(ND#DaG!7sXCVTKc5+RzLZd zG7!V4YFGT}sJyW%J)>7OBp-KSMpmmRuwA7@CM&&JNPU-J#_gHsyffQMM$Pc&j9)4O zgF}1>sw6uZEgR(LI-*yK3M z=6Lr2ToH0B!pCGAqaLGJs-+58vAQYZvyI{Ef=kdhm&~h{*&n7y*GhJRzE|0`YHud! z*IiNY4Xplr5PanC&A_bF$-Da6s;VACLr?D8aUzr@>msxzmH1Kyu$OmR!i=d;emFAo zoIVt4riwFM;e6O%ekR(WMLsH?pbgLeQV4A&B z=Jbg#5<`1ZM`kS4cEc_XEbo_&{HXoml=xLGH${8Vfpb04x(w#Lrd$8WC1s$ z6P_m*8B^5X{tHVs4RcS`e=AeZ))ksbGBufR9*iS? zQ$QJTjZ`<1UY>sb8H1}?a9K7f)pVh8n*}-qCmVx68FX9R6IOvv!SnM}OUy%V1zV;iu%YZ16cuvEZMot%t*gt)S8bgk>0IKutwMXN_k+!shxO1$F31 z+=)z?$F&2I)$3G3t)7zEVW}ap7sgxaXCix$?Y-;sh>zIaBgNt$4nX|&x#b@^TF(|g zfXsRXH0;e#b3e8OD)!=q{h)lF;9p^UDUjk;>mgJh8JaosZrh%7E1@XhMPEttIH}d% z*IL7Y4~l_8b8nX#KFWq${b;?pF>)5}jt%@bj39;Zq1Js-SV!YZKxpw@hI2zD`H0wb zwij>16_x04TzjaQ8Eg*Mh2ZdEMfRX8R`Lu=LE;zAR5A;gy*^xyeuBS=z9_KkI<8yv zmzA92Tv+ViIcGkc;R7Tyk zm27t$?L#P5F}jMVO^%gLSMi1zB<_q}Yb5X{$A`ZGvkO1f>s;_7{W z9%T!jt^+%-hwRbgaXy!z=V(f2$L-Mu;nk6eizh8DqE%bbG;`qr8I&a>D|s>UC~gjv z#&!}GxTD!`+BZ^ajhx$iW7#LT$CH;dAK)~oeQ$;K5j7a2QPJnZtC&JV?l>94;4%8* z(#|Gwr#+nVS=W_T&x-{p{b9YAqftzg&&}{g>{Uj2RcRRg)4rwTe>ky`xFhVV%qTM6 zgVngL%%zb~3a8mhkw;U5LUPkhs=jx6IZw@Bzj)}CT$!6S(!CCg0g>RTqm<8HaZ zR{R4lETLSWt1uiZJO`_%T-&olo-Df=J!<0s^t$egY%o+HbU zhG<(&(;T)w;uTfeUc5zyVG1ysooVofeAkd%)_Y@z@W%IHKWx}Rmt=f+E)@2bQs^9F zx&_ZY^k}`FzWvg37Xi3>MMQ*hGN2CIjFSZ2vzo#vr^m_{vzG3XnLlifE&APhj4TlE zHHN>^IAz8{>d(Y%di(pAtZdG?sVSD4o+g+4$MV@#GxeZ66-K6}yop_g!$aR3fhmjX zj>uopGSS_V58EFP{Dsfljv?35l*JSsEWHw`Td@t`7 z3+1f9uaqUW66yk882ck?FTXi_EaXJNT|;Z8C04SlX|izk0E1(4Wy+}Ay_=)~T{Oxu0QK6I*E{GC#M_4WI;*$yY! zQeO94kV06j;ti@e!wW@}qflP-QSme6Vv@%{(G?xel_t4Bx9+H4zm5wtGzw9rsO$w| zPQ}>z^0UOmG%!4EsXlLZ*``9uj$LdNCH6MGTK7YfY^$GfxN|3-wJ7#&l&WAVm!I69 z{<5PDp|LG&F}uu0zBjqYrl$oPBivAy{XASXs{ ze$W@+0FqQC7Fp@eXIV_XXKI43tubATt|Qa_Ty>kw&fmKkoru!3d`U~0vI4WQpt993 ziFq|~t}Q+iy{I`a&nivPeuBh;yxM!4XjQ|_fkdrE0jfPoPrhL)7A*bM{6{GTTliLu z$ue@AtL(ABmF@oZNuYNN(WW9MG-5|XI+CpvRg`2iGgW;d0ku$f)T@c#p39~6fmhPz zvK2=X==sp@WqK5{MA2p9wb+9*i*q_XX2Zc-w|QeUH=UAA9)!be8X0d#*hXX9kVM2g zHZV%JB=$|x#IMD zVszJU)3vntyRfxO7Usv*v`==#-gZ7f{?0&{g=f$mi6>Sm?A=@noPYBza^!l2u$@a>(HE4%%Y!NG0zE!Dd)s%x{O z_u!jfe3_zh&19i51btY*Pk_9U0oHwHdK{X9uak3YsQ?T z8d>L%P1Qso^Y;Wf2_4aaOOS9nS03*y4Ykha*+y`%5i9pN;F-FWcYGPmW-Efdwde&z z8A|T#w!sC1Tq1*_R3Cnwat^!(wNTlNut-Bt- z9(Zk#fPYmO7SSL~Ja-r>f*u2%^iU_oP%A#&RFa>T5hrgp4IPD+*xKUd)x5B6X#32h ze_H^aGIZkSvAr(JM3x@A`X^&7X|;_a9qF`q^>a*6ewAi+k0XQ;ZFm@R z@P|(QIFbl(ISmyAPVWHqyd(aPlNwv9?y%ar6_56Yms-6A`_Iih$BjEKW=y--Sm#YA zD?ltq?rX=5+((2aVVcXxQ{;JtceS8KiZ*G3WsWk2MhMzus9j}UC_fWf2ze9U>)koD z4^bVhIKrJjEGp+Uz$mraXX=xBQaBSk`mk?P`E=bk*!8v(fUVT_RzyW@Py704==_7* zWRx)Ji{{4U_k1CaPxp9H;H2#=j80rF9@S(B-7@nPaGR~5dU!v}f-lPF>{`Q>uN3nE zj$7-@ZWFq>WN-5EZ1G>lVW%n99lxVCOaI-DQYH%X6p^s&iu#o;zs{E)_wZ9Y$&9Bg znQD_%LzgHfgb8n?5;Y-4gIIk0Tk)- z5BGyCtqaX^cD|yrkZie%#gcWhktB*K<{W6}>Pgp?*zv#Q_2Lq3?Y)%?z4Z_$+tTyI z7*WU268G}`;kdYG)+&F1yVPm}2wM?DMPNk>7jXynKx5$*-}Rdw+@M zx!xY0!!o8>qyvr8BI(twCNE~{cR7u2+0!d+ovrngPVKsg>7)DFPGjuZk;ZpUf7UcRDkkyjoK~;!G%Lh^iArn|U$M=b*2mjh`^c(u92PjtBd6MzG7x0G? zv1C@LOpeEHbsGm}Wzlro#wRt*R%4^I5`Ehe+alnNf7O84!WV@O6JJ6}a16a^MFIbo zb@@E^q)VMzSDe+LVSOPoe$+QI^QY?#qdWnQ8=5tN;px~>Q}_Xmu!@?aXjeSgq= z)e;^y?>M@;iCUmdl%yC**CMe``IzFJ;0yWSqE8ukEaBYU)4boeu70+(1RIfP-di?Z z@SG1E`~|tI^Q9;jak&HNUqN-zw@5iM&PLp7_edz|yq;9D{~mrF2Wa^Yd-mXQmwW!J&1%avy_?#iCuuRf@l ztKZGM11`b?X1*6#^{k+3)gpPKo+lcifJ+Hp*o|C6}?r^)gDYK8Efd zZO#~sDMtUK$y_b4L!BZ|zq13$g-kz{U&kR6)AA=VgFl0~cQSr9rEj`WZxA6tG+i3> zJk+tnTjAkuT6;Z)Z(RV}5Z|qO5eUDPSWSaQ)z9I39MF;IcpMnRYz}kM8!&Fny!I@`P}`Z-&EV(E_p_OfP*dI-CNB-MD7Tj z{~=C4x<>#hic{lUXlV`HfbgZQ=SpV!z7=Oyi*n^e_lt#3;V+j^w&a zP;Sy6rA~i_JpWCk?x`CSfFm*=@cmf!$*;P+VW#223Iti|T`yL5QojwDc7z(+`ip=S zViFx9?q$#jRMbE6()J>~2#l1=H4t&tTy_^Zt!j@xUeUbUn8llMsg$TgFp^&%4KMrl z26zsnZ7qC{UD|73qJVd~T;QQiLzo#1W%wU+H||$P+wV5}cdkoqOy3UP-%1L4@8~*( zEnU`+wqLWV3mDx2kjH&*3o2)I4M$_Aq30j--i6d^%k?dr$dno}_?O>di7U5%=oTC^ zmJaeYBqDRFP~-mze*aVQ@MHIl_uYrcitP;#pm6C-SEc=~e%{T6`l>2<_WM&s2j6-d z=*LwfFuO89Wb#hHDCj$-to0x?Qx>IVE_XcXiZ}%!|(_4A=DHkkry7sGp zWL=4`dvLJzF|T)yZ?xU<(eRxTIrmD-CD3|reziAqm+-{#r0FNnTf+RwKh1N+T6C7K zA-;VRsO$a-LZE{Bk<~>GjJaIMT^cGWzl|PVh9~A^T?vm_x%cPSEd=3Idu4t2;vK?P z)jH?gfKYG0Ut_CUI4RC_S_yc}KMJ6F=$`dF#$);o05b$icUO{k@UuD3ay2Kwm*{&p zF(rIsff`PYMvp5z2F5TAyii*?JgC2_T*hOx36uG+m0N(lr(n_{$awRjBy9aUaWtFO zq-LqxfyDau#m@AfO)bqYkV%yzUvyh3?nP zN>{A+M91driP0gJm`g?ZgFj+Rwt3_{i?#QVJ-iDzY+PA24FsIAwq}5W#H>q>U&n^T zVQ)_0$?aqPd}yHAmQv5+v3mRCAG+Av`*n2*wuI}To~Uq1v!<8_`W19w9bfO&uvP5U zBZ`||D0)`4@5Id9J_zw+uSsS&A8mB|gnl1z69kVE#i?O`@3u*tbUf*E!%kL6(A#=_31#zf1YA~wkUl$#Km{r5$Gnr*qhMT@8yM~p zFs_zP;-k%lqm$ltgkX>#O@m~h=<{Gr82YH>tyOtxX*Ib^tEe;kBVd}lk`1`@ITmG$ z-(3R5{3fg~2Amcg-{?{NH&0n6zc4Zr`$4Y91Z32g$GpMDZ97lqkMll_FV(Qj34 z4>P-adli7VhO_b1*XUh;_gy34>Hiv(kW3@25Za2EX`ZPt(%<9T+BXd)sNen*5`gb> zLr|ROOBRZU8EIrb5>Va3>TTWaqo(UD{bg z!$m`znx3AgYIZ*IItn`0x;@Ubbg2<>l)%)lc<`ca{i9H2yLX_8w`L=+q1uvD`{L4Y(k$K?ZpWxfWRlRk?mEu&O*@SEt7I{R@2|zx@&cuosQ}#x; zTttSU2wX$ck+Gw>PcS&Sb6OudHOVhe*FDcyQLp`Tytmbjf?8|$jkXT_jy}fT^8g=W$f@T_sI@-KC-p8o=4LfwX(A7VUG)0b_ zZ7gMB%=&^09$_q=n|FWA+u`DHvy;De8)cobL5d70U^?8^}|pMX?Jvk1>RZ>%>!Yld%6tr?b$Dql8x z?l?v^m!4s58K+Vtl6b7NxNV(nsxBMTQ&U1{E@UBRMpTT$pG;O_9&+f!jv=R zYoM^!BgGLI?oHPFhzv!8HwVLAotq+DQR2l*aI#E!Fjo{TpW zoaLB7$e^cw6z=}Z5%7b8$@RYeNf?QY`C3qaFPe2?djv~Z)ANAt~5LuLi7~U4FM45 z$vI%|nCAki1w0}LIXBu1KbMMg>Zr%B3;PP9(~LDjn3|s`5J2;h%kl)&=c#%(I?P4b znUOJfKm7C?La1BS$D6Od2HxXTTvqvP9|2FjI9w`!-@G*yBb9sj{v$TH(5os#NO?;CjctLTNo1QxnO6sQiAaz)V@T><%!Dx zfXUWpBa@?mqa~UV;_>rY6neBiqkiLZPH3p_-n0YJ(J>nQ&1mZ9ob1tIl~VYjBqDkG9hKJSUoBVDW$EICF1>wQ76eg#eMG)o3zv6iUG z0O)~nB8jy(yH)zo+^eq6WsvvwzqW$4_;r8#@4l1v^NO)l;w@SwE-&qEYl;eOt4TvF zc7HZ*_dRue4LI2ls*5vn+*A>2r5R%hBtL29GOJ3nsWWxf5|z2YFBxZId5)dhCag-p ze4ZtA(c-?d2)6c|TVra5U2xlV#OlzRv`A0|Ui$oh?LB!s)Lr+Pcr5iGMvzTHga zcj`gWmeo{k@@IEJ;#GUbj&>R98`zomxy34^ND*}Ta&k#tHSBI9_A=%`ys6AWkB|Rb zr*c}2weQgsQB7W>ueMy_KM||0ND< z3=x*qwpbka<>=lcUlh7+nwYA z+$qn5S3q#0&mY8_!0>_1A2qzIMk(#}` zcUrp8jVezmjkHjWJcw!fs0;APzX_aHnqqpQs7vetcGu*=;U>Y4O%lFe^FE?QW+BtL?? zQIiIHp$D4=);@6D&=HHf|LWL_k4YC48%TQ#w1*DXs) zZ@lqcSIJ7B_Foh&szbYznr>ZfSRGKeGTi7`%Sk5Aam@NIoE2*tcU$V~>!U`{?%M{B z$jRheiGORWYO2Txn7&`2G0oNQ+Q}~YSSnTh!~+|Yej8&76_SDp?oDhg$_{*EI>I!4 z;1S%*)Zi; zU{LT>YIA9d$lDW+1Iq>Kel$9Y>7FZu!hHV9Fr5W^Yztq85EIY41AM za*~M2{4pxBKBmhCFka6NHVplik5BoHpbn8|RxKY#*Oy(-mEaHBK+3Gvz7=zI*q!x! zBj(yfIe{Z)``KxIZLPL-+SwQg9ebW2zLmo{Iu$xD!G~1eq2^zo5ZeA+4*x>>K_KrW zDdN}H{Ji|Rso3d|;LSN9D}pjmc6*7!6bpjeSf`aK;&yBk=*y%kjxHk}N;stb$Y^;F z=Ato5lWL${@86eNg<8m@mra_ZXPVqw;zOof*=>Z}6j7MYF2`66435~&>(xQ)GHHzIN@$g07UTsAUBv^#}~mIyAZ zgQM!dy^iox)-{Ci*2xNVaHL3B_hhE;+A1{zHDJp0o=S4Ihrqrh#)sP0mQFG3 z3z_LteH<0ZZTI51gOz^V)JtH@W~J^HKteuCjYJ)BxRx!@Qn)Ez@J8*`%0HwEG55=rdvh30lPb<~VF}4njz#6k&9^%WKuz^LE zi(`T?oaF7TioPX=+R8%5+v8pLyr;S*kCoPk&<72R&vK|9$-NF&r(ZuXj(kFcFvtdXqG;MFiUFEc{mRsdb}X6y29= zNjDuF0%3{^F>CWzk;VfWiwJ}Q5rQ{Cg<%$&sqbo(`JK&QyJ3IgAhBfc?zAcnp`O88nS{N8#BNT7diNwY*NOEc?l2K4valB z(jG}p(2;DWO?kf*|KP(Ykr%C|sDSQrJ*iN`f8P`x=G5Js*vxgXRr5AJwms-h{lF=n zlCBv%gJxVV$o^iF%V|LRT%^Vo371DWsekwO^u*lWM_Fnt35!$Ty$*5LUj&y{M zItE8`zMn4TM(($RF!*`3D^JUUpC9j}Y%wN)Y|}N@AbiI6&mzL5G2JiXa4oYzNx0j# z5g=TbkKNis+6gv0huN2dK>Df8fo+qVli`GO!#6avoVN7_~KDM6^X&J573^1}3 zTciJP$iM!Au^*3uSyTg6X8vyW6Bv%+GUCxbZPu^{C;&=o6L>{B{{IAlmT*G=SxiKB zY7dZ`4dKLXc~{^+T|M|?ie){k$uRCu|rS60WLXydw~BFZv=MB)|OVJ`=c z`E)TX_EKZ0*EDvJF;)#Pt*trSFGzabziyBdJ5_%IQ(&2{akzctXt$h9z#q8 z6TnlLzo_4LzG##Zz=17kZUx2hGQCrM@hiMjAP>s5_Gvx*4&+0 z%*7bJoJhC=S87qz`HpeDXTqu07DU0o=6&UxvdWK1#if}s`(68dK6qARDAsnh_Op%# z?|__1HMgpXT>4K+6iyXvJX_pn2q~23?^Y%nLgd+vxjVR@Sl4s~OU~Bmm#Zn}zUnu~ zS*czfM>zSpz1+->;4o6r$3H)8ZTmI9YJB#%cw9za-rTS~@m#nKbiOa9wubMXwb6ms z2%gcmPD0&rae)4UtcZQE{v!faZezt|0*B7`$INv`MG+L`tJShvTPHfsvXiVu6VPt@ zdO-=wtIm3$a>tl)51bJf*=*DR1IHRB!Xh=La*(1RpD?NUAvNQ7O9E|b$E%h9fTMFt z^UhrKB$9%_=oWHnYn=zBJW22T3_#|(U7V<3;dv&NT4 zT8oC-JmK!#9XeWGHrCnYFX#OM706C9K3Ec8pd4H?!S$q4?LCr5N;Lj=dG>s{*8vSW zy1c|iQxu;k77j@hK9wt4i&us!mBKS*Au_x-&!0nX`!LJSh4aVwuV}cwDv9qLQUIKj zqo~C~n6})Lf+r`~Z=Z)UJe{^URo;KnJ-{sG+vYDk((%HzS!xF*y&KXq5qDi6WDx8R^f!U5P1^v7y&quj6z<^{&OJCA#7JtanLp zFP(V;HV;jFzQgsY>!w%pPR~U0^+PfAyGR`aF%Qahk&D|su^&&!LAGO^DAT*ng?E-88R^RR zV4KJ)O&8Lg3s4zp)MC|;)m{GaVJ*F!gT~_o5b(gp$eMjSiA)7+h5_ zr8_3ZJme(edq0lJSuOieTNyxamxgUkHD&D zp@V#YM%L{by1}BQ;m}L)D`}ni0<8LT6Hva(-5R6=tlHOw+lZ%f+(MGoXy^h)V_Vqp z!Fg7bqX6`B7;DVh_2=l;hv`e*nDIRn`GxIUU$hPNkN#sc0EWB)n$04{+Ip-shd7Q$ z;jl0F^fL`8^am;_0g57 z{g5E29uyc$vD2d8HgsIDCx9zejs_>mLoukiQLI?_5CQxx4y!hRoT2X-AG`DkCE5f| zkY1zAD%^J|VY&$AtL?cetYS+m4&&@MA&?0y#viJ56)?arj`C(ou*^iO3&(simPbb3 z%VQ4#2{uTM=3b3THmE)Oa}cufuUC??^T~mpry3HOlZ>$SbzHWU zpXgCweF1pM{P*(j3G~+N5x$5}TH|-ZN)e~$v?^|D^( zLxI`92E8qC&(x`55f^-bsF@zv814wrd-Q6jnBHcrGcXx<%ccYXv(nEgZd(QKm zUTf`Dd{mH=#>FPbMnXcum3b?vh=hb1goK2$gNcE7f)*9X zjfC`A%v?f3K}JFXpx|I@Vr~URLVEi#PVJGpQa^E;R&-?K7z*ZFtX3>4MU=N#nL#U0 zC23wGi+^OtSKj}b6<|q%GdHI46rBk`Ojub>f6=C{pfJ-DpyM8c(sanQ3Oj-cKHO~& z`HrLrUXD;8P08E!{LofL^%HvU|C(nmot=k2NNg7aEd#lr11Hhm9d4-VmNq*`1L3m;+qaMNk|1c!9v-Q30T}y*8rDizk;ZcrpWMbHZ~zY zBvLRcaciDRFi)E1J!Hhdd56zlL0EYmF`2fgfQ-mpUiPf63lB-*4>~6fxq%`j`ne`D z;)YPiVE5)YP6lvrA^zp33F>UXOu$uOB(Oe&G}l;0;u+yZ!7E@ot|NxiE0-URs9gY_ z4}5Q9pOcksOmcn@dlC8_TPz+@QBqeEn%{+4wVewhejOp7sW*Xmcrl^}Z zxCdZZMxWta&lHRAoj16Yo=F7D5c?}}P}kSDq0<1Dq0x^xN(*5O1BTL17T)GmR$Z|G z!ihoy?uf3{4T4|OtD5U2Cy4UtSvkf>5)^*D!KwNoK?v{Ebk}yjwPT%w`iI7`6;St4 zJ{RF5X#)Th*j-Ds0PjMTcD?XPu6h~2{UEfrshN1mOR#}4=*AhUbAq!TYxL_YN&|rC z+AX*NAfWq{PB(TK_lxS+Kp^UOKU@?f)VBtZM=>BC{JKk?vo66m^7v~gSbb3mAx6SmDeBy>}{}L0m@mQCUl7{>w z9y1Ljb%l4Nt?tgYqOA_Sdq|@+Zs%m~`@lrDlOY{^ok7DMNeX)W3gfA@J?he<%dYP4 z(|D?;DIYx_kE}Nfe`m-HJPx%>9g}Ggey`39XBfa7!#WR)ZG8K{PSQX$<hIEyubMH%#*(yv*o?3Q?_aBe#dQj=< z1g;ov{@MUhd>6gN717Y3Jx#Sp@knW-zs5#Wg07l%q`gj~eQIJt#HMa1jnBqMm9~x< zTpd%5gH(0*<`>+9fO?e|f4S~xsYMj&*ybfEDc?ydjx~mUx}et`p6|9*qTQYX`r48~ znzCZSn%#U5Qv0*rW60#AZyhh@I^cY$ybTd>e-J))7D(tV27&&WhFz*`2O%5k5IRl9 zV`kLiPLB#KD|Ermmlc#;e%WiU`A}H{2G;}{aMa{U+>oz31dqwY@SllG{0tQ_3{a=K z2<7aO^oj(%e(~{5bQITXf~T((jWIaz7$j5ydr>TJxvTK_!%`$is44oaH(pHywn&L& zlD>OW`<{9Vo8lwKdt&n7Z`tePU?&dE4Slu^o0myFwtZW znEg@M$I422X7s_1*K^DzgiO6f6`CbjBHP94bTgm5zkcMSFkO3MhaR$q#fO(3Hrhq9 zzV|EDO?c&#UJvCD?<-!EFZypQ=-i(1eW?5Z?jjV&%1o(9wF|W)Z-%A$IjacXzEte{nyu2`$6dWx=q zq%fhFQlUL(rC4mHVnW~2j@!gs+3dwkL*aP2%%8E%#v?mgx96)eK@i z%eEQSQYFoZ9n$5Lk-XENr#}~e=I`h%NLpK3hr86dBwf5ba5)g6V4)yMl}s%ZAQI?x z5^!eMVbTe=DLYhLzH8!j62;{t|3*$rT4$zyP{Gu_vWGi+I!W*|Zg+Y|XZ9v%bPR85 zbX>1&HN$rmiMN6?ls(a~VtlPe?8xrmyKc98w`|A}rB5$DcMWG4cZyBJbj5JRYTq3F z+*_-fk)N^e%PY$&)9veiF|MzF6Q*?{pd`rbXN)n4*?vrc@i}Txeb5YgmPDQ$ocIn> zpI8U;;i=}4WneAUO)TfIWk0HBs|>A3G%?QolLoeodXwg$%ih?K1A>twAAtB*S;orl1!g0fa(wbplvPQ3s`KZ+t?No=< zI{syfTy91uH zURr)_Q)?r9NPK917$e`P#v|*ozXLbo1-3?nc;XzN$*2Sp#^NdP{R3 za=ThBJkL2#hf?9U<~QMY0V?hI&~fgM7cdmS5oi%`9iS7K|0o^v)rSv3%y^Cc>_3kA zrc>G!F2|BGOAV$f8Y<2WBDxN`Xud<9nn{{{9SHS|ijT_b3#P~K`KU?eEV>}z;cym3 zY6x}$zZsgGdtb?EIQngTo%Y+oCr^?i%66`Mn*c}vS0>GSVRr6HfnVN=povd8BbC&> zBQHGJ=K>ONrv|WWe)j6QZnkOS|?ug=K{_g}mRiBGLu!Z_xs=8VSN7%ISTnZh$Y5 z@v(JG2ROW+w0aKYw{z6;E`QCnaJP_niQY5%M099Xh#xa|3mUzVa?Nwy8W>7rUM)E( z(S4=WpnJtA_}WwH;wGgag@PZoQKr$^ozdOgJ>-pM){FOhuh(Ui=$u0jdT4%(^rywB z$sfjikg40IhOeJK$Eo=q;RTzLy8e7-kSTBQ=6eXkN2Mp==@iD~1)gD>g)H;YPXV8N zVBzxH5ZfdJ0i(mP5Kaxw`XO?0<7u-4s+aE2G!^8} zQB~R0`ly9dFR~opaIkMXv|3dE+zPmO?;K(#y*)CQS~`6=J>C4+m8De7GKX8ZS;N<16BgaS6TTen&!qmvY zsQ3F=Hw#1;5)#h$a^8OG%&dn!)kro%DST8^WK4T%$yeMf>(Y3uzn6tT>oASnb63+6 zYu4FX8$U4ghFLCVuIl)TP94tZ`u5)`u0taR zArwXe;d;MX9ZoDdra5Q%W?6M3T2}0-zke%*74iz&{<3vm9cjJWmHVDL>bku|y~Na7 zZr^_E|2?os)as#N&uLHSf^E%UF}p$9mGbmuyIb_bhV1NZeog-7C^${URnV340Bg7L z)@$jsjN}JNx~J^@)NS=i?(krsFZ^zLhPSSKFK%PHW3R{dY<1sl@1!nQwCSOq2iSKbbVf4COyqN?Ih?7dZ4yg4q5GLTYld6oD|=YMjKv^gu#>?h1{`6fixD4 zoY8$s22J^KO9u@7F~lgnCTh?__Fi`hsUYa#h`sgrXp0ufv%YhkWJ*mQ9gvIxYIy{b zj(AxVXvz(5R8$Q;eo?`HVd_O}y!pp@i^gr|euQ&hf_^*}f|E%O^WB>Qcf4%wN zD^(n!4idK3h%KE&{yCYy7ytX^-wTC+zbXG0C;npd|2#$TSp-`M_}?=V!6sw<-id?+ zLXwdbQ+7k%Uq)|vuCmba{gQTeFPM;#&@9u8!KP<fJqNN_+qp`$rsGx7J zl|q#pgiUBM<*Czln&#vX<4GO!aY^Pxw0(t^O!yQ`Yr4X3IuZ-Mf@r@r5c9R(BMhxFfHe$*g^pKp&p{qqDdBFqGVG(X!F&l~>%0tuN(-vaw1 zHk|d}5Rg!M7(u7whRdf`y#EFJ8=O8G$`rwg@V{_CVDm}MFS+Z-@}(93A9Dd{L0(w@ zMiAs~FRuSK8J=+YH2+`^*zR;XBocqY%6 zAE^JMTUY0u@vSZLyxm(64<$KaYnGJwU#I2YMci<|DFxRzbTqIv{yJm+<)^hR&%$ZG zH}Be%a6oW98Q~f%P7F*u{XSzw`>W@VNfYbY_Os0b=6Hv)+P>8J(5oVM6tGvh9RvM4e?dQlA@5K zw6V8oeDj9Q`>{EwETE{svfFN*tG$k6dSQgrBz>NL3&wG2$DkgOJgz}W>hUgbPwQPJ zm^7XYIiTw=Fzqn?12_<7EaSapfoW9oZAH7RHWKJF{rYotOPTtfDe2!rV63OVkY38+ z`QBxep{ku|r}X=xUL#Uk8o;ra06-r`*L_@rzQPWXs+F$Ler+vxUCh8NlF}CeWo^-T z^cRRm;y%fAw8jy~yxIKv!AShRV5Cbz6NxyeroX(e3qeNhzz@;3sK!-cnp~CEoYm0o z+>)m9nmVq*mXGBFKg=m*-ju(p8uE~SCj+pT=lGKMc~X8zz%|2_wax!u`qF@qNhe6p zheGTj?Z{gT)$T0Ojmyijm?nNvnT#6oU6NZy)H*WiQ@U2#>UK8}Imu|GK2)9oOSO-K z`UxZvy_6*-F2h98u{x(r#e@~yKq{z6=~?MD`mE3r-`!QbU~uo##It!TGfC-(FkCnk2`uXS^`&fJR)TYi3LoZWB#Au5PPKcH)a?l1__ zF$0y&$Ykhu9Xxwh{qqu-V$68W;P#cqvgol_l?o!;c|V_r9~0IA-Tk<|u+XR-)AH#!-nVl?aQdr-1_y1=3_K znBCI7>Iw9`h&9ScI&Q&}sa7JTDOk0Tk!0S(jqL>?YZ-z2uu~tWy~&RS72K^lQsNrC z>bpLtUg7(C;^&x8v{(UqFjF1@vCNC1qEWkKlI$dzT8+z4F)@uywU3o%gt#{t7r1=| z(*Y-0jgOR32R6Z=7ORM70bRy=gx~&aPS61$hyn7xWV?-cbfm&N$nc`B7H-TrUYiWY zlNa>f*JtscK4DLSYo?rDRwr}umQsBt0mi4gth~73k-F;ec~Ct&v089`HHF+>4#mSdRL z=5f9_eW6*%UF$7p!3NRu<$=GeYe}Q+m?|r%C3cJ|JfCVYFU@O<=t~}MUNPeLeBWz5 z?dPhWuDY|_GetWxTl%c9%&hiwNQ+9*7R3@*^LdPIa*VfLtH|ZVp2Mny(Pqy2lLU(T zWe!GLrTjZuQAjfLp{PW?+~mwj7c?ld+U5>)*qVHF{@#5R7Um4_F3%0 zw=wTT95CB;oq3bM;F}m-Q!*cKgo|5K4g8qY`bq+${~hY1P`SyuG19cWwl*=FmQ5S@ z+WKf$cM9(&6zZ@bBR!z1Wo7ut`?6d9T{X>v*BAFZS!rDhhxwy zD(}04ONX7f*};Ng-e^aubo`guV!9GW^gwx$n<}B(E6(rsQMNX1_wO`Xa-_%;#K95S?6BLWfqGyQvt|PXUD*bN4inS^@-sfhVC~J`aLUepn zs>GS|vH!?30R28QoJzO+9y7hgy0Ao$jeavPc`rYmb|4T>get}-jsA3-h3&GFJ4y2^ z$Ig6q$YYA8q8A>0VjNbr1{`0NU+mY5eZ&I1(d8XxQ-WM)uatX!EHO>i5NYM&q30eX zH}~lPI^9fsc@U%{VWqMN)MMK+D8ZV zAr!aUOYR(prI*HJN=$EmJ1Y}Je0{OA9uHnOIh$o7TLW0wwt_|CXFqI8a*)6K^TLV; zXsw&26y)a1n7y7hR5pTHJ+eCMP$r-j#V?s|GFHzUF^|fBm?h@3%uugBBMV=E4}mAehM7qy z4jXh#S@Us{Q{C3N6XsR!x9@v5;0fRQkv)$Xn~$neDK0iRfv$Zcv4!pP1~BU?|Ho_) zDem*bX{EYl3r_dr%6w=V+-ErXF258mV7Iy~`M{;)eOG$&oi05D#as{XLUD1C|f0GzZ=HbnyBFET1F{^Js{! zWL5EKTQWV|jD*ngr2#0tuY+_(cjzdfr`Pa=)d7Sd0chDaek`fHR+wLMvk>^P=6zsU z^5Dczj=Af@$({)b#3(bf#5nJM`RK)Sa?*9*+H{U{wZhWk>Kkb~_%7^d!&Avf_J5B3 z>6m8o&uF2VnuizlHS2!4IPE{?F~-R|E_S942CY6*nO@mz#r0<`sFL032ewi^?4l07 z$>+Z@uy{m4t$W8ZR;k&&3a4>(XRRn|q_lxeOCTErHjWnAj0lnO*i~pd-=lN5FK{Js z+NPDN{9LImKI0vh4tY!pxbrxRZ4!mt$PnbJob9vT4G}fp@zBQ=``A_tGdRAMnDA%kms)w3a6v$YD2Z!xS=O$k=r_12BZ7w0IiEuJwr~Bkwy)9GR z==xUhmQ=tvw1i7PqcOc;e#MoLOT`G97hf@TYi_|#*LUu?Et_O+NW#n%mpO=G9J*ug zI6+xBOY9LhxlpIKT{lO0-_K?mB=lv^2S(>G+6>A2__@y| z4{NX~5XGU#XY(S8JpF!x>L~dJt2Rlt@w>JsNa5lIS?m!6vX@QCQrh&Z=|nC?{%8`W zkAeY7_qnfaC4pFGr{vUvuX&xOU-4kJ+|2B4_)DkNPz<;HTD`Q&m%4+P(s~}%1@1R4 zhL2c%S1To&)D(o&FWLLLxs~v0cHiCiK2&Gd@E5Q6Hq4M0J15r6Eb0AR`pnnM6*7e+ zJ!z`vMJ+HQGb(Cdf6B96e&l;5I&a(^HBoMBt0X~D!R@FixSfMLqa{6~Ze7q?uXwaK z>9-)`A-`tOoA#=>tSVaD84h=;a3RjU>EVx0H795lx#_a3%k^^^sqST69DHL`RvVM< zHk4VlC%4#F4Qyk*6vD^WCSVD%M>ymlD&&JVx0!eX@qvz10bOpVmc`WDmGYWT_JY=< z0t55tj))gMUG*lbWIQqHUPS^?(1PGq`PhJTVemG`H9Z>S%V%O)C5b?+<7c6Gz|}PqAFow z*TVB#17=+gtt|&@6hd3{%2&9adhgwsB-xgoK;YE}k93Z()O*mfmxqL-m@asp+K|iO zL^I@l+&*(>sZwnBvr3aH&9<4nrC~W4!DE?dSL@&!<{my9I%!Xuq0&ogU)`!(c=?9= zp*x=UQrJe5aWKh~i9mRg{R?DpzGMNcj4IKJr(k)L=Ifra-|DGlSAR3I*k8cH6Tgrw zFpeZ2<3hXcL{E_Pp6=&3`PVjYk9qxrEkVkPm=yQjN)F>=5PW<1A*w%*!KfsM+j9X; z1(m^?(Y+drs`k-vA3$Zh`Rc^-jU@&5vi)WEh025H&q`BC%T2D@^xh{!-+jy5e#uS9 znWXGL=0tWiR+yVuFud#!2>QJL`ty)|slPLD@=P#}Yb&c-QZRjd?dU$FcLBOzcUs2- z07Ln~pAlJ)*U!clrDr(qkZa@@I>ZLYBxM4{4@wth)Y`}B)%LY)ZcxVzK0_j}A`%t_ zgdFqMiICf|@d>Y;M+x=YRDUWx^Z1qy$1T-UrsgymjsINUEJw_&X(sm}kmEidtLmYw z8J1^A#Nm1`M0RsBSXcd7)iDd+Zrc{sT-K=i&Qjd^uD0+SJ^?s4+G5D|R8-HJ&|5h$ z#sX~0{NPc_UgU^>kg-`AF~r81G`XReKl^+l;<*a#V4~kURA%e6B;9wwiZJc^ElEn& z%+3tmB(Hm%Qz1!$C7#4l4_Mxo_qvKW_lIjf9F}8_`is7ljjh%Ts_VI!(Zz+F#fNiO z{_iz78!L~}E0|ngj$}q~ky==kjI^zNvIE33yIwbZJcr~nB-|aO^NcM)drP6P_ppWe zqT*u1k^5`d(ZGSLsB!PzLDlI--Gh+v%i`nI6rV#q$v{}2Q)r{>as3Xbct3^|NyMqcn%(@qB5y6^5ho){`!~M{kmmy&s3nOtCbB^&0PsWOHSmwL z4w3yxkXuJ}fhRU~7Gv={O^@@p=ZJGDZ;jC@-jTvn~62_>tu0SxK$s|(dKH(szb}H7M?f_3DImp#)eAb>s*yjrL^>R z*=|Z&FPKjHO>r^H8^80wU`ld)T^P9AsqR_Y-rc1DwJ0iY*wxGGT%%pyR;#Ko znfd6DWss#gEX94Gk~XyI+XdV8j;Y?8;kGvS*ns;3*Pk+5@0nUR!eM2f$d5ws7L1iG zFAp2GU%6if%3B|mB?DXY8Q;UnSb|J6+q(v_Bcy zeNk`90hXn8OF=}0>T8D)LoxdQH864V<9gOLMou6~B=@@={sLbdQ zqEs|Kdy>1wPJz5*5TJLUb8z%1cF}xFa{JV1qL&^J+({Xd|ogfT|FvRqYM|=9@&PNw10{4g2pGx6%7}qVG#^$w|OrK|H!__^%*hS_* zXl&cQzjI$dz%%Z(u8$2d6iQHlweFtcEau-FHFRpf{&lZo)-F_@zUr}!I!;^J#FC%t zmgD{SgU60=3ZBq)EN(}-*Uu-5Q!452=k!smAlGwP5Z|Fh2D)_nC~r#mYFt7ZQ$mWU zfJ3BrId{M>MPtxaAHir43`PFdy=uw%D4VAvB87IvfixUpmibVwe`2x_q~=^MUb3go zrM3k!fD>q2mnF3@Xm%y^2_{jbA6U5}(#CcMA@hYardM93J5^Gm`q;X@#DybUC!hTA z2~TMHKKi9Gj_}|GPAeN`HR?kfm3dSKYDsioUxs;Wn;@lY(@%SRB>w|PX=bv>P+0aaC^B(20RQgZn8Owrl!?f!5E3!jN}QKeqvHXRyxziYKzjp zUdPBj`sVRm%TFWjl-T|j{=uQI#TSO~^1W|P>aijg;tz(x(OKPJu`sL}HBR)|94=zQ zg_%#Xy~~F)xdGtV8r1k3ux&x*1TiAba1HJrdDl9`Ny%-FSMZr+Hqj)7`=av%2a?9E z0;A25n;gHO=;IS>NUd1*6?3dLkRX`Kk3NHc&=f34#n|zNd5mu7lBB$vOGnNJ01Rb z9C6-s=ArHuD^jg)``s+PMhTXCmrzUDV~QrAZiSbtz&HL12w+nrO`LFM9r zX1MlzOQdMUVaA?rj*(e7N*8*pkNV7FqCoB8!Twh+59yRW%~tuul4*`iAk39cQqsl6 z?Bt>58(1(7zITdS)#3CyTMauT*(A<1`B6{3{Ekp*XCvkNqvgrskjd@Z0n?aTg76E= z{##SrJ*sj)sWLGf*4ELAl?^7s7kj9OUoI!q$K1c9gj~Kt_MU5*(X~O})wi58P`uQC+LSJwJ0fGulvXMakt7>5r+Z-@Axq(Nr;;EUK5})lTf|6qx#g({ zwII0U5bk+dadbE_eI|Z8Y6+|+LAt*=45?F9f*nQwu9fhjge=cg<_5#y(U9y?AFhri z6E`h8GXBwZN&-SDkK+|R6dF;vrR1K<;f7#V->d!oDSV*6f?VziCh)PV!Y z@^IeGb#jtp&b-jRv}NfJ8r&zSc@p7egO_oBh^PRy3^=s@qKwC1$9OGoaF#XWh>v!P z4AQb`{)pXFbV(m(WpP}y^+~MJ>L^?+bELd;vL;tJa@X4x)dN;`o^U@isy)U?w@T7v z3o7Tcn2fp4Gq*@hl0K5rHlC^O!#9f&Xm;KbHDxM>5WDI&D?j1pPDtKLMmisP;2Fpl zg_+Ifu;v*herH0nf~1S!$XH&I52qfrf@4Mkd0FFXA7N~S*OPC`u4gP(1Sef&2@hDG zzHj#9dl=>sYb1WR&|H*91on}iYXYls`&aUmPrK2b?3$hY=@C{u*Qa1sCvR^F*?T#=7FP75#5_UKWB6`4g85r9X{5S1Hd0@DvD@~NtpY(USZPP8T( z6W>r~(?k0gEA3w~Qj3`hnxw}yOxjv3CZ+S?M#gF9<3t{K88K%!Wbk>iw0)JpIOVO$ z5!DlZXWq`l`%S9SG2h0-Vi`jG-N*gkdbR0M|IYma5T!ZNyfsK3dJT`2j1x2y_gfnW zo|34&MW9us2gpT7&@4G7S+nR9YaUO<=h9LK6d-O5mscUXz2TQanaPFD$_LBnMs^e+ z%$3uqw$YX?E(bXVLpEPD@^&D52H)aK%Ed{cjOA2~RJr%WE6w%1QMQREma2%-!t*5Z z2?r%2*S1Eo))_RfgP0K|1A(TGwJm+-=V_w(c^nRIHTGpVLkt=RsIK;P-H zA6E>7788DSWpb0B&IGQ=7S>mV0b~PT;wqoLI@z)hzDN^FrPY`KnJT2$X|@_q3a&o~ z>((%sRpr1nJB8LqW$wV`#&~J54TVLVrEMc`E1p;rd#HxpkW+6*c%|=mo@#a%BIgNM zI9M>%Vp%!A=@2TZmvrGkhS%_y(z;niF*s_5)z2^oA69Fxa4}8iHN5_B;n%;51W|{* z^Q!pg-yY>zEoR5bxzipR~*h71DX@JQE6n!0XwG{Fik}q53Y=f z1yMvB-r{r#ui1*(mpm8$18#F9Z77QQf%#O;ZOsvNy;NXV+Vr(LF7BCl#O#gmWT>o6Rg#!>REgo}|%g<*$-aq@}+Mr`E>9OIe?0 z>9W(f!E=?Q&jWbrU}?@qE?~T~yHG0&@yj|+3giQ!<5+81NJP>WncEICeSZsi4ldWQ z)VZ!`y?+=+)V13u<@*|V!K|MGuNZF1`Ofw77Wd57UKJOxNeEU>+R@~dD)peKk-*9r zw_~&!Vepsi7;EakO>^;!mkG(tOGkNzGLMfa1LLa1lM#EtQ#-<<#_Y9Osvt9q%EMadIaoS1E)6;Aw^(SAbA*Tj9t z<{m%d*z5SvgD>&=HgDql*VDNMc_))0wuzb2G?F4^R76RB3`8}-U_r%sw>ZCj5i0uS zp;qVrNDIA{e>V?Pj4i|$z5U+Y)`fomi*>!TRvB?D3)mMIQEz|MAsjTX08L^?KfABz z-?D!eV_H9Ov;}v&-fvM}jI)@o!|+4(NazDhHW#|&iSv=h!2T}366W|_baVmr~Lwp1GErXkojn6<3IYPL2zZJSnXbB^SQY99h8MYL%ZSvE5n=C%24x7 zsfnge6n}R{%__j zpkZP!GP{NRZg2Q+R{~)wl9<8xfddce-?RP_P%}j3+Nyeu;@?vN3Qh=g-_#Gz>;G55 zelN;^AiSF40M~y(MMNRvSonm*%dDn>|DcHg?azZKuk+xn{MCf;A1vO`=~L>q>vslZ zE!zDrL_nag7(ttxo9h3d{68bYOg~)g;-aEYc9Z{CqsJk`hTwld|AiD`C4$PQM_xP> ze^3da|Nj$zGwS~ZdqCd;yUg3=68e?$;Au{sT|tP7r*aanum92MJB&YN!U`+a#ISQa zO;qZe$X$!j=~r)uk32DTV0$n1_SXT;s(naR7YNTXK8zU zpa1^7H{GiaoPIBT<=Dcj7TySwDyx@k8GkJOhr*nQcQ`9tjWkmZh&+19LYHnAdwYI@ zv$-)j5<{2fp(}D@mcp!2B}oj_rGh|)Wq7Xc>U!MmT;!1(%A zIN;EYqHa*hqh2gdVmMXOlJn^YsRw2U-|^hJ-e_39)Y8(*&B=Lf;dO&I8s4f`gS8)u zTOZZtebcv1*=|7BxOw5Z0Zh=N?xpZ9(DoSTKQLYA{KFnZCZLoBc7d&QbaYZ%ZY}8h zCN{lK`nRikww}{zpN$CGFfCeFLx;=<1_zCvM7+2VkSNAwKS_%?p%*uy>W55u(~4%jT% zDy?5l;2ddG7lG>)e6u}lasM$zPCHP6p(6d#)1v_^PtG%?(bsljG=^Z9R+>^&6QiWX zW~e>nB?ZiGW%VKP74PcIOv~94&bPOx6Xc_PWan*?h^m-3o{$vJst2#2CM;55?|yNb zcfp{3**%?t=l+J0nxykT4Mcxc`T;<6#WIGeaKp1v8NoxBj8mSi;uX`Y&XDvz(FgC4 zmdpFzs*}jhlatekf!c?w`X%pG>Z(26kO3%3I(74YOY0fJZ|~-CS#_4yfX4k?5H`)? z4k_PiIXJ%FR9hXG-&%Q7`by}>80y9;u)S_?)%&P>L$O+fuJ*{xgitDW?1;m z!YCID&7XD^&Kl{U;5HQXXwX?LB8obkAEN64O?lz{we#fghH^eH>44qB(h}M|?DDL% zax#b8L0-fq;-FyjNKKdOGq~g8E8=e5G1W1CNORi|tvZ;|l4LQtv6k+S*Rp!XJp@-! zB^SI|^}0#5sz3E{;lMpEyI-U^=?&A!oB8!vs~dj%xx63yPVhprXt5?IuXLxNI!(Pi zKh-@mOk|UftadZ6Qi}8O9|pM($A9j<3buym=GScNqim0M-5X^U6`Gr)=4P+UJ2ZZ~ zhgRcliu$J%d4)Ax^!0Z)n*7^CF`H4nY0I1n4@ zaUUf+-LvWx9e8fHUk77sv;5Ai{Ud)MUF@6}gcgxbtAPy>rC)(p1ulM%s*`$n8(1EQ%3ulEAPFmE-7L#DJz{39FvZb$m%f z*U1R;$&YHh!N*G3d`4R(#}!Ia=|BRXR6gOwG2g6+nTJqK;_PGNn@Mu$;C-(wxA9{qaxr(9Sf&x&QP z$n$!gE1b&IYYFN1+-J3hG(j{`^C6thZOV#lav_|S=-M5?F=%)8H}`_5-|Src^Zt%qncdnr8|_G^1b*wxN=_iR7jNB!g7|Mqpn ziRt0?6R|S}Os-ZQJI>j)B;y#9OxtpTR@DBWjy*#Tf%J=K0?+}jB!L571|}x%h-~$h z87TqbOsO)fi+z3$%Zv1=K!KLoG$n3)+W$+ne`T<(iuH;9L4yJq<-TBmiPpZ3=nn=S zM`HfH+RjSFV0m_JbOgGxk@{?>L?^>rbCx#dA6pfJsr>v}=?U0+ zb@PBD3KzdN#Q}{-P(26gJP_bHisqI(%Z(6vkOxN*T`nRxdCQ#9`zcK_J~?I*Jf&@R zAQ{7dQII6RKcbFibv!d=1swQ^WkLH4sz*zxA;pfVa6#0qYx4Y#K2mNz!9m8{k{%QD z?n)RSFG7Tg?l5fr$RSBHTt2Cf7)9f0pK?-M;ifT^T7w=%gz&Gwt|CL3Uqx~w1EH$# z#0+F*nIJP&bvNpEuW-zmEQLXnG6JHdwUbYcR}6_NYKil1Pm<|xS_atlDsd1y-|+e! z9D)6n2isx;#C7-(T~#eubBx{*y$XX9CIu@qLx|?)NI7`iNJ}5J!aho@ch5bp{*9m# zAns()S)oAfT`hL{2PBjg^km@~RkzepPq`!l|E_0aC$fW;$^=loB13QlNE*2unm7v= z*z$XYNth2}gr?tQRK#g^{kRpVoK7Mf3*?-hR7_37;YeD-VJ=oj*A$91(%oWE)vJ5% z?}pg(moaHL=mLEy-l!~4T<%?U`=q)=6lRX*dfM*Uo31_+s>mY01c#wPp~9`tJ5TAc z5#&@U=L4}Nd7k-C{a(g^7F1{&!2g%D9)I>ra0CNSub`g&f4B4646@IPy~;t5N`?#^ zmgcNBi4XXny92b1I3DM4LCZHCr3ii0V#xbbm#`HOkra|EBMiZVf5~eD5u$OIsmJMG zj}QSCGNN!pye0>Y`BQ7^5$a)+oA~4p^`{3R!Y-7hLaS&0h6`9zMJReH;pCr6icXJ6 z@%RbGL4LQ(`~!Rmv0qc1p}@Z$A!0uygzDnhZhH5wnB{jQ3w&4n~v0h|7G`V5c@5^WB*@)sUL!9^aiE*|HSft zIcEQ#$$#_pJnFByvf+(s_Xldw&kR3!y#Bropj+b(jEeMyHBh2yXUHq#!tlJLc{5`Rj z`Pqq3Y!Le_(X->C%sh)XpdG!R0;{D3B2OVke> z_#mebpWpHf1ks|?-*6Q6SK-?MLG#-yj3i19E>Sp}LK-29V=&3=;@2%6WcwJi~y zRud(~uF*Q63uzKPDRMnDd2t6DBN$f<@Cd;jevnHe_6V!CI8nE;O<8=f1!MHA8DSvF zVklyZfq`gOo@_{qxk$2%b9|8B+|5p{m252i&9fc0C&)*LP`CQKmGYJG3MH3&MeD?6Vx$%-}ln1s?wT6Qb1HF9=j`tsai^2TP$5GI2 zjJ!iMwZAcXHV+Uo^OXe=Y;t1~#)1m;!+hJzU;)(`pgB@B2YSRYN?54|fj%Hy5;Q5g zb{hKq4T`n;Y0J|ww@ad3|KfFot&gPemu!8mD4R&(82`x+8{xzVgECGL#0iXwI1HzJ zm$o?8)zs7^Secz#z(!m;#$0mxLA#|vDj5bdvI$L#oSB)CF)~sb`t?{63Bh*{?dj?1UfkQ{Sz)FFd_biV+F&DyOws%65P;(P_`iROEYyWzyXX3o0q!e=Sy1KFP&F*l2;Ud9&iyt5cb3+{zk$!#cF=;Glk85ya zweyR-JjwOO93F;*Qi;IEu$hg}-wNSlLAB-(eNH^*PIa9DpBoi)JjvlE95#0$&K?}=sx1jCk6s_Jv_U&--mZ;jS>$JC zz)IZ4rPclX(sSqD$Bf_wcj%>6_g8*>W`vtKad+sU=UBzha1)KiF4B&m?(0g3{CooZ zh~4zWJkcVv!R$R`fzHL;_|;)aZm!tQM6Q6j{#=R_OJ=ph!Er#w*!UW^8p`$1kW(3t z2~#@xy8_BBeGzS3*r>T%Mk89+^2HtD}pRJg}3twSFq@7 z^?(nbbleb)k>@9BqH2w;wUu`Vjb4+>`@Z8O`U-dQ)GINrllpzQZSB~{AYv%wbiXjfICue_fO^vaI{*d9Z z65;l9mZjgimyYtH9p1Rw=e&($x9@Z>0(gY!MznTy&Y0jP643Qk1YI=V#1y^#^E@aW z+xW-a;8zZ>0f{>Nz9OVvIaPNJJ`{U&4*PwmA(=g=`d4a9?9Xo7mfM62ucVq}j`Ut5 z&dmbFA9URd0c21tj5%>}yXUdG{JtI@Fe>g+5wXr}()GvLVd0>U-dW#VT3p9Ot$~Z_ zq`}y&1^cd7`r_hP7^qtsrW8`ST%ZIoalj%9MTDp?n#4gwYox?UOB{5~@ZG+%si%C! zts%irxBd4QJFb3J<#XX5M&?(-d-YCEXh`_K=-j^^eGb)Qy$G*&MmU~Mlg~XZE%&mU zI%aXsu4m`1VY0Haxmj647P0|i2l0Y36(%QX`;|oRalZT#^Cb-EJhK!sWKI^t{D6Ko z_t{Iq^Jl}UG#w`*pZLBvd8@QV2rh5gp$#5i&o}a?T-ndDMapr;%dGC(^Bk__&jM*2!{9f+xAAmUy7)ir zy=739-`g-M2nYy*prUjrDc!vR5s(&?F6mafLj+X1n@x9j?G1volypmX!=~XZ{_(s& zoOwT-nRC89%)o5!x%ai|>RPQ1dL~BTX6L@VYQULn7;ozu?K~DgK_Q_XmF5juODn{Y2D=k?DYHk?9rHB87oz`*o}R-J16rCpCZ_;uV>BeS&fdt2T{J*om4<@ImUqre1SPpI((5rlcw{ z)lV|sqL<00x+|4g@QO(2POQ!oG$Z8{g%H6mc%X-@s%kU}=Fv&|X7_Ib>Yi2`u~=yc zEH4#?WhTKs!TQQT{wotfSY;=NJT`VIlp)nyLrraddXtkDOUv|V=8(gj{AJA_l*6&X z2h1F6jxR3+ErOW0EK6pjbXoM0oiRvfe;`N9!Mu4Y^v1P^S7-D5q z;PXHf_$-y>_dNIsTV*t|YOsT+h8Bs-p{S*0Qt@X|Y=tEJWyFw+=tQ}3HNq!dXyaQx z;$xIqny$>dz%>}=DwPU7{ox*SVKO{ldvwD{Xp2oiJFlpyf*@i(2*g4|sF+2p$^r!U zMmj&Dyag)FMvgcb^b5s}db6?m27G?5B!-SDDCvN(#n3n8)s_`&m<#LfNA8t=qkMPX z(D|1Sgbk^<(yTK&q4(rfdu+liCUbjOZ~BwxC^mF|md_KrFIMa3Nj&%bB$h+UnBV#w zdjR2de~Y9GzUd(i6Tds&gD>4z>ZOe#$GL_R851$CJlb-I{-_MH%JW9BMtX(%QWRk@ z3Cf(j%9tNBW{H#A0z`@{|Fswnbi&-Y?C#$_O4o0t_+X>?1-S+OrVnZDyu-tXJpF33 z)A}19Tj($WCTNrTix2lJ*j$3iOm_b)53b*FwT9Db_>z@DRZp^p9vN9Wmi(c_+qLn; zSg7;@?8Pud*zK)u~X!KaJ&^Pea{;{ zinPHVD^Z5ZfH}tDE;tV(x+f%6_}-g97cm@-$)v)S2OyGVRkqT6@paZ@$}X8I!C2T0wzioo6^FoR$5s+ot6>Ow88 ztioPMn^~~Lc6DkLh?^tj<52Z1e~Uv)s;sm}oXXb0>*`K$MuVdyxLX>Sl;nSb`01~^ zu?EBK|E{j@710qUMwjmW3>hx-Ii1e39P)V!hiQ>9 z_my0pyNH5r5C853@b10&NxfYzSEKN$(qw!d&Y-azVCd;D40R;%{R||)K}xkkwBGH1=`o$>o|W@9r|gR?`UtFGhwWJR3PAhiA)WE~0rS zf0^suV1h&ATZG|Ad4J67@t9gc8DK7ir?7mBB8_#SjO)zMQLwzqq%j%C#7c@#5}rBF zo-F1RK6@idp6r$UYIvB_;KDVny?i9YoKdnWoJ(oAi6wy%xnWt$)3Hp^XN^<%*NQwq z>0dhp;7`Jnc|5xFvT_xmi`3&iqGmNS>9Bx2t*!I(^D97;a1kZUtIXNeD)i;L+wtB~ zHiLENKm{V7a!C5w;(4}OWsFg*)j|4k@B4S}3@%AORG)rJ3{GJIL|zJr?n7>da9|m; zdyA+JvY`$F!D6WMLE}c!BS@%1h4!XU^)s36rDn}&QnLTLFHZqA#}r;ljK`=(r?8aD%e9%YSJm+e z^7hCTezkh#T&raMgQ>4m&hUjZMG9l=5viCZeN4}NcEYF8F)`zECi}>KGL)fr!A=m9 zmt&%Q0OF+;q8Exwak40lOHaJfa~UvxAFER3?Uu75e;NhQFC-!NB`n{jdFxdbQJMw8 z(0nHnZ(LrMfFD^tX%Hii0Uv6IdPD3VlAM?buVLgmG=;APTT*hf4kZ@;c913GO*}?_ zRPTjAFCc*!mbWSJr{oqD9U9)_XoX*oU-jYxmMh>o5_rduY!*oZ__)G$JM*6e%h^_0 z7}5=~=ME+Ytwb4i$1N>GA**vW6YQoA=9}f01-~yMXxdwuAmb{Vvv;Z**>8lh(yZ_X zHSJ*^{A<@YF5^L~gL3=wMj_qF;y$H-&wuVB^FI0LLfvB&3e~p3zTg3p z=Z&K5dL3Hd{5WNkVak2Oq5H;hW#4Q!u_u$mtATLw2CyzqQnuv&7)1dsr2@k=r%hK=!>ezE67!Od1u0Ob*mfo_)!Sj5V><8nL(Cco0`Qr%?UA(2*Z*qMQ)V8ri4 zMti|!S_AL4HU%Xs*a{sHU77J)(?G4O1ibTqeAS4+$1vip7YX?*4Wz71)`)+aJnjXBIOnC+SZ(iMru-=1ub zeq}rWu7wq(AT`{M&>J0w{6Lo##n-tcV!~JvN|)ZpK9t2dE}6P)vGn%cyH0nx@jFIw z&I~E-iKMO*VjlqEE{*8RLrp=^C&)hOg5PAHgaV5Qu4(2tQ-_Yp-zQYaY2MDx$vN(9 z;L9~Suzg}r!eJeun02R7*y61VSk&4nD>t$> zz>Dt*&uRtkTa9STOqblxem^dJCQ+BxZdbmOmg%+4CZwuTT$ar`>F;bCQ3+ArG( zcFU?Pn(7G$%@}d835&=s4XZxe3=9kcj=1UV2_p~IzZH@C--H?f>c>odrNixr1{+;v zz;9iP;+td)-Q)BpRT=moF9#dqT6O<&CIO%fp;Uat;#^`n7!nCgo-*rezWKfuScN_N zGK3r->`t7*VIP}`&^pvTEG%(V_Qb_zJu|CMnmjH{rW_Xq69Nh0wQSp(vJUH_{?sX_XrTKNi!~r4RCzK++Uh1@QH7p;xV>kJPSSDx3Q!qETKu+N=Pup?+0?uGDy$V zlx42&NY^1g&}bi?^M%3iIkNLh1#N9Jeuv)?3WaJR4R`SAiHR)O`@6dKGc?wSUBkL1 z`S9_{6*9mC#p@QvEp!08I{m#P+yuI9vs$>e3V%ciNt!cskBS}ZHimE@&Bu&l{@RHs`_Q>-1+=Z5|$+)GGx zhS%sYEkG!kGAW~-`LZj6s-vNm67Zy#uJK!k>30mFWXEro4sVVRRlD@ej8)Ij;?brWy!lnfDX5Q07rDTP|gZzhq<#WLS8FfsWU_&yj@ z+5@h54OI`vPM~(Avb}B~GE(@|2O@y9!t9NQpdoHOXC#U`P`z~eBN(Z3n z3FUto*~~L@;8DUl;uy&lNs2gJEK8+0M8~jf%ks^l#=gTT{v_=Tp8CT%S$&di^UDPY zAV{HB=x29iO-^(M&fw&<9HF@te(TTARmV^D%|Y{)`+a&ChVL@0oPFbPFaxKW>&(je zABRK6bxh0nx9ej?9)I`p$yf(5r#gF^XpD>dNlLdb!IU2bWYrOj;BK!FGOh)33nMu z^xD>31x1GU!UT!dE8-8oyt@W9TYt16_g~XgR{6zin_H%6fBY0IO|tVS1@V-#JvV|f zMEGBk`A|(jWwj5L$U_;yFczI>*0q+#yjR^syk<20S3i{!0?j^VdqW2c7?o`Y%*+|= z&fY4C&1H0)Ch0YR$Rj@zP0nC0u%0bhayb2#*#g{)TPk;l78FCIHR?+_LKnxBNbrEc zNf|;W*alb|FB`#soLEaM0+tWOJeC`CYzjGX!g4{yaq^e=Gtq+y#FVIeiMzgjIU~H#@H^KmBOX=ZF`_I)Hi^Ac;_rnfL9CXgG!@1-N8cX zdnz*>vRFu49nEW>INDZge1QAU68rTO##8S*$QY=HKb1oom6?lp4qj;TPyx4mDxhLf z($|zAE}D%6OjyEF>nBsC@txdiR8*xX6>aiR=PcM)v!K+$T=7lQN~O4deFi%h;P=d+ zNl}qWNZ8mc%|70H?cg=w(dkma#ksaOs+$l|Mb>8wA~XN;Vt=Q5*iivS$r8V;75FUb zxgC>H`@8q$p?pGq?Z6+V7>G);AgDCJ-uxp3>2wpz|Jf$y;T3)FwYCI2G@G&X!9_S;cOUkVVFe0m;M_^zppP`_W0K1yl6mFQr_Yh(2xG{{E;7sO6qM&R3ZN}+KIb+ zlh^PqDDKueyqj@BR5I|gnZgw}AQZR*;F(0@_mGvc==GJ$9cg^eS!W^JqiH~x^JLggSb(*B}n)Qb)pz-t`s3M`JxnNqH;!Ovy#jrYKR{DdGW#W?BMoU)|*T&n|Z zvGk6&7U_;aS@I~5GS0B`4!2~Wvys=^E>OFD_<#5TuFY=YvE4?tMLDk&7RQl- z+k~(SlCV>E959~UCOjJ&pmXz^kK6`v0zmXT)_=jeO&_%&WBXSUr}=FVZUDq;y_Tro zZ8V+&RI}V0&v_dJ9Dq2SW}*=L2Xz3F-Ui5RYupom3k1^aO?Hk|Oen=IU*UJxup@x2L_q2Hp%j+;dF|J~+)bHD%H=6|H7 zc>jNh&8eaUv{Ik$DkTZEwzB`H%cB~BWaUd~`?CV;I}DJNCRELPzAuQAP_N$U9srU6 z4G(wU20O=PmpmT-S8j~A8{S8a;7r^{c#oF{3A`H4RGYR2)+|Kx2Kf(e6cR<`7o@>2 zm=9hRM&bZ998dD-MB3gZ5oj4%UXwPz>=mBUeiAhOg~f`Cg!1aJN#@BQA0i{!vUR^B^4!$239CjHu_bnv(q1_z zV_FtT!9}gO_-*rY_|#ib<%(y4ho#zN`}Bjc?{rk!7&ij0z) z)73zjK1vx?%AO`m?C-e|3MxL~PkQ&Bppl0vL%JE6E5G!9raLFb(0(W>3lvyR=B(G` z5y-jG?sU-1^>3ziG}Uoax**a%i(0V`=Xfepe`=o#7Fkuta%vwZn+CF5D=qaK*Z`j0Gru(1d2Qrl3bT_$obpsBW%ZnAmD87UQ>kNQd z2YQ*(=l#&2mVZ52&!^%AtN=j-&&34(UacgEFR@?$E{Y3jml!9I_nQ+3`kcz44$>Vy zd2)P1=t@fexCIS9LT2n)2go;FeAR@O?1Cl(Ea*g_kS;|gL{Z@0M1op>+(Tib4BZ#> zeWu26|8|-t?yfHo5X=sD<8CWIe89I=VmqaFJC79v|38b~1pjaAYj(kafv(h)zrV$> zn+R^W?HIPfZS7~37_jEvPsW9}`8e|pA1@^W*G2sEIdD+{H^D-$`mM4KBpsj%o_*j3 zsSW>>94WQ{27h}}CFMWzsqY}efns&oYDJF!PrzOvVJ?H@(G`zgxErE%6vOuVsCu?j zW!5d`V|+*0peK~#+I__b^iD&p5iC}(d4BQliRIPMCOV$oT`{mG_1xzL9iXIn#$$9s zVyxS*aUJ8AmyMhkzZt*MkwRa5n*tix30)lqJjfr?FV3nOc>o&cMzyuI#d`AfTK--z z8`&%urmrZuQirO`HXWuS#TsjsudW9WuJm-&rzvKz^d~97oQgrHZ_{}&oGxNo^ zUG7!zPc2YY+2Q5oVJx;Jamy2{!W);{Tq35Jwg%Xz3I70gw z99*28mX0$t{97eK1sqN(7S%_~X}&9#j)LU;R*m*UY{$ZzD7n@I7t@X_jf>5V7g|*l zHte~11(7N`*TsiBjRgg;<=q_TcGzjKa{QioVQrnj?(SF){=!X1Jy|Yw9j0ftm7A55 za&NV?9&<92fm*euhSP(k&~&-z`@MpKW}GV53$yzZpb#Q2A1e$)`0{0Tvc2Ar(qw(l|~Z=$@3r#|_&pGaDMFu3lTP*l5Ky>ZS@9 zF%={l1Rr%MtEey&gw(!4OuDL^iXS92??^7%0E;pU^(v8H-s<8wNiksBA%W3gvCe#Q zUw2l}F-o^Y)2i;sO2a{1)D{Q~7{S5C@j6J@{19W` zlR$?~!=kEGFkAY_jd9Qr8c|!n?Jl`|!K=c=do9DinjRvYzG?f>spme@D5vk;dj-1Y zXrR<5L!~%*|1?IYyCgOLmF414ZsT{f_vVGA>LLtg!eObQ zT(0tT*tg*bah_I5Y7IMpU+gaY>?p8vx&{q#-iV7kJMl;BSdBjzWVz$5c^`|E144OS zXP5iHSg%qqzaxP;q|%dF;MA+(s(Aqc)BZ@u%zz`GZCx?qreoVssLwQ%=rXTZ)h1>> zNTp<2GDK=E=xP_k$UQrjc!IXcdh|mA+NEimHYK!GGfk^zT*$fEny?TeBvWU3Pu^#`$Ssf0n3;WkZ4l_V>))+C zp1D??VUg{u_%mgnZJB93D@05t3dXUNFQd&8m1$iPsk^2z>lTvqL|N|tk#_Qj`&x2GhZ$_27S$hEvdjnQN6FI7AP zY{l-Nj!b+YfL%_#CTHPO+5+u4F$Iw6FG~i_s5Vgm#)ny^X11qBbH?{JF23P4Tl1Bu zUNIl1J?CIq|1`P&NA5?MrFC0xpl=ZpnLK|=Py=@|pdayugkk1@D zMn719XXN>uo=c{2KFM+EF+cC!QTBVs`ufnQZ&}XqGweB1@@`ZSPm;~C$f&R3bJjLT zI?N9XdsZj2s}I?K7@ucU5`-`oZq-~0<8*9}dv+COy%$ZWH04_uT1fxgfH(J&JJWK9SyaqP@*e++;Qtk|?xosDmCNL__E7SjZf7{* z__HfB+nWgi^$>;?`2@}OH<9k8%1`}(A1_Y_yF2@H&bRio#IP@)%EQYuaMvU5S)vvhs1 z-8{h`gL$rk1C#bUEe6M0j-eixXYqG!V{@^;YAKje(PMDM#)YG{L0KLdgboO?$jt?T$^FXPKSO3~!Wc%PVQ@wc%)BY$cfn=Oo zFQ|FbNA3^;^?yE=2i5!g!8B#P4Y>{Q-J!c_vg?u{5CYlJnRfCy`nmRUSW(wibFgLu(m(jwL&Lm{^vMw{-f%+wg7#;%N~Fr=ROi zX*tX(oxuH2ds-#~97LQdQ#XV>%qyC^7`CfA^gQ4RWAIr)6`$8{*O8+d zV)#UV&f4K!L!EngXypAO5c63%&J~aNs%b+{SI-NK>|};?dEVX!MDQ~f4JlpWpQpu_ zr|Mi?@VW_?(*)j~ArBUgAlE$%4Y8B zzP+Fk6c^XAtjWPM+2h!AWU4{pL0;dH_d~;@al!Pa{E>^|&o3BeB5@-CDyl-|Rtd(1Dm!WZ??YzJN$5DowKH z!FRh_;#RDT+;QLiRx4qX^(&EclB-z5u;b6i2oz(|!ptFtW|t^c{;C14t$4dh&K;1T zLeW1xmB8I^*JQW;EVX$+ZKaZX>Vx?>l=~QG9m6!n9TDm|>rl5LDgeRYiTb-L@asDGrF|i8`p1iE(#nEUl{JJ-=YB0uAxTJ+cmddhGl1?j#y9 zW$}G0>kIocTnx&{L}3#0jeq2dQ+m-XE9P9%RLnWnF8wBg&uj;k3!5uWw};F9u~>hM za4$4EQt#~MCA9^*ulwetD8yuQZ}3a`{J@vvS3$5;hWnsBD4}Vd;Gdh5c9pivveh>4 z5%l*bw*QVzo}}l(!Ux+o$8Y!+;la8!n7{RH|2xBB3>}V#axg%2j>{>3nNW2G7IN z)HK>y$Eh{g5sgW`VNCO4ywzh<&ulCyi^Jum`5@s|(x+#G6HQXu9ukSp&f?^Q$m-=R zW(Ts1+Jj0CwY9Y4(~-U|B5xZvcX|iI}%`~WzNLqT7tVLrQP+~PL>MrTTtJD2{JiFSAM=Bvq3BgO)uz)rDSblxYQdW&LL?uzW|^X*{40{itST4ab88M9$9iizX&F7P6EuABrp(PNni#*5 zxcg@0&qup^L)0@7RrMD(-Cz7oWnG{%f-TS^*@CR(F#J{2a0vO(vxo;fGq8M)SmP32 zDJW}Rk0_3iE?F)Y3~8ftTe=voSL7vEoixld$Xl$wA-o)Jn;5cxqSV)&CY~zCTQPnF znwMdR*v`D-YCSmPpMM#kg2G0Za$G!n(bwpxYOv^tIE~RRKc3{n2O_u-+c8||&05;Q zYksnp;z)Nr%o*}fg+DY(a^lg3<^@7S(V%mRK6~+sd89i==QFi0$aJ6tZ6{^qV(sx@ z$0J&djw2PFC)-QxHi__2_24WX9JkRd6Q6rHt0gi?JAC+KrV2Soi4KXMT4WtT(=E@j z^V15hy+rm8j+&{*6f@_#hnHj%0j7&M-h%+I8=1c$rgTCK^!WQ?<)2Ih}6YMk#DlWM+y8NMTM%R?>=7lLt zN`qQi%X^@nISgN(zi%YiL^fI5?%ObH&1a|FK4Z&=OoN;KC>?tGeiQix zzDM$JK9024g<~RP9=C1USd@94Xl82Ezp5^2-vTR|a(d5#>z2Ko0?cKQ!1+&G{{MDi z2zc?{-!Gykd$h&rpB;YpD2h`FnW*EVV+gvA42YkY$hp^54NTp=o*qU-oT+|KdH;<2 zwSI1HE_)vhu?1NOtHH@@gqm4rvecLmncM58V&tCX0j48t>`x)(2JO0a3kxLaQ1`t` z(0+Yzf8E@=bI0>n=sOjX4+l>Bs|QQ_jatk!#I~_IQk?`KSNZS+Bi2~qr>otYvIT~j zy#<4&Zl^AACDG^y0!h1zimIwNTJG*sWrG_|g3DyC^J>ofz)BA&hDY7hRi}5u&-FfA z2$-o1Nbq2D_bET82*p9B8-4^o{y|f=Hc}serqKsGF>^XU{POX-MJ|+cgy;p41w7(n zp>6UN4hxN-*@IY1$8ntz;@YUqvg6eK=I(_=MFeNkp5xS|SK_Db7iAv@KHM~%NVHi- zWraFFtrQg^4>d-<|I3!|h}Zi@00{OX#&*z8^_qX~zJJb-Hb??peL8GNrW<@+48M}2 zr|()~R?((O@2mZ}T-Yig7WM@KzrX6});^6>)}Bo2lMQt*b^eH$-!*!{562@Bt_!tm zQ$q7|ylaiA3hAQ@;n}uxy~_ODA}H)V%1Yv1t)9D;6TenYSt9*r0vVfPhwy zmF<9C2?GlHYxuKkcOKWUmF79`29c)hn|kEZW%`b=_K;|x=a0*Ng0HGGd<4#hu9d9* zDgA1ats0G;2KjCH&cpMotz)6cfOgFn5!o^kmxvizk3^PEv`;#2r?Rixt}nVD)h7Zg z3nUiuDHH7t{)BF^T-{^|U)i*Bg1+dETdY|)U8L8b$bNoou%~5F!=gtsO`m0)HQvIl zOy8+%NQd!2tYf;cM*~ZtP?zn@z(C=- z*cQuom%*;Y7UmQ&8V=8R&vtz_%T95;Me+KPx6bn0I>yuGBQ2|EL~pzS9tl_e|HhBa zr!#u>ie;UzHzorFH7u&LVQ*YIQH`JA2~NKKi5w8~GAy8%h|zJzEh*8aS75bgOKZ>%+KB# zv$}ssFZr!DM${aMYVfC2<5-A!QE9w8$?o-L5~>$*Yn5N0nE(Vm92Xs2L-gmP_dU%i zrtNKqPmYcl+uK$I7~2niB>j0nf$?PadHwl%v6Q?KO}e09IXl1352Lzz(CxO7Ps_cR zZq38}GS=*f*38Y3<)>wscPZ=DP+sHXvf>WAKHVx~4h^>~V`alI zn+AV#G6Uk^r>wt?KG{Y_tt2r8-|>D!({J3%Ya!2#Ctl_O2=Ro}b$ZZ<=(>GYouV&< zt>e(mFkppbHQ&pVkHN$V?(6i% zNXp4X5E}!BcFU`Jhpi7T!ucdQj^<_@TwG%>RJ5(TU)IJpl7eZ6qc2)K>LQnU>~U)U zMOZ+-v37poJ|jybunB3nY!*!#`vWMKV`0@HJ1c>&eaSq}T3t;K^Kq%KK#z&TgBUlo z!K;Div!`c$mOcc}Vx3|w(e2QYZ7Mb^uOGr4uP(~v5n>4HPoswSdvW7#4(zB4--9O!t2t!GWu_Rxaafw|4!^kT9W1Kb{N-EK3f%uRmHys# zy}u>A^XzH_tkd?FP{Lz8=+-mskKU(K>^wt$u!|Zp?IL8sz5b*sxU0A4`4)}`XH{@B z^gPE3`94n0PsPFj(D3d^IJUy_PYd7}D50RYaBEf5I*=I5Ok3$Le}MOmo?hbTq0p zXa$>N+Za!;*AeK_`RYloAcBI)g*i->f-7@pBn^Mxt(W~+bEMXmM&qY!(>o{IvHGjy zBktL~#=8XSP1jHGW;1P#%`I|{#auprgPA>l@<~kjNWu#uL6PEIuP(C;P`zBsVQk_7 zuWs>4p`k0<{h+?Xz>(o$=as%|QjaOW+A>s;mX0H=E=4gf$P4_Z2!yM{RHyNzEi-(b zIM{Zgji_K_g|qXN_bj9ltSV~l^kIzXyz{;HWd@1}3lwVk`U-p~4XgM3<-#O24l|5$~mz%U+s~^R&fd(lYH@>%2 z8Z+t+y0lK+JHu*yp`vNM&Wo|^L|idTDrAi)A^Vp-J{UQ7w<7psFFffC=`HnFWCocgsJbciq$obSxg8AM}mUTVLG) zMA(deXmei!bkGsIlDFL$zRQ%UoUVBo+=*~AboIatS|L%@Ll*yJOWpq`@rs6wOk<3W zM+zDfTE3Sfc6{t#CMc|qviDiKs4B@pxCsqMeTCTbwFK`$=ohejx&l0{ReG z`7$cCk7o{%V~`7D40eglc&~Gnvd^61XMPk&$WgB$`6Lf)Y=?x;PS{=dmPWVE$vn%V zR5W{;>i@_zI*F(D$yco~Xb9{yy@{ahN?`Dwm{8ZS+52I6W!1QWwDCJLK+8qMVz1Jo zuboYrajub$Z!_umBF%*1Wpzc8<47lbRA-5nLmQeAx}87pDgEk%>S}vXlnXP7kO-DO zw6lwY(v=A5A((ZWt?R!Sq?vp2R=dY}eZH=j^9%dCe%u&Pt8E(FoBqEu^_{PiMr%)rY_kHEc~Iy-doAkpVi&T- z(i^zKe+vqWXzKywM>{+zbU=CFq?HZQysRf{;q zYX9fue}6C1>&|OE402nHe?#~mU`ucAq?c%#``L)x9)lJMDXk4jCT#Z5r1RV2S=5pXX|b zV&-A`0+mEiF#m@`f%V$Ra-*K%_iu!HsAbK{B%p3HGakoc8=T!TTuObULP3Gu;2xO) zbq$TezQpprkEHj&u{`w_opGP_xK77*pI1BIK8IS&T-j>4yTdrStH<)K8Th{JN`$(5GI{T+C35ehuzi=tBTnZ?-Q&|bli@DWD|Khdxefn>bJA%H(@wJRga@JCj5l13bY)4 znDQ8f$ClqmdPuuCoqa$flW0=E)v-MV9K;L06 zVI~bEB_3mOSTGyheLRPSB`P8_CHI9-1*+DRtV%ZW$W72KB;A=i6 zrr#2{Jew${dQA;&6G9@a+ce_<)6^RfHMo-yJ_J9M&l()wZFiSf##E%x?JkFM}6wjJo$MEZYZC0;*L}nv1K?MO_!+t`P@Pbq_v_fT7-Qd z#CjD~S$)w#`FoA=}fJ9|>F6)HX*d1GvCsAehL$@bh4P z8&Cc}jrC)wG1}%ye4J+tGG=D`jSKDaCCP)!r&%=|{^Sb7H^fCPANN6w3EoyUwkSM< zLI0KT#bCJv4iUG9TVie&=h{;wWZaHH+M$+QURgG*yDyY+4RP0F=YP{>ek&nx5PV#W z<2uUhwf8&Un$M>Mgvma?jqmt+!!OYNtZ0N>-{5c3^m5Ax950RfjSq8AS%Hfj+}u** zeF+G4``{;eAeNqZKFlr!NaQU(`uX-?x#OJSXf0~8QPm3qGK06uGA0&rDEsOr)HRmRyw$f@R6C^vzl>vv7JAhj^`4L4b=1_y#y+|d&#m=M zntC<65F)@rqt8|&)QFp7gv^G_sm$@Q|2gwjTiK7x+@s{1P+`G1}mHmUc#yXoW z8#H5$(b~A4dr?sy-f?7JVM@^aQX`)F)cSi3#^*$#F2VbyR%N(Q?eNf=u$ z;tm4>uqGsFsr<}@twfoj>_v8G1v7Il)+=N{R%G6PmSTIze?{lJFmcR=f>#&i$Y&j) zk-yv8{GMS6CpS*TMc^S*;tto#=ZDr6vz~G?lHW%{|B3#{;1Tk}+Y-oD^K$L!`PtfqaEgC~*?xeHCp`ZUHN%Ot}N&5I5S2gBs z$w(dtp0hnfQ2bZg{~Ma}Lm)`$^DL|$-<~O`!wqaUpxgvR^UnctD1khFr#wDI|9{km z8$jL$;Cbh(G5_0hR1imD!OYJot9|#^qB_Czh;Jo0x96Dh9bNa)dqqRr{C|#l!|pM3 zA5r7$0oM3W%>?rJVH0gZTG#UXzZUfzzlm0cx*6ciKNsswPYIM5@u;3cz@PsKNRnD% zaw6XC>)$(%oAU(u@X>o|SzG8oU%#O(TrdEVuh?IY^L)V`R}OI;W87XBIV#x9M+!VB zw;!jd-z@ik!T;Yj=TQ&s#W|D}u^`_#HdeZ@{~^~Fety;7&?_Z#0V2rbjvAjm<=Mxe^#+j4l~5 z*at7U&jkPd{`B~Iyold&BZSQJx0=Jb*72mEqo(oXW=TvC5%trEBcxx_IUcFe&=o`&5ZjT0Tlx&$~JmF}| zg^|gf%JyWZHY?cPKG$o#yaQ@bueU=b5$E#ov2xo?IbwhEM=9KWxnkTH+C#QL_7}|! zi;_nw)=bbdjAs%gFFi|g7(wN7IV7uE+2)^^4|q@pRKH9E$DO+&W8bn9^&_Zd_xHG` zU1G4^FHAMegWeUu;Y>@saSuGM#Vo$&x-gde+K;IB96IjKwNGw2&RC1}@^w~?n<;_n zOLw%h*-;&rUoMBM$&3v1e^I9$E%I8su~ALW4eP;L)mRbPJc zvC6Co8Ca`;91%zki@MyKByhMKCOBQ#C@lAzZM@84n9S%lH10r+X^)t8y>3BtbCYU5nvDzl6>&q$e#l zv=(4N7@cpe^89x}e4v53r{QaI^ zK*5^aX{>Ku_-*;JZ1?k88qb5jc##+$y5XZ_!9_g&>oirI+3k7@<9j3})rAdbehwfR zZxVDX)sq*piRqazKNDs9wm9Rm;@+6Am!bZ{ZtVp@`LWOm4^7L*;>!osG|6tg&|==8 z1dEE~gpe^^(Crqkqov%U7SR$RFKj(pYqNwWM0Az8W8bj8e_$geNBGwnJ(dS&bTX>r zc}}DvKdtCbrmIzFS4sf&=QOc3Fbj@2u{E045~>wft*#Q8yUmH2=we5^lv~R9&RCHM!$a z!Fweyqx|1q0L!sG%L&De(;s_UxeU98B4-KQMj6r5Q`0cd0)OTjCt9z!PA)Y1tA<#W z?qHmCU|o0MHtbDEyL}(k_Uztv|D$J(1?GZ&{SD(;I`H^;gYbFXjFYnH5w+DOLiobu zj9B7XmIRq+9b^5kaEI+UnzrJxVx8HOZ2I|ovpZhsV5`JH3BLmk-7^#8mYj(DzEC9gJaaRR@F~V?zrhn*M&^4 z;N$rhKhQKmx=v~iOTXH^-)X`cCku5OA<7X+j-ZjR;vAi%91FVc;*k;X_z|jP34(_= zmd0O5mW~gQY#G_GI;ood5_Rr(KyMk56?{;Rf6c^G5@uHnJIT2`UD3I63T2us7GnN% zWM6$^a6IeoQwU%0+EY5DI5T{&+TCX^uu-w#j$T-s94Es?^$J?{zXRuwiz~%Aa&v-W3EVXQ7?OFWQK8C$jFBGebK*yzrsqT>Q z95G2&U=8K9JS6j+2w-kpF8}QTV$^Sq@>?y#TVgp3<>lJ{RxN^GljEiD2I=j@UcE)d zrifCErNdHpN+~QKF&km%`JUOilI+<_=P;kUaxx>>!zhEr_S8SoKD^UO=5a9ZT%fW) zFWO&QMUOFrb$xa|0`3^{uXA>P|KZ{U<5{2O=8#GGF9D@Cj&ETg2_#K6iEnsB$GY%m z3tjav|H(#i<2ZWtyeSYK2w1TCA+@SA2TyKg<*+9{>zMrU=+*)r{IT?z?Z`7RLKW;ur2f2p_-LZAtnHhp}0OU3enZ~~R7 zz)yXd^e<_UK>@U0G%WwW9{(@+8{PH)_svm&E<3HZfUa;Op!*6a8%RC)13J0k=M)x} z07IqK;1tHpINMW<4csokfc(Wd&Ow?sZ!AKcQ-G&C(J)b>&SSAtliH zuBEZL#FM3>jAOW6F^2NFO4UW2PBcX+g(&8;!;vPH*)$JZxexR?O@) zFO;Je>oANHKQ}Ym#jdZ1!5|C%Q7Gjo*?2p8hpxG0)LShA)1B&MoK993j_~)G$ZS{| znacdU!DRA?9Db5^tTcD=Q~WVP?6UGG zi=Lun1WJDTN-61$unD9lL6zI@2=j{JU-_e;Pb#h;q@?BX(2zhptRo#0-KjR9|Dm^t zDypcGUp1}Zdl!f@(lif!_+kWz!P+l;4iweW)QUktuej%(v&cMB{+YO1g2YC4C3M$M zQ*VC-HqAtaj56T^vB)u=+h6gY;Dvp@6U>7bfIzxzF z-~FO)W|Xw&xbI0@sumQZlN!j$k@f7SN>)TjkXy-dvt+RiANd`b5G-VM;sa~DP0E{? ziXZs0Ev$iuw`*;NPP&}}H%kk9(8H1V!;};+9y(RKUN2p{YqkuDKLl=R&XXPr90OFW zB#UzUkKLvnVr}`*nXJ-fFcujiPP3Q?C$m&ZzCxbHVcE*v6KyMur0{0xtzub;oGVny zc<_pRwu&=SF?L6s4_C)3QwHNtHtpc|RMi_cT85i)*^B&jH5?y3eZ`MAdy%^hHUIm~ zkhJL~d0%bH|KhcLEP!)9(5#&zL?KsDL)q7YGt3@FiTnKiuUV=<4_Ig>Wsm(W^A!m_ zk^+2@t>Dr3zwJn6U`Jw2;>qqxQjHq7p-g@d?*N z1-YlE2Q-$CFU8{ItdtAhQ#1VX%Ag)Eme1a7WFw#PeS!?&40sCs1qdFEoMMT0zuLZ@ zAgH{oh)G1o4pBf;l$7j6{Ny(s+vzH}_QP^H&h^ifWJp-- z|HIx}zg5+Jd&4(d5Trr6k?xL7hjg`Q&>v!MTwW_AXLAkb5oI_@fz;yi}o}yhd3ju z0#>|W$LRWqV0`T_1Aln)Uhwl<0a*Ia*%@9qC;wY@_7{Nd&`=CUXw2sVvIfOqGc2KcwE)8hA2W8a(#w%}5PO;HSCkM``$sFv`TJ}=f5fMScDjtN-$%cwHA-hN2 zIyesPFTVY4+gq{~6G%J<|B)BGI!bBsob~=;EIPkjI;wNq;4^)(W7n=`iHbIsae)*l ztz~kKf*Qp%eUcUzFE~AFB-(Mn^K}RfIU2$1+&aPUdOUFv*pvKWRzxwGnmr~>r4P5VNTFiTup98eko)@FB|LbU6!{|iO)5&H79 zP{l1jjtSXZ17!NHoy`6yF;*gv)9Cbnn%wwb^PuOi8cZ0UW7X>*<#Q7f#w61Ps}4Nx zN*<{0VTQ1R(yRnbM6+0_W2AG%UlbUrGA2&uiw_Rg(#AzdH3_^Fo0e1XiDFfxX_!DeL~6># z4)7$Fa2ibu&<>n%N%$(_Cm=Z2ohwjfxYm{-sRY`|zLu`RjqA)*j^QJXd{aYD24Y~M z@ll&T{PHQOg|*==5@1QWW*dv~exQ_rDNeaqN@%2tj2r!IU6-iT$nYJzyn{ozfKc(j zsXQzSG-HRzfPwIE_&#P{_Y1G`NII!pd|=Kn4`U}@0O*#YNub!4(W_ zu9@aLP*;&2Ao86~;r%RC;CDm98H@Z3))c6;nw-c5?6H)hBLaW;M0g0U0O}DB=3rqB zvx4E%mw6d$B@l8_EL=NXx;F7n5gB zH6>uB@R1qs@_%?SdqunA05qDOWZ=UnCI;(iSd_(6QfAAwJGonOHa)oJTP#8K~0U?onU=4%n5r^p*B^&GG!OrTZD zC<%X=q4|0q*Swel&Gtc8LY#>#FeP%$1p7*!v@Gm>CJaI1o5(nBWFS7F1@?+?rf@Pb zCy*cfZrivq(VXCY;toT`pZtautc^b=R__0SV8=h{$p4g)1Gy95)_$N0)d-psdrDbn zoQWFjkJh*IS))(?@T@=M2QHe*KTE>wjZ<6G#S+G?3JZH1Sv!`?!b+MI)wz$Q47D}`lx z8FNF7=VkH6h4>kIOWP!w*UTw6c~DxaE%iyfQWB)N#0p3BkmS zZwW&4^blLQo4%+dAxZ_EEysy9XtjGHUK63;BHW6^CQYOMjbIuJ6lYHx4}l!> ziIJpnDL96_wB-Vi%s9V`)Cg&9U1lpC=&YW=2ma0TF!F~G8H}VjTAe(YqF8Qnm2STL zkgv9WyJtL-5{8~{L*^5+BQ_In_Ae%_rVdDe7K#H?|98+89k_P{m(fZ!8w%(y1-lR| z3EvEKGe>3H!NH+fkzdR;kGt*$TclZN@ese4af|jtLAaf5 z#~;tm5Nb*5WPpU%>Q{&sGp`!&XmMr%M-Yh2G*g&DQT>yvY|L4+zBpGnv}o_0Zz%mb zLOoVZ$V{v~A)yH$t%L*HJv`M>$#eo|BWgFBzAGG>@mr9|j4tYcp?KPQV@M6~gr>b@o;CqLyPu#uwC03rI^icEjGr*!jW#bEX>M82nRMuen7xY}Wg zSiyH_@JS-JE#s^SX%^eaXZUwSiBfIQDBz=Xdi$S`vRu<^_mh^vj{%x>O=SEq!HsmJ z2*t_*MSWHf0=qSFF)aRGdkJT@R2_t(!Qg(a}$a8I>k~U~^jHK`V)t z6*?sGNINpoxmZwE-WuY&Iv;wtUO)1mBTNchY#=3W7`M;+K7`Mv0o_DkF7?%miX#m7 z^@)%;ICCW{h>GN}l}US|NJYCgc6WD|Iw_ZIge#v#M@Nq^XQuLUBHqf%nw-*JigE`7 zaL7&b>7N$ck#a+txN znMXe}Ub3LW8$P0|r7g`w@qPsrrHmUdSZsW7W=BtZ21DmNW6AjKALVf_=AnD`SjO$+@*!_ zKq$C<*8jE<<@d{7G3SzGq6dFKgTKnz?rEg$VIGQxyeSyyCQleWZmDTtLD%v?hPoNr zN|S*A_LWqn`1>Ed8-^c~RG!8kvPospp&g@oIx_Q3FEEB}H#j&HIJsoXtotE(pS3f} zi-o5V;l2E&f(?}f(VLr_zqVWIEwADOwVf?OPydnkpbkgWm>7Z*XgPwj_gJCQI}r@M z2_34?%*Y|7w3&p%Mr61!vGPWa{AsylzeXkPu4xo}6wNAO9qtth7eSCtRU5-eNJnaW z1|_qsq>kJ#@NE)ueu;+HaOkylFxAlqvC0++3cYboyvq9gXT$I)%@GMaB3}Ysdj?i_ z-r`-7PJ*)g$O?_TZWeYE=xTpx^Z4`r!DmBajw8TqM;avQyolT$6?7UYw$NHSzCTl; z(i19ZL=}Ew7}#2B2VKicaNI*WTzr$mx2=<~M|k$iLp^?I+K)OZpRTW(Y?#NgXX~p! z@>QkT$wVF1n{Lw8%!>6-Icj;<>PP}G|#}WKRxN3Y_ zNkUp)^}E9$t9TT(#=)^sMG zptAOF&-0)uYcz6V$E-H(7MlbKtLjgp^Bms8i>z_(qXNe(IscOvebqd6+K}y=$wn=3*v9eRd@XD_W7OM7@g$zDw*tF8x()>LT66Zlm^5OFY+kd4mf?-sZ0qQ##rS%oB`Zj^ zLL0F)l)b#Pe-*|lSd-XuzP%L|hLbA9OishV)cUQ2_GA6I5j8fi#kZj|$s*elR&adQ z*!SnbG9SBzUS?7Qsil|+ewkKriD5o>guMQj$*Czg z*@bMx)w;?cb3Z-pWUWwh0R2N3 zb!ZC5eo;`2pVuj+#ejFAIa_a{J^I8IRA@-rh^Eo7hxPXt(+IPGYc6z99=K7G=bc9O zGDnrDe^^z~@-DR|DZ_J#T~)zbrO7~N;I>vi?@F1s4Acu*EB=j#8y8=SN1>($dDW+e z!8?t}KDs2Cr|!p!QYr6DJqw>kI_@kt|(?kOuL9Z0bHq(wrz`Sw~{XIUJ} zY=T=1gsiM2)s@1J$rWKv4|V-9d-qkFcinJ9LFz31i{bGr!5{4^%|i%I$(p2+BxHVl z!7>zE3kTxY^-y0HuxrHt!+U3Aut%7d!KbE)V}^@{*LYKd6Sd_@c%fW!9f@L4I$X@I zNPE=)zv0n=181datrv=sIL|gs~Nhq%Ok-AX6rrzGDyY zm22f7qf&b>Rf^WvfoEi1f4m|7G4CD<#RbTcz{rIKSu3?qDPpphy}+7QfTYSzm|ka> zN|u*^t4uJmMOO+VVXDf$I}2TcWy@6jANoWw;93}CZyWTjlT-HgtmK~rB2^mTU3P!* zWQ_`y{q8BYpmIR;w`9YK&@5KeY40z!?pB;Q1iWFPfw*yIUNle{M zceR5g%ZIV5A<4*JDB1|fJMwToov~IZo7)#>VEeWKAMEBNTXijl$mH3Q`o)`y6geTz z_Vg_^y)Pm!TKu#EO2BmyBy5SFOKuv5_(8#5T&!HRp`6vOsB60Rpk0nAd*ojCu5Xo7 z^&J;w|5;m;T)6|0@14%cgF2-y)JqLhzxd3mBw+m2S}#+DtNXDY9XSl}V(cp|rmhqM zDRZP8<$A*d)sqRbD~Ew`-QK5{d|EV!Yo@L`tv$!c$F3_IBfI zA_X!2hwjw4bs1);vjMQk=KXShrryz<^H3dKXKkAEe+bHC$Gr8Ee^!bwW~tzf95!+rU;+L5LJ9$o|*a{dojI>>shDI2|3Zo-!z*<2Q&OF+7?8;skP5 zfW>~GM)QtDeZcPkwDZco%g8W&;g+aD0(lXAe7om>Z3{#a}zI39L0@nrVxO`MkkP z1Sr-&ENoB9@;bO%9NG4jW4;%%ba1$avohrh8aTO`m@IUgTfwc3-ZRb+)i+!=6b`UJ zZx7U@%9k1U2v`$0Q3VC8sphF2A~Rr~%Jo;R(EAu5`EBsu{T%X6S%=uZ<)aId5?(l| zcQp>RN@JW2{iN5z2cAp_FD9gE*pNuy2b<;{+-)@UkcPbBk_Dj=0L7ZF zCbT9uEv>C2ggX{jF`S+i1xfAZa7qc?D>{cd*MV23lmOl+?+Mx^9pdPNadc_5a_;VI zPQGk(qtiWkVYT~0wWZ0|n7>R`zJMqxUUknHgv=WL-b#O<-q)JnOD|tAZe6)ddVm#} ze|O5qsr8nKprx{AnX&ROp$1q#7`;%XvE09m>l?9Ix+YLR}-b8=x~`Sk+6dG;>46gUv3D`EUV|7vHHv!zuBSWQ9y+nH>IyBr=jJN+kAoC2>YU| z{4}O&%8e9zw{O=L0j@G3u2NLl(d?>}Z_CT;;98?)cx^YGn*S*&H=*IR9_W-8^|Yir zo_=!vXukHletKb2iI66>mR_c>KK%kfzV&)<)r$6lM$-z^vBt}bHr=DFS6hL2Bh3{N zF;-zj%(VhEeF&Vk=@&r)ZAeMgkn~mSVNZYI714uCZpW%r5`I7!l6@}rCJpU#15eRd z<093z-aw>;fP?Rz8knmlihb%!StGhCfd|bW{PhP)T1|C!FJb27ph5;*_D=+T1%cD$ z6}e9RjkncAvu72!+hfwcL2*GeVW~zfC&d+4J^7 zN!e$`Ef-RfwB56zrElxPP=d-rdiuNHj~G%S+FiwZloh(b@LZfZ97n~1Vgc8d3q(dW zKSpCC@0k28cT004p2BNyrdDk{J<+#q;dRZkV9!^%KDr%a&2J@CG?P-HOP94ILm5~T z$G}=J(%eg7&?v=BU)pcOEEJbx3wxPWt$umlzLXMjeiTvUL=p#Rr4iq_VomFCUZJMw zu2T-7qQwBq2&JLvmFIpGF!GuDea2DmnDnm;4k*1U>!52{x{=?E&22U9k8nG#tqW-4 zB|h=jL7i;lg#%R|TmVabO7PWw9N*11y~Y@gr2z7H3m$+jwgMsXzAD1eh^VkE)kuBLN-AyxpBD4O}GwaBtz%r>+)p=J$XO3b?(0i(^*_dF#L@?LII?bL16^tFBV7=4lvGX zDTXrWFXR#agm}heV*C$e`X8PzGc_>I281{X`LBiOf1y*MWdMOdXRQ4?=I6@@Kh{(v z8l&rd#I5hpF&dOzdaf9hUUiV6N!CG_&bT!On|ZJyjb>bd%e3TlC)U zZqclNvWv&gMCrf_oy~*U*;)N}9g#Y_Km$tx7MmIl#$Zkp5n{gEh{5LS_^qZj)?va1 z2-9-DbnEnNz8MNT>jCkSw{Ns=zO!+yym`H|3D&BRgKbGYz$M?&Kr$kfl@ezc_jTv< zB^t6a(8<@YviKw*D?R<(oFqLc#_tmDGeW~^P04^#lNan&x~%e_BuZG%Wx5Q=BUH4r z*<0T;siiwUF**PON1BE!QsE57SJ+k$2>NFV_}o6W*^C~}Oc5lmUvg@cR#oM3o{p6x zG3jsySDJ`s0Oh{KVjXKE_AvRak*v)88vFYn$!sl?%A8xqs>QZ7rI3tr?U)VQ6t}4S z8fZ7^l0g>3bUC?xEn^{ZbrK$MAf*9(f*apZbv-Dhw&xig5lQWPdL0oY(knnx$qR(A za%F4hK#WlhcVH&gU+?q_fF|p?Uub#%6=We#=yMdc&EHgXTi{(2ngkF~{q?TRf!M%U z@16TA_E^(_*pt(z4*83Rt4RXHSm(8y;9uWD1VG0(7@t;H{VOI37Y&DF5V6qEZDHWnFQy#ag3DLsW0J$~-JdO?RL zDeiyMMlhX|U%6X>eCjGlLMY#mlx;6}^7ojJl)frhv5CDq1DI>7w3u=v}+ud+KAq5t~Poswp!GDDopI_09x@3RkQ zfVM9Qx${T4`AB%p5F7;%ZkSu~4uSh;t*Jp;_`qYjNJDA`LSNxq*T(D9BHL$)g}wmT zIY4XrU@1Y6`3BFv&)k5l7;@)-Xgd&j;0KJL374+E{1IuO;P$ye8y}6K%N)aiSQ`(= zPkiK~lnBV9HqW2D?W7XR$GNG-l>%h`#2aGk6~U3C$MhHpPk%o@`K^XT?;*bp_4K0@ z?Tr)dmJAgzAGFD$(8(f`(&_84YMJ~N^V1JfCMMntug@*Ey6`{;DpF7bMdtH6nabft zTwJ7KR+iV;t(FBpx8A3}m&!vfm?c_cmlxvv@f<+aK|D)>k6P|1cCRixJn~vUXf5*l z0NAv^vbh*-_|$pd6d24XmD`F|ax&tz7zBOe5lD;f0}b4lr7;89E1c;|&zs5}fJZj# zRDZKkB7qr!!O6y=F&O#~A-K%1g*f||b@K2YWXfV-UHEZAoDn@nvnetrW@gusH2bZt zrWg2ewE88Mbh*X;+?dbE?mj2HpC6T>B$xJ?t|Xp-yo7ggA)nIXCQFkTzg!Zg>2P6r zK~P3c>_}kWr})v2_I2U!Bz&sbGF6ba{~jIHJNgiLC`GabB+ZJ&qZG{>r2y@qXx^M< zdm!hZV2hW`dd;Pml&A{T4zYL7K=wix53x0KuZ6I;PmNeXTH8GrT7-HbS}E2rmGasj zKVBzuAf$f2)O==Sv~D%j|E79sNlMEljj;@7&Ib?m9+@Ck^ zhq6I4F$5>z(mw}NAqA1(DM&<9%QDBXdW?}#CdHPPRDul9UpRq_0~4akMAqbnO(>l( z_FrT?K6DQS)6z;9Ycpig63hE5VKE1e$%<}(#o{$gn|g&436Djjwzhh;ARJu)Y7Dxj zJjM^+CxV??oTHLZfGu>T^TUA(2y6 zqKUJ#5@w*n*82yEt9g>&2i^c;je1o?|K2$h9|LvplT-%`eGo3e3`imWx2y;W?Gw#= zEfNq}@n4sqZD!yg5>-}%Qvc6p@Sp!61Ki3mk)k1g4dYG#9B7nCSAVg%X^?{zqdQYf1G)kM)6b}G@0-Sy{d&B18`VS-#1tRb?>?>k^{^t< zGz)!WSR$ZA{uLW=-fwgH5SH`niqFaapb+Adh-iJ-T(|_h9eQI+O+F6+tZIQk_Q}xfNPyg6t!&YB_?@dIfk&hU`Y;_vd9EF6~8=r0UV&`?rn@b1+e1rk_WSTI-nO;2q%-FokoM9~Bb{>8la8bA3# zA-Uwk6wJx}l)w8d3^opd+O3=g^zbEzHw+=~@+lO@wBELb?E~y|yO)jK@5tv5yu{yT zINeca*c=9$`gqTZQ%I)<)GgPYVH?eP2rZeT9yEttq`_in1|E0w8Xq=AozAxVu#P7Btf{ms9oDFb$2S>;AUe85Om{-ND(`i!wlQl)pnGRjR zQgnUyRc-Y{lf%tfo7cd3`{y?ky(WI^2Xz}ood=J^5=<@qLus%6HQtO45N*_EILz{R`NE7Xx|V%~+Nz@I zaF$j8AH|@DH-Iuk@)i)Cd0w^R%uDzkOfW9ddo8VNfEP@>p55wgsPW2NdCh8*0^x11 z!YR=(+_R7wJJdodTaAdu0ng7OP**kBozhnz2+6of~r9FSP zH5<)xn%sFbc^z$TT-1pk)w8Hex9`qpIJJ7rd_!zz_4dyVEaS!B1wKxa1}z-axMc8V z2h6(x{kQ+PCzLzpU(Ckz?ob{__yq#y$)pR;hL!(>mim8#=2`abC zaEjP%7NqIRd-45Lh$CRBPzT=16gQ0nL@o1x?JVEI@;!^=x49U>+D0%{6_!UJh40Vh zx?9eLS}@g*X04r`susZ^Kn?UoaMpXfE#m+%UOgE#%q1Uu10ljm$Q zYSl`YT_e8w@;>=GJd$$kH4TtD9*8+>D3S z&Eug<`(&q;CL#+CE-hI#y;e)LdKc&sWH+sz3*&$k&b)d5NA&3FEp=d&Uv{CRB98{~ zREB$@pE;(XRo->$xw{XZ2zIc~?Wj|D5MW3ey|UQ(jQHCYRr}~8R_mjlpYOJKpwR%- zQr1!|OAsC`vH6S7DWgJ=2aJ6Q-nPBn-E&zeD6J~Lf{LA~iUZ-H@7iNoq10pQx6Y9` z5l?|F?&?A=Y5oOrh*MXXVz@YC96)Gf-dGq=18BE?o1IbH5SXr7@k6dx!*cdXXH}@h zVs9$EVu)lmUTSjnuBq>sxMWS=uRsSm1-jG%ZkJ*i<*wfcc*Z{VhtpKK)IgyhA;<+k z2Yl-Pyhk{y%nAxIv2bT)LMkD}@vIP+kSh=G}e1RsD2?4XJw~e$iRi;=&hovKIW45euLXgm6;h=*VVFHR?5y>f=S{L zyZf;*CVxCD;lR@!SEGX!HeVC@*4Z5(3Y9qz{Mtsnn@(ND#DaG!7sXCVTKc5+RzLZd zG7!V4YFGT}sJyW%J)>7OBp-KSMpmmRuwA7@CM&&JNPU-J#_gHsyffQMM$Pc&j9)4O zgF}1>sw6uZEgR(LI-*yK3M z=6Lr2ToH0B!pCGAqaLGJs-+58vAQYZvyI{Ef=kdhm&~h{*&n7y*GhJRzE|0`YHud! z*IiNY4Xplr5PanC&A_bF$-Da6s;VACLr?D8aUzr@>msxzmH1Kyu$OmR!i=d;emFAo zoIVt4riwFM;e6O%ekR(WMLsH?pbgLeQV4A&B z=Jbg#5<`1ZM`kS4cEc_XEbo_&{HXoml=xLGH${8Vfpb04x(w#Lrd$8WC1s$ z6P_m*8B^5X{tHVs4RcS`e=AeZ))ksbGBufR9*iS? zQ$QJTjZ`<1UY>sb8H1}?a9K7f)pVh8n*}-qCmVx68FX9R6IOvv!SnM}OUy%V1zV;iu%YZ16cuvEZMot%t*gt)S8bgk>0IKutwMXN_k+!shxO1$F31 z+=)z?$F&2I)$3G3t)7zEVW}ap7sgxaXCix$?Y-;sh>zIaBgNt$4nX|&x#b@^TF(|g zfXsRXH0;e#b3e8OD)!=q{h)lF;9p^UDUjk;>mgJh8JaosZrh%7E1@XhMPEttIH}d% z*IL7Y4~l_8b8nX#KFWq${b;?pF>)5}jt%@bj39;Zq1Js-SV!YZKxpw@hI2zD`H0wb zwij>16_x04TzjaQ8Eg*Mh2ZdEMfRX8R`Lu=LE;zAR5A;gy*^xyeuBS=z9_KkI<8yv zmzA92Tv+ViIcGkc;R7Tyk zm27t$?L#P5F}jMVO^%gLSMi1zB<_q}Yb5X{$A`ZGvkO1f>s;_7{W z9%T!jt^+%-hwRbgaXy!z=V(f2$L-Mu;nk6eizh8DqE%bbG;`qr8I&a>D|s>UC~gjv z#&!}GxTD!`+BZ^ajhx$iW7#LT$CH;dAK)~oeQ$;K5j7a2QPJnZtC&JV?l>94;4%8* z(#|Gwr#+nVS=W_T&x-{p{b9YAqftzg&&}{g>{Uj2RcRRg)4rwTe>ky`xFhVV%qTM6 zgVngL%%zb~3a8mhkw;U5LUPkhs=jx6IZw@Bzj)}CT$!6S(!CCg0g>RTqm<8HaZ zR{R4lETLSWt1uiZJO`_%T-&olo-Df=J!<0s^t$egY%o+HbU zhG<(&(;T)w;uTfeUc5zyVG1ysooVofeAkd%)_Y@z@W%IHKWx}Rmt=f+E)@2bQs^9F zx&_ZY^k}`FzWvg37Xi3>MMQ*hGN2CIjFSZ2vzo#vr^m_{vzG3XnLlifE&APhj4TlE zHHN>^IAz8{>d(Y%di(pAtZdG?sVSD4o+g+4$MV@#GxeZ66-K6}yop_g!$aR3fhmjX zj>uopGSS_V58EFP{Dsfljv?35l*JSsEWHw`Td@t`7 z3+1f9uaqUW66yk882ck?FTXi_EaXJNT|;Z8C04SlX|izk0E1(4Wy+}Ay_=)~T{Oxu0QK6I*E{GC#M_4WI;*$yY! zQeO94kV06j;ti@e!wW@}qflP-QSme6Vv@%{(G?xel_t4Bx9+H4zm5wtGzw9rsO$w| zPQ}>z^0UOmG%!4EsXlLZ*``9uj$LdNCH6MGTK7YfY^$GfxN|3-wJ7#&l&WAVm!I69 z{<5PDp|LG&F}uu0zBjqYrl$oPBivAy{XASXs{ ze$W@+0FqQC7Fp@eXIV_XXKI43tubATt|Qa_Ty>kw&fmKkoru!3d`U~0vI4WQpt993 ziFq|~t}Q+iy{I`a&nivPeuBh;yxM!4XjQ|_fkdrE0jfPoPrhL)7A*bM{6{GTTliLu z$ue@AtL(ABmF@oZNuYNN(WW9MG-5|XI+CpvRg`2iGgW;d0ku$f)T@c#p39~6fmhPz zvK2=X==sp@WqK5{MA2p9wb+9*i*q_XX2Zc-w|QeUH=UAA9)!be8X0d#*hXX9kVM2g zHZV%JB=$|x#IMD zVszJU)3vntyRfxO7Usv*v`==#-gZ7f{?0&{g=f$mi6>Sm?A=@noPYBza^!l2u$@a>(HE4%%Y!NG0zE!Dd)s%x{O z_u!jfe3_zh&19i51btY*Pk_9U0oHwHdK{X9uak3YsQ?T z8d>L%P1Qso^Y;Wf2_4aaOOS9nS03*y4Ykha*+y`%5i9pN;F-FWcYGPmW-Efdwde&z z8A|T#w!sC1Tq1*_R3Cnwat^!(wNTlNut-Bt- z9(Zk#fPYmO7SSL~Ja-r>f*u2%^iU_oP%A#&RFa>T5hrgp4IPD+*xKUd)x5B6X#32h ze_H^aGIZkSvAr(JM3x@A`X^&7X|;_a9qF`q^>a*6ewAi+k0XQ;ZFm@R z@P|(QIFbl(ISmyAPVWHqyd(aPlNwv9?y%ar6_56Yms-6A`_Iih$BjEKW=y--Sm#YA zD?ltq?rX=5+((2aVVcXxQ{;JtceS8KiZ*G3WsWk2MhMzus9j}UC_fWf2ze9U>)koD z4^bVhIKrJjEGp+Uz$mraXX=xBQaBSk`mk?P`E=bk*!8v(fUVT_RzyW@Py704==_7* zWRx)Ji{{4U_k1CaPxp9H;H2#=j80rF9@S(B-7@nPaGR~5dU!v}f-lPF>{`Q>uN3nE zj$7-@ZWFq>WN-5EZ1G>lVW%n99lxVCOaI-DQYH%X6p^s&iu#o;zs{E)_wZ9Y$&9Bg znQD_%LzgHfgb8n?5;Y-4gIIk0Tk)- z5BGyCtqaX^cD|yrkZie%#gcWhktB*K<{W6}>Pgp?*zv#Q_2Lq3?Y)%?z4Z_$+tTyI z7*WU268G}`;kdYG)+&F1yVPm}2wM?DMPNk>7jXynKx5$*-}Rdw+@M zx!xY0!!o8>qyvr8BI(twCNE~{cR7u2+0!d+ovrngPVKsg>7)DFPGjuZk;ZpUf7UcRDkkyjoK~;!G%Lh^iArn|U$M=b*2mjh`^c(u92PjtBd6MzG7x0G? zv1C@LOpeEHbsGm}Wzlro#wRt*R%4^I5`Ehe+alnNf7O84!WV@O6JJ6}a16a^MFIbo zb@@E^q)VMzSDe+LVSOPoe$+QI^QY?#qdWnQ8=5tN;px~>Q}_Xmu!@?aXjeSgq= z)e;^y?>M@;iCUmdl%yC**CMe``IzFJ;0yWSqE8ukEaBYU)4boeu70+(1RIfP-di?Z z@SG1E`~|tI^Q9;jak&HNUqN-zw@5iM&PLp7_edz|yq;9D{~mrF2Wa^Yd-mXQmwW!J&1%avy_?#iCuuRf@l ztKZGM11`b?X1*6#^{k+3)gpPKo+lcifJ+Hp*o|C6}?r^)gDYK8Efd zZO#~sDMtUK$y_b4L!BZ|zq13$g-kz{U&kR6)AA=VgFl0~cQSr9rEj`WZxA6tG+i3> zJk+tnTjAkuT6;Z)Z(RV}5Z|qO5eUDPSWSaQ)z9I39MF;IcpMnRYz}kM8!&Fny!I@`P}`Z-&EV(E_p_OfP*dI-CNB-MD7Tj z{~=C4x<>#hic{lUXlV`HfbgZQ=SpV!z7=Oyi*n^e_lt#3;V+j^w&a zP;Sy6rA~i_JpWCk?x`CSfFm*=@cmf!$*;P+VW#223Iti|T`yL5QojwDc7z(+`ip=S zViFx9?q$#jRMbE6()J>~2#l1=H4t&tTy_^Zt!j@xUeUbUn8llMsg$TgFp^&%4KMrl z26zsnZ7qC{UD|73qJVd~T;QQiLzo#1W%wU+H||$P+wV5}cdkoqOy3UP-%1L4@8~*( zEnU`+wqLWV3mDx2kjH&*3o2)I4M$_Aq30j--i6d^%k?dr$dno}_?O>di7U5%=oTC^ zmJaeYBqDRFP~-mze*aVQ@MHIl_uYrcitP;#pm6C-SEc=~e%{T6`l>2<_WM&s2j6-d z=*LwfFuO89Wb#hHDCj$-to0x?Qx>IVE_XcXiZ}%!|(_4A=DHkkry7sGp zWL=4`dvLJzF|T)yZ?xU<(eRxTIrmD-CD3|reziAqm+-{#r0FNnTf+RwKh1N+T6C7K zA-;VRsO$a-LZE{Bk<~>GjJaIMT^cGWzl|PVh9~A^T?vm_x%cPSEd=3Idu4t2;vK?P z)jH?gfKYG0Ut_CUI4RC_S_yc}KMJ6F=$`dF#$);o05b$icUO{k@UuD3ay2Kwm*{&p zF(rIsff`PYMvp5z2F5TAyii*?JgC2_T*hOx36uG+m0N(lr(n_{$awRjBy9aUaWtFO zq-LqxfyDau#m@AfO)bqYkV%yzUvyh3?nP zN>{A+M91driP0gJm`g?ZgFj+Rwt3_{i?#QVJ-iDzY+PA24FsIAwq}5W#H>q>U&n^T zVQ)_0$?aqPd}yHAmQv5+v3mRCAG+Av`*n2*wuI}To~Uq1v!<8_`W19w9bfO&uvP5U zBZ`||D0)`4@5Id9J_zw+uSsS&A8mB|gnl1z69kVE#i?O`@3u*tbUf*E!%kL6(A#=_31#zf1YA~wkUl$#Km{r5$Gnr*qhMT@8yM~p zFs_zP;-k%lqm$ltgkX>#O@m~h=<{Gr82YH>tyOtxX*Ib^tEe;kBVd}lk`1`@ITmG$ z-(3R5{3fg~2Amcg-{?{NH&0n6zc4Zr`$4Y91Z32g$GpMDZ97lqkMll_FV(Qj34 z4>P-adli7VhO_b1*XUh;_gy34>Hiv(kW3@25Za2EX`ZPt(%<9T+BXd)sNen*5`gb> zLr|ROOBRZU8EIrb5>Va3>TTWaqo(UD{bg z!$m`znx3AgYIZ*IItn`0x;@Ubbg2<>l)%)lc<`ca{i9H2yLX_8w`L=+q1uvD`{L4Y(k$K?ZpWxfWRlRk?mEu&O*@SEt7I{R@2|zx@&cuosQ}#x; zTttSU2wX$ck+Gw>PcS&Sb6OudHOVhe*FDcyQLp`Tytmbjf?8|$jkXT_jy}fT^8g=W$f@T_sI@-KC-p8o=4LfwX(A7VUG)0b_ zZ7gMB%=&^09$_q=n|FWA+u`DHvy;De8)cobL5d70U^?8^}|pMX?Jvk1>RZ>%>!Yld%6tr?b$Dql8x z?l?v^m!4s58K+Vtl6b7NxNV(nsxBMTQ&U1{E@UBRMpTT$pG;O_9&+f!jv=R zYoM^!BgGLI?oHPFhzv!8HwVLAotq+DQR2l*aI#E!Fjo{TpW zoaLB7$e^cw6z=}Z5%7b8$@RYeNf?QY`C3qaFPe2?djv~Z)ANAt~5LuLi7~U4FM45 z$vI%|nCAki1w0}LIXBu1KbMMg>Zr%B3;PP9(~LDjn3|s`5J2;h%kl)&=c#%(I?P4b znUOJfKm7C?La1BS$D6Od2HxXTTvqvP9|2FjI9w`!-@G*yBb9sj{v$TH(5os#NO?;CjctLTNo1QxnO6sQiAaz)V@T><%!Dx zfXUWpBa@?mqa~UV;_>rY6neBiqkiLZPH3p_-n0YJ(J>nQ&1mZ9ob1tIl~VYjBqDkG9hKJSUoBVDW$EICF1>wQ76eg#eMG)o3zv6iUG z0O)~nB8jy(yH)zo+^eq6WsvvwzqW$4_;r8#@4l1v^NO)l;w@SwE-&qEYl;eOt4TvF zc7HZ*_dRue4LI2ls*5vn+*A>2r5R%hBtL29GOJ3nsWWxf5|z2YFBxZId5)dhCag-p ze4ZtA(c-?d2)6c|TVra5U2xlV#OlzRv`A0|Ui$oh?LB!s)Lr+Pcr5iGMvzTHga zcj`gWmeo{k@@IEJ;#GUbj&>R98`zomxy34^ND*}Ta&k#tHSBI9_A=%`ys6AWkB|Rb zr*c}2weQgsQB7W>ueMy_KM||0ND< z3=x*qwpbka<>=lcUlh7+nwYA z+$qn5S3q#0&mY8_!0>_1A2qzIMk(#}` zcUrp8jVezmjkHjWJcw!fs0;APzX_aHnqqpQs7vetcGu*=;U>Y4O%lFe^FE?QW+BtL?? zQIiIHp$D4=);@6D&=HHf|LWL_k4YC48%TQ#w1*DXs) zZ@lqcSIJ7B_Foh&szbYznr>ZfSRGKeGTi7`%Sk5Aam@NIoE2*tcU$V~>!U`{?%M{B z$jRheiGORWYO2Txn7&`2G0oNQ+Q}~YSSnTh!~+|Yej8&76_SDp?oDhg$_{*EI>I!4 z;1S%*)Zi; zU{LT>YIA9d$lDW+1Iq>Kel$9Y>7FZu!hHV9Fr5W^Yztq85EIY41AM za*~M2{4pxBKBmhCFka6NHVplik5BoHpbn8|RxKY#*Oy(-mEaHBK+3Gvz7=zI*q!x! zBj(yfIe{Z)``KxIZLPL-+SwQg9ebW2zLmo{Iu$xD!G~1eq2^zo5ZeA+4*x>>K_KrW zDdN}H{Ji|Rso3d|;LSN9D}pjmc6*7!6bpjeSf`aK;&yBk=*y%kjxHk}N;stb$Y^;F z=Ato5lWL${@86eNg<8m@mra_ZXPVqw;zOof*=>Z}6j7MYF2`66435~&>(xQ)GHHzIN@$g07UTsAUBv^#}~mIyAZ zgQM!dy^iox)-{Ci*2xNVaHL3B_hhE;+A1{zHDJp0o=S4Ihrqrh#)sP0mQFG3 z3z_LteH<0ZZTI51gOz^V)JtH@W~J^HKteuCjYJ)BxRx!@Qn)Ez@J8*`%0HwEG55=rdvh30lPb<~VF}4njz#6k&9^%WKuz^LE zi(`T?oaF7TioPX=+R8%5+v8pLyr;S*kCoPk&<72R&vK|9$-NF&r(ZuXj(kFcFvtdXqG;MFiUFEc{mRsdb}X6y29= zNjDuF0%3{^F>CWzk;VfWiwJ}Q5rQ{Cg<%$&sqbo(`JK&QyJ3IgAhBfc?zAcnp`O88nS{N8#BNT7diNwY*NOEc?l2K4valB z(jG}p(2;DWO?kf*|KP(Ykr%C|sDSQrJ*iN`f8P`x=G5Js*vxgXRr5AJwms-h{lF=n zlCBv%gJxVV$o^iF%V|LRT%^Vo371DWsekwO^u*lWM_Fnt35!$Ty$*5LUj&y{M zItE8`zMn4TM(($RF!*`3D^JUUpC9j}Y%wN)Y|}N@AbiI6&mzL5G2JiXa4oYzNx0j# z5g=TbkKNis+6gv0huN2dK>Df8fo+qVli`GO!#6avoVN7_~KDM6^X&J573^1}3 zTciJP$iM!Au^*3uSyTg6X8vyW6Bv%+GUCxbZPu^{C;&=o6L>{B{{IAlmT*G=SxiKB zY7dZ`4dKLXc~{^+T|M|?ie){k$uRCu|rS60WLXydw~BFZv=MB)|OVJ`=c z`E)TX_EKZ0*EDvJF;)#Pt*trSFGzabziyBdJ5_%IQ(&2{akzctXt$h9z#q8 z6TnlLzo_4LzG##Zz=17kZUx2hGQCrM@hiMjAP>s5_Gvx*4&+0 z%*7bJoJhC=S87qz`HpeDXTqu07DU0o=6&UxvdWK1#if}s`(68dK6qARDAsnh_Op%# z?|__1HMgpXT>4K+6iyXvJX_pn2q~23?^Y%nLgd+vxjVR@Sl4s~OU~Bmm#Zn}zUnu~ zS*czfM>zSpz1+->;4o6r$3H)8ZTmI9YJB#%cw9za-rTS~@m#nKbiOa9wubMXwb6ms z2%gcmPD0&rae)4UtcZQE{v!faZezt|0*B7`$INv`MG+L`tJShvTPHfsvXiVu6VPt@ zdO-=wtIm3$a>tl)51bJf*=*DR1IHRB!Xh=La*(1RpD?NUAvNQ7O9E|b$E%h9fTMFt z^UhrKB$9%_=oWHnYn=zBJW22T3_#|(U7V<3;dv&NT4 zT8oC-JmK!#9XeWGHrCnYFX#OM706C9K3Ec8pd4H?!S$q4?LCr5N;Lj=dG>s{*8vSW zy1c|iQxu;k77j@hK9wt4i&us!mBKS*Au_x-&!0nX`!LJSh4aVwuV}cwDv9qLQUIKj zqo~C~n6})Lf+r`~Z=Z)UJe{^URo;KnJ-{sG+vYDk((%HzS!xF*y&KXq5qDi6WDx8R^f!U5P1^v7y&quj6z<^{&OJCA#7JtanLp zFP(V;HV;jFzQgsY>!w%pPR~U0^+PfAyGR`aF%Qahk&D|su^&&!LAGO^DAT*ng?E-88R^RR zV4KJ)O&8Lg3s4zp)MC|;)m{GaVJ*F!gT~_o5b(gp$eMjSiA)7+h5_ zr8_3ZJme(edq0lJSuOieTNyxamxgUkHD&D zp@V#YM%L{by1}BQ;m}L)D`}ni0<8LT6Hva(-5R6=tlHOw+lZ%f+(MGoXy^h)V_Vqp z!Fg7bqX6`B7;DVh_2=l;hv`e*nDIRn`GxIUU$hPNkN#sc0EWB)n$04{+Ip-shd7Q$ z;jl0F^fL`8^am;_0g57 z{g5E29uyc$vD2d8HgsIDCx9zejs_>mLoukiQLI?_5CQxx4y!hRoT2X-AG`DkCE5f| zkY1zAD%^J|VY&$AtL?cetYS+m4&&@MA&?0y#viJ56)?arj`C(ou*^iO3&(simPbb3 z%VQ4#2{uTM=3b3THmE)Oa}cufuUC??^T~mpry3HOlZ>$SbzHWU zpXgCweF1pM{P*(j3G~+N5x$5}TH|-ZN)e~$v?^|D^( zLxI`92E8qC&(x` Date: Mon, 27 May 2024 14:00:30 +0900 Subject: [PATCH 23/60] =?UTF-8?q?[#M10]=20feat=20:=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 580 +----------------- .../migration.sql | 60 ++ prisma/mock.js | 3 - prisma/schema.prisma | 54 +- routes/articles.js | 295 +++++++++ routes/images.js | 41 ++ routes/products.js | 252 ++++++++ uploads/.gitkeep | 0 utils/asyncHandler.js | 26 + 9 files changed, 724 insertions(+), 587 deletions(-) create mode 100644 prisma/migrations/20240527043147_add_user_and_favorite_model_and_change_product_model/migration.sql create mode 100644 routes/articles.js create mode 100644 routes/images.js create mode 100644 routes/products.js create mode 100644 uploads/.gitkeep create mode 100644 utils/asyncHandler.js diff --git a/app.js b/app.js index 37ed8b3..bb5098e 100644 --- a/app.js +++ b/app.js @@ -1,579 +1,15 @@ -import { Prisma, PrismaClient } from "@prisma/client"; import express from "express"; -import multer from "multer"; -import path from "path"; -import { assert } from "superstruct"; -import { CreateArticle, CreateComment, CreateProduct, PatchArticle, PatchComment, PatchProduct } from "./structs.js"; -const SERVER_URL = "http://localhost:3000"; - -const prisma = new PrismaClient(); +import articlesRouter from "./routes/articles.js"; +import imagesRouter from "./routes/images.js"; +import productsRouter from "./routes/products.js"; const app = express(); app.use(express.json()); app.use(express.urlencoded({ extended: true })); -const storage = multer.diskStorage({ - destination: (req, file, cb) => { - cb(null, "uploads/"); - }, - filename: (req, file, cb) => { - const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9); - cb(null, file.fieldname + "-" + uniqueSuffix + path.extname(file.originalname)); - }, -}); - -const upload = multer({ storage: storage }); - -app.post("/images/upload", upload.single("image"), async (req, res) => { - const file = req.file; - console.log(req); - if (!file) { - return res.status(400).send("이미지 파일을 선택해주세요."); - } - const imagePath = file.path; - const imageUrl = `${SERVER_URL}/${imagePath.replace(/\\/g, "/")}`; - const image = await prisma.image.create({ - data: { - imagePath: imagePath, - }, - }); +app.use("/products", productsRouter); +app.use("/articles", articlesRouter); +app.use("/images", imagesRouter); - res.status(200).json({ url: imageUrl }); +app.listen(3000, () => { + console.log("Server is running on port 3000"); }); - -const asyncHandler = (handler) => { - return async (req, res) => { - try { - await handler(req, res); - } catch (e) { - if (e.name === "StructError") { - const errors = e.failures().map((failure) => ({ - path: failure.path.join("."), - message: failure.message, - })); - res.status(400).json({ message: "유효성 검사 오류입니다.", errors }); - } else if (e instanceof Prisma.PrismaClientValidationError) { - res.status(400).json({ message: e.message }); - } else if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") { - res.status(404).json({ message: "존재하지 않는 게시글입니다." }); - } else { - console.error(e); - res.status(500).json({ message: "서버 에러입니다." }); - } - } - }; -}; - -// 상품 목록 조회 -app.get( - "/products", - asyncHandler(async (req, res) => { - /** - * 쿼리 파라미터 - * - offset : 가져올 데이터의 시작 지점 - * - limit : 한 번에 가져올 데이터의 개수 - * - orderBy : 정렬 기준 favorite, recent (기본값: recent) - * - keyword : 검색 키워드 - */ - const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; - const order = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; - const products = await prisma.product.findMany({ - orderBy: order, - skip: parseInt(offset), - take: parseInt(limit), - where: { - OR: [ - { - name: { - contains: keyword, - mode: "insensitive", - }, - }, - { - description: { - contains: keyword, - mode: "insensitive", - }, - }, - ], - }, - }); - res.send(products); - }) -); - -// 상품 상세 조회 -app.get( - "/products/:id", - asyncHandler(async (req, res) => { - const { id } = req.params; - const product = await prisma.product.findUniqueOrThrow({ - where: { - id, - }, - }); - res.send(product); - }) -); - -// 상품 등록 -app.post( - "/products", - asyncHandler(async (req, res) => { - assert(req.body, CreateProduct); - const product = await prisma.product.create({ - data: req.body, - }); - res.status(201).send(product); - }) -); - -// 상품 수정 -app.patch( - "/products/:id", - asyncHandler(async (req, res) => { - assert(req.body, PatchProduct); - const { id } = req.params; - const product = await prisma.product.update({ - where: { - id, - }, - data: req.body, - }); - - res.send(product); - }) -); - -// 상품 삭제 -app.delete( - "/products/:id", - asyncHandler(async (req, res) => { - const { id } = req.params; - await prisma.product.delete({ - where: { - id, - }, - }); - - res.sendStatus(204); - }) -); - -// 상품 좋아요 -app.patch( - "/products/:id/like", - asyncHandler(async (req, res) => { - const product = await prisma.product.findUniqueOrThrow({ - where: { - id: req.params.id, - }, - }); - - if (product.isFavorite) { - res.status(400).send({ message: "이미 좋아요 처리된 상품입니다." }); - return; - } - - const updatedProduct = await prisma.product.update({ - where: { - id: req.params.id, - }, - data: { - favoriteCount: { - increment: 1, - }, - isFavorite: true, - }, - }); - - res.send(updatedProduct); - }) -); - -// 상품 좋아요 취소 -app.patch( - "/products/:id/unlike", - asyncHandler(async (req, res) => { - const product = await prisma.product.findUniqueOrThrow({ - where: { - id: req.params.id, - }, - }); - - if (!product.isFavorite) { - res.status(400).send({ message: "아직 좋아요 처리되지 않은 상품입니다." }); - return; - } - - const updatedProduct = await prisma.product.update({ - where: { - id: req.params.id, - }, - data: { - favoriteCount: { - decrement: 1, - }, - isFavorite: false, - }, - }); - - res.send(updatedProduct); - }) -); - -// 게시글 목록 조회 -app.get( - "/articles", - asyncHandler(async (req, res) => { - /** - * 쿼리 파라미터 - * - offset : 가져올 데이터의 시작 지점 - * - limit : 한 번에 가져올 데이터의 개수 - * - orderBy : 정렬 기준 like, recent (기본값: recent) - */ - const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; - const order = orderBy === "like" ? { likeCount: "desc" } : { createdAt: "desc" }; - const articles = await prisma.article.findMany({ - select: { - id: true, - title: true, - content: true, - imageUrl: true, - createdAt: true, - writer: true, - }, - orderBy: order, - skip: parseInt(offset), - take: parseInt(limit), - where: { - OR: [ - { - title: { - contains: keyword, - mode: "insensitive", - }, - }, - { - content: { - contains: keyword, - mode: "insensitive", - }, - }, - ], - }, - }); - // 좋아요가 많은 상위 4개의 글 조회 - const bestArticles = await prisma.article.findMany({ - orderBy: { - likeCount: "desc", - }, - take: 4, - }); - - res.send({ articles, bestArticles }); - }) -); - -// 게시글 상세 조회 -app.get( - "/articles/:id", - asyncHandler(async (req, res) => { - const { id } = req.params; - const article = await prisma.article.findUniqueOrThrow({ - where: { - id, - }, - select: { - id: true, - title: true, - content: true, - imageUrl: true, - createdAt: true, - likeCount: true, - isLiked: true, - writer: true, - }, - }); - res.send(article); - }) -); - -// 게시글 등록 -app.post( - "/articles", - asyncHandler(async (req, res) => { - assert(req.body, CreateArticle); - const article = await prisma.article.create({ - data: req.body, - }); - res.status(201).send(article); - }) -); - -// 게시글 수정 -app.patch( - "/articles/:id", - asyncHandler(async (req, res) => { - assert(req.body, PatchArticle); - const { id } = req.params; - const article = await prisma.article.update({ - where: { - id, - }, - data: req.body, - }); - - res.send(article); - }) -); - -// 게시글 삭제 -app.delete( - "/articles/:id", - asyncHandler(async (req, res) => { - const { id } = req.params; - await prisma.article.delete({ - where: { - id, - }, - }); - - res.sendStatus(204); - }) -); - -// 게시글 좋아요 -app.patch( - "/articles/:id/like", - asyncHandler(async (req, res) => { - const article = await prisma.article.findUniqueOrThrow({ - where: { - id: req.params.id, - }, - }); - - if (article.isLiked) { - res.status(400).send({ message: "이미 좋아요 처리된 게시글입니다." }); - return; - } - - const updatedArticle = await prisma.article.update({ - where: { - id: req.params.id, - }, - data: { - likeCount: { - increment: 1, - }, - isLiked: true, - }, - }); - - res.send(updatedArticle); - }) -); - -// 게시글 좋아요 취소 -app.patch( - "/articles/:id/unlike", - asyncHandler(async (req, res) => { - const article = await prisma.article.findUniqueOrThrow({ - where: { - id: req.params.id, - }, - }); - - if (!article.isLiked) { - res.status(400).send({ message: "아직 좋아요 처리되지 않은 게시글입니다." }); - return; - } - - const updatedArticle = await prisma.article.update({ - where: { - id: req.params.id, - }, - data: { - likeCount: { - decrement: 1, - }, - isLiked: false, - }, - }); - - res.send(updatedArticle); - }) -); - -// 중고마켓 댓글 목록 조회 -app.get( - "/products/:id/comments", - asyncHandler(async (req, res) => { - const { id } = req.params; - const { cursor } = req.query; - let queryOptions = { - take: 10, - orderBy: { - createdAt: "desc", - }, - where: { - productId: id, - }, - select: { - id: true, - content: true, - createdAt: true, - writer: true, - }, - }; - - if (cursor) { - queryOptions = { - ...queryOptions, - cursor: { - id: cursor, - }, - skip: 1, - }; - } - - const comments = await prisma.comment.findMany(queryOptions); - res.send(comments); - }) -); - -// 중고마켓 댓글 등록 -app.post( - "/products/:id/comments", - asyncHandler(async (req, res) => { - assert(req.body, CreateComment); - const { id } = req.params; - - const comment = await prisma.comment.create({ - data: { - ...req.body, - productId: id, - }, - }); - res.status(201).send(comment); - }) -); - -// 중고마켓 댓글 수정 -app.patch( - "/products/:id/comments/:commentId", - asyncHandler(async (req, res) => { - assert(req.body, PatchComment); - const { commentId } = req.params; - const comment = await prisma.comment.update({ - where: { - id: commentId, - }, - data: req.body, - }); - - res.send(comment); - }) -); - -// 중고마켓 댓글 삭제 -app.delete( - "/products/:id/comments/:commentId", - asyncHandler(async (req, res) => { - const { commentId } = req.params; - await prisma.comment.delete({ - where: { - id: commentId, - }, - }); - - res.sendStatus(204); - }) -); - -// 자유게시판 댓글 목록 조회 -app.get( - "/articles/:id/comments", - asyncHandler(async (req, res) => { - const { id } = req.params; - const { cursor } = req.query; - let queryOptions = { - take: 10, - orderBy: { - createdAt: "desc", - }, - where: { - articleId: id, - }, - select: { - id: true, - content: true, - createdAt: true, - writer: true, - }, - }; - - if (cursor) { - queryOptions = { - ...queryOptions, - cursor: { - id: cursor, - }, - skip: 1, - }; - } - - const comments = await prisma.comment.findMany(queryOptions); - res.send(comments); - }) -); - -// 자유게시판 댓글 등록 -app.post( - "/articles/:id/comments", - asyncHandler(async (req, res) => { - assert(req.body, CreateComment); - const { id } = req.params; - - const comment = await prisma.comment.create({ - data: { - ...req.body, - articleId: id, - }, - }); - res.status(201).send(comment); - }) -); - -// 자유게시판 댓글 수정 -app.patch( - "/articles/:id/comments/:commentId", - asyncHandler(async (req, res) => { - assert(req.body, PatchComment); - const { commentId } = req.params; - const comment = await prisma.comment.update({ - where: { - id: commentId, - }, - data: req.body, - }); - - res.send(comment); - }) -); - -// 중고마켓 댓글 삭제 -app.delete( - "/articles/:id/comments/:commentId", - asyncHandler(async (req, res) => { - const { commentId } = req.params; - await prisma.comment.delete({ - where: { - id: commentId, - }, - }); - - res.sendStatus(204); - }) -); - -app.listen(process.env.PORT || 3000, () => console.log("Server Started")); diff --git a/prisma/migrations/20240527043147_add_user_and_favorite_model_and_change_product_model/migration.sql b/prisma/migrations/20240527043147_add_user_and_favorite_model_and_change_product_model/migration.sql new file mode 100644 index 0000000..50bbf1d --- /dev/null +++ b/prisma/migrations/20240527043147_add_user_and_favorite_model_and_change_product_model/migration.sql @@ -0,0 +1,60 @@ +/* + Warnings: + + - You are about to drop the column `isLiked` on the `Article` table. All the data in the column will be lost. + - You are about to drop the column `isFavorite` on the `Product` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "Article" DROP COLUMN "isLiked", +ADD COLUMN "userId" INTEGER; + +-- AlterTable +ALTER TABLE "Product" DROP COLUMN "isFavorite", +ADD COLUMN "userId" INTEGER; + +-- CreateTable +CREATE TABLE "User" ( + "id" SERIAL NOT NULL, + "email" TEXT NOT NULL, + "name" TEXT, + "nickname" TEXT NOT NULL, + "image" TEXT, + "password" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Favorite" ( + "id" SERIAL NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "userId" INTEGER NOT NULL, + "productId" TEXT, + "articleId" TEXT, + + CONSTRAINT "Favorite_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "Favorite_userId_productId_articleId_key" ON "Favorite"("userId", "productId", "articleId"); + +-- AddForeignKey +ALTER TABLE "Product" ADD CONSTRAINT "Product_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Article" ADD CONSTRAINT "Article_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Favorite" ADD CONSTRAINT "Favorite_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Favorite" ADD CONSTRAINT "Favorite_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Favorite" ADD CONSTRAINT "Favorite_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/mock.js b/prisma/mock.js index 0b4e46e..a68eed2 100644 --- a/prisma/mock.js +++ b/prisma/mock.js @@ -30,7 +30,6 @@ export const ARTICLES = [ content: "판다인형 구매 후기입니다.", imageUrl: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", likeCount: 7, - isLiked: false, writer: "판다인형 수집가", }, { @@ -39,7 +38,6 @@ export const ARTICLES = [ content: "판다인형 판매 후기입니다.", imageUrl: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", likeCount: 2, - isLiked: true, writer: "판다인형 중개인", }, { @@ -48,7 +46,6 @@ export const ARTICLES = [ content: "불곰인형 구하는 곳 아시는분 계신가요?", imageUrl: "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg", likeCount: 3, - isLiked: false, writer: "불곰인형 수집가", }, ]; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f586145..dae5e66 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -3,7 +3,6 @@ // Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? // Try Prisma Accelerate: https://pris.ly/cli/accelerate-init - generator client { provider = "prisma-client-js" } @@ -13,34 +12,52 @@ datasource db { url = env("DATABASE_URL") } +model User { + id Int @id @default(autoincrement()) + email String @unique + name String? + nickname String + image String? + password String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + products Product[] + articles Article[] + favorites Favorite[] +} + model Product { - id String @id @default(uuid()) + id String @id @default(uuid()) name String description String price Float tags String[] images String[] - favoriteCount Int @default(0) - isFavorite Boolean @default(false) + favoriteCount Int @default(0) ownerId Int - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt comments Comment[] Image Image[] + User User? @relation(fields: [userId], references: [id]) + userId Int? + favorites Favorite[] } model Article { - id String @id @default(uuid()) + id String @id @default(uuid()) title String content String - imageUrl String? @default("") - likeCount Int @default(0) - isLiked Boolean @default(false) + imageUrl String? @default("") + likeCount Int @default(0) writer String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt comments Comment[] Image Image[] + User User? @relation(fields: [userId], references: [id]) + userId Int? + favorites Favorite[] } model Comment { @@ -71,3 +88,16 @@ model Image { @@index([productId]) @@index([articleId]) } + +model Favorite { + id Int @id @default(autoincrement()) + createdAt DateTime @default(now()) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + userId Int + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) + productId String? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) + articleId String? + + @@unique([userId, productId, articleId]) +} diff --git a/routes/articles.js b/routes/articles.js new file mode 100644 index 0000000..ae32411 --- /dev/null +++ b/routes/articles.js @@ -0,0 +1,295 @@ +import { PrismaClient } from "@prisma/client"; +import express from "express"; +import { assert } from "superstruct"; +import { CreateArticle, CreateComment, PatchArticle, PatchComment } from "../structs.js"; +import asyncHandler from "../utils/asyncHandler.js"; + +const prisma = new PrismaClient(); +const router = express.Router(); +// 게시글 목록 조회 +router.get( + "/", + asyncHandler(async (req, res) => { + /** + * 쿼리 파라미터 + * - offset : 가져올 데이터의 시작 지점 + * - limit : 한 번에 가져올 데이터의 개수 + * - orderBy : 정렬 기준 like, recent (기본값: recent) + */ + const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; + const order = orderBy === "like" ? { likeCount: "desc" } : { createdAt: "desc" }; + const articles = await prisma.article.findMany({ + select: { + id: true, + title: true, + content: true, + imageUrl: true, + createdAt: true, + writer: true, + }, + orderBy: order, + skip: parseInt(offset), + take: parseInt(limit), + where: { + OR: [ + { + title: { + contains: keyword, + mode: "insensitive", + }, + }, + { + content: { + contains: keyword, + mode: "insensitive", + }, + }, + ], + }, + }); + // 좋아요가 많은 상위 4개의 글 조회 + const bestArticles = await prisma.article.findMany({ + orderBy: { + likeCount: "desc", + }, + take: 4, + }); + + res.send({ articles, bestArticles }); + }) +); + +// 게시글 상세 조회 +router.get( + "/:id", + asyncHandler(async (req, res) => { + const { id } = req.params; + const article = await prisma.article.findUniqueOrThrow({ + where: { + id, + }, + select: { + id: true, + title: true, + content: true, + imageUrl: true, + createdAt: true, + likeCount: true, + writer: true, + }, + }); + res.send(article); + }) +); + +// 게시글 등록 +router.post( + "/", + asyncHandler(async (req, res) => { + assert(req.body, CreateArticle); + const article = await prisma.article.create({ + data: req.body, + }); + res.status(201).send(article); + }) +); + +// 게시글 수정 +router.patch( + "/:id", + asyncHandler(async (req, res) => { + assert(req.body, PatchArticle); + const { id } = req.params; + const article = await prisma.article.update({ + where: { + id, + }, + data: req.body, + }); + + res.send(article); + }) +); + +// 게시글 삭제 +router.delete( + "/:id", + asyncHandler(async (req, res) => { + const { id } = req.params; + await prisma.article.delete({ + where: { + id, + }, + }); + + res.sendStatus(204); + }) +); + +// 게시글 좋아요 +router.patch( + "/:id/like", + asyncHandler(async (req, res) => { + const article = await prisma.article.findUniqueOrThrow({ + where: { + id: req.params.id, + }, + }); + + const favorite = await prisma.favorite.findUnique({ + where: { + userId_productId_articleId: { + userId: req.userId, + articleId: req.params.id, + }, + }, + }); + + if (favorite) { + res.status(400).send({ message: "이미 좋아요 처리된 게시글입니다." }); + return; + } + + const updatedArticle = await prisma.article.update({ + where: { + id: req.params.id, + }, + data: { + likeCount: { + increment: 1, + }, + isLiked: true, + }, + }); + + res.send(updatedArticle); + }) +); + +// 게시글 좋아요 취소 +router.patch( + "/:id/unlike", + asyncHandler(async (req, res) => { + const article = await prisma.article.findUniqueOrThrow({ + where: { + id: req.params.id, + }, + }); + + const favorite = await prisma.favorite.findUnique({ + where: { + userId_productId_articleId: { + userId: req.userId, + articleId: req.params.id, + }, + }, + }); + + if (!favorite) { + res.status(400).send({ message: "아직 좋아요 처리되지 않은 게시글입니다." }); + return; + } + + const updatedArticle = await prisma.article.update({ + where: { + id: req.params.id, + }, + data: { + likeCount: { + decrement: 1, + }, + isLiked: false, + }, + }); + + res.send(updatedArticle); + }) +); + +// 자유게시판 댓글 목록 조회 +router.get( + "/:id/comments", + asyncHandler(async (req, res) => { + const { id } = req.params; + const { cursor } = req.query; + let queryOptions = { + take: 10, + orderBy: { + createdAt: "desc", + }, + where: { + articleId: id, + }, + select: { + id: true, + content: true, + createdAt: true, + writer: true, + }, + }; + + if (cursor) { + queryOptions = { + ...queryOptions, + cursor: { + id: cursor, + }, + skip: 1, + }; + } + + const comments = await prisma.comment.findMany(queryOptions); + res.send(comments); + }) +); + +// 자유게시판 댓글 등록 +router.post( + "/:id/comments", + asyncHandler(async (req, res) => { + assert(req.body, CreateComment); + const { id } = req.params; + + const comment = await prisma.comment.create({ + data: { + ...req.body, + articleId: id, + }, + }); + res.status(201).send(comment); + }) +); + +// 자유게시판 댓글 수정 +router.patch( + "/:id/comments/:commentId", + asyncHandler(async (req, res) => { + assert(req.body, PatchComment); + const { commentId } = req.params; + const comment = await prisma.comment.update({ + where: { + id: commentId, + }, + data: req.body, + }); + + res.send(comment); + }) +); + +// 중고마켓 댓글 삭제 +router.delete( + "/:id/comments/:commentId", + asyncHandler(async (req, res) => { + const { commentId } = req.params; + await prisma.comment.delete({ + where: { + id: commentId, + }, + }); + + res.sendStatus(204); + }) +); + +export default router; diff --git a/routes/images.js b/routes/images.js new file mode 100644 index 0000000..8b0876c --- /dev/null +++ b/routes/images.js @@ -0,0 +1,41 @@ +import { PrismaClient } from "@prisma/client"; +import express from "express"; +import multer from "multer"; +import path from "path"; + +const prisma = new PrismaClient(); +const SERVER_URL = "http://localhost:3000"; + +const router = express.Router(); + +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + cb(null, "uploads/"); + }, + filename: (req, file, cb) => { + const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9); + cb(null, file.fieldname + "-" + uniqueSuffix + path.extname(file.originalname)); + }, +}); + +const upload = multer({ storage: storage }); + +// 이미지 업로드 +router.post("/upload", upload.single("image"), async (req, res) => { + const file = req.file; + console.log(req); + if (!file) { + return res.status(400).send("이미지 파일을 선택해주세요."); + } + const imagePath = file.path; + const imageUrl = `${SERVER_URL}/${imagePath.replace(/\\/g, "/")}`; + const image = await prisma.image.create({ + data: { + imagePath: imagePath, + }, + }); + + res.status(200).json({ url: imageUrl }); +}); + +export default router; diff --git a/routes/products.js b/routes/products.js new file mode 100644 index 0000000..2bea203 --- /dev/null +++ b/routes/products.js @@ -0,0 +1,252 @@ +import { PrismaClient } from "@prisma/client"; +import express from "express"; +import { assert } from "superstruct"; +import { CreateComment, CreateProduct, PatchComment, PatchProduct } from "../structs.js"; +import asyncHandler from "../utils/asyncHandler.js"; + +const prisma = new PrismaClient(); +const router = express.Router(); // 상품 목록 조회 +router.get( + "/", + asyncHandler(async (req, res) => { + /** + * 쿼리 파라미터 + * - offset : 가져올 데이터의 시작 지점 + * - limit : 한 번에 가져올 데이터의 개수 + * - orderBy : 정렬 기준 favorite, recent (기본값: recent) + * - keyword : 검색 키워드 + */ + const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; + const order = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; + const products = await prisma.product.findMany({ + orderBy: order, + skip: parseInt(offset), + take: parseInt(limit), + where: { + OR: [ + { + name: { + contains: keyword, + mode: "insensitive", + }, + }, + { + description: { + contains: keyword, + mode: "insensitive", + }, + }, + ], + }, + }); + res.send(products); + }) +); + +// 상품 상세 조회 +router.get( + "/:id", + asyncHandler(async (req, res) => { + const { id } = req.params; + const product = await prisma.product.findUniqueOrThrow({ + where: { + id, + }, + }); + res.send(product); + }) +); + +// 상품 등록 +router.post( + "/", + asyncHandler(async (req, res) => { + assert(req.body, CreateProduct); + const product = await prisma.product.create({ + data: req.body, + }); + res.status(201).send(product); + }) +); + +// 상품 수정 +router.patch( + "/:id", + asyncHandler(async (req, res) => { + assert(req.body, PatchProduct); + const { id } = req.params; + const product = await prisma.product.update({ + where: { + id, + }, + data: req.body, + }); + + res.send(product); + }) +); + +// 상품 삭제 +router.delete( + "/:id", + asyncHandler(async (req, res) => { + const { id } = req.params; + await prisma.product.delete({ + where: { + id, + }, + }); + + res.sendStatus(204); + }) +); + +// 상품 좋아요 +router.patch( + "/:id/like", + asyncHandler(async (req, res) => { + const product = await prisma.product.findUniqueOrThrow({ + where: { + id: req.params.id, + }, + }); + + if (product.isFavorite) { + res.status(400).send({ message: "이미 좋아요 처리된 상품입니다." }); + return; + } + + const updatedProduct = await prisma.product.update({ + where: { + id: req.params.id, + }, + data: { + favoriteCount: { + increment: 1, + }, + isFavorite: true, + }, + }); + + res.send(updatedProduct); + }) +); + +// 상품 좋아요 취소 +router.patch( + "/:id/unlike", + asyncHandler(async (req, res) => { + const product = await prisma.product.findUniqueOrThrow({ + where: { + id: req.params.id, + }, + }); + + if (!product.isFavorite) { + res.status(400).send({ message: "아직 좋아요 처리되지 않은 상품입니다." }); + return; + } + + const updatedProduct = await prisma.product.update({ + where: { + id: req.params.id, + }, + data: { + favoriteCount: { + decrement: 1, + }, + isFavorite: false, + }, + }); + + res.send(updatedProduct); + }) +); + +// 중고마켓 댓글 목록 조회 +router.get( + "/:id/comments", + asyncHandler(async (req, res) => { + const { id } = req.params; + const { cursor } = req.query; + let queryOptions = { + take: 10, + orderBy: { + createdAt: "desc", + }, + where: { + productId: id, + }, + select: { + id: true, + content: true, + createdAt: true, + writer: true, + }, + }; + + if (cursor) { + queryOptions = { + ...queryOptions, + cursor: { + id: cursor, + }, + skip: 1, + }; + } + + const comments = await prisma.comment.findMany(queryOptions); + res.send(comments); + }) +); + +// 중고마켓 댓글 등록 +router.post( + "/:id/comments", + asyncHandler(async (req, res) => { + assert(req.body, CreateComment); + const { id } = req.params; + + const comment = await prisma.comment.create({ + data: { + ...req.body, + productId: id, + }, + }); + res.status(201).send(comment); + }) +); + +// 중고마켓 댓글 수정 +router.patch( + "/:id/comments/:commentId", + asyncHandler(async (req, res) => { + assert(req.body, PatchComment); + const { commentId } = req.params; + const comment = await prisma.comment.update({ + where: { + id: commentId, + }, + data: req.body, + }); + + res.send(comment); + }) +); + +// 중고마켓 댓글 삭제 +router.delete( + "/:id/comments/:commentId", + asyncHandler(async (req, res) => { + const { commentId } = req.params; + await prisma.comment.delete({ + where: { + id: commentId, + }, + }); + + res.sendStatus(204); + }) +); + +export default router; diff --git a/uploads/.gitkeep b/uploads/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/utils/asyncHandler.js b/utils/asyncHandler.js new file mode 100644 index 0000000..15c70c4 --- /dev/null +++ b/utils/asyncHandler.js @@ -0,0 +1,26 @@ +import { Prisma } from "@prisma/client"; + +const asyncHandler = (handler) => { + return async (req, res) => { + try { + await handler(req, res); + } catch (e) { + if (e.name === "StructError") { + const errors = e.failures().map((failure) => ({ + path: failure.path.join("."), + message: failure.message, + })); + res.status(400).json({ message: "유효성 검사 오류입니다.", errors }); + } else if (e instanceof Prisma.PrismaClientValidationError) { + res.status(400).json({ message: e.message }); + } else if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") { + res.status(404).json({ message: "존재하지 않는 게시글입니다." }); + } else { + console.error(e); + res.status(500).json({ message: "서버 에러입니다." }); + } + } + }; +}; + +export default asyncHandler; From e1f70381a923d243b79f0559d0104f3e35ca70cb Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Mon, 27 May 2024 15:40:57 +0900 Subject: [PATCH 24/60] =?UTF-8?q?[#M10]=20feat=20:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85,=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 3 + http/auth.http | 29 ++ middlewares/authenticate.js | 25 ++ package-lock.json | 563 +++++++++++++++++++++++++++++++++++- package.json | 2 + routes/auth.js | 97 +++++++ structs.js | 15 +- utils/tokens.js | 14 + 8 files changed, 734 insertions(+), 14 deletions(-) create mode 100644 http/auth.http create mode 100644 middlewares/authenticate.js create mode 100644 routes/auth.js create mode 100644 utils/tokens.js diff --git a/app.js b/app.js index bb5098e..e8f8057 100644 --- a/app.js +++ b/app.js @@ -1,7 +1,9 @@ import express from "express"; import articlesRouter from "./routes/articles.js"; +import authRouter from "./routes/auth.js"; import imagesRouter from "./routes/images.js"; import productsRouter from "./routes/products.js"; + const app = express(); app.use(express.json()); app.use(express.urlencoded({ extended: true })); @@ -9,6 +11,7 @@ app.use(express.urlencoded({ extended: true })); app.use("/products", productsRouter); app.use("/articles", articlesRouter); app.use("/images", imagesRouter); +app.use("/auth", authRouter); app.listen(3000, () => { console.log("Server is running on port 3000"); diff --git a/http/auth.http b/http/auth.http new file mode 100644 index 0000000..da4cb67 --- /dev/null +++ b/http/auth.http @@ -0,0 +1,29 @@ +POST http://localhost:3000/auth/signUp +Content-Type: application/json + +{ + "email":"test4@gmail.com", + "password":"pandapower", + "name":"김판다", + "nickname":"판다의 왕" +} + +### +# 로그인 + +POST http://localhost:3000/auth/signIn +Content-Type: application/json + +{ + "email":"test4@gmail.com", + "password":"pandapower" +} + +### +# 토큰 재발급 +POST http://localhost:3000/auth/refresh-token +Content-Type: application/json + +{ + "refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjcsImlhdCI6MTcxNjc5MTY3NiwiZXhwIjoxNzE3Mzk2NDc2fQ.wcGjW1SsWm7OKELCcKI-1aA9rmxt1FxmE9SYAJJjgwc" +} \ No newline at end of file diff --git a/middlewares/authenticate.js b/middlewares/authenticate.js new file mode 100644 index 0000000..f891647 --- /dev/null +++ b/middlewares/authenticate.js @@ -0,0 +1,25 @@ +import dotenv from "dotenv"; +import jwt from "jsonwebtoken"; + +dotenv.config(); + +const JWT_SECRET = process.env.JWT_SECRET; + +const authenticate = (req, res, next) => { + const authHeader = req.headers.authorization; + if (!authHeader) { + return res.status(401).json({ message: "No token provided" }); + } + + const token = authHeader.split(" ")[1]; + + try { + const decoded = jwt.verify(token, JWT_SECRET); + req.userId = decoded.userId; + next(); + } catch (error) { + res.status(401).json({ message: "올바르지 않은 토큰입니다." }); + } +}; + +export default authenticate; diff --git a/package-lock.json b/package-lock.json index 1a2d057..9d0d87d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,10 +6,12 @@ "": { "dependencies": { "@prisma/client": "^5.4.2", + "bcrypt": "^5.1.1", "dotenv": "^16.3.1", "express": "^4.18.2", "is-email": "^1.0.2", "is-uuid": "^1.0.2", + "jsonwebtoken": "^9.0.2", "multer": "^1.4.5-lts.1", "prisma": "^5.4.2", "superstruct": "^1.0.3" @@ -18,6 +20,25 @@ "nodemon": "^3.0.1" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, "node_modules/@prisma/client": { "version": "5.14.0", "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.14.0.tgz", @@ -75,6 +96,11 @@ "@prisma/debug": "5.14.0" } }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -87,6 +113,25 @@ "node": ">= 0.6" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -105,6 +150,37 @@ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -113,8 +189,20 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } }, "node_modules/binary-extensions": { "version": "2.3.0", @@ -168,7 +256,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -186,6 +273,11 @@ "node": ">=8" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -252,11 +344,26 @@ "fsevents": "~2.3.2" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/concat-stream": { "version": "1.6.2", @@ -272,6 +379,11 @@ "typedarray": "^0.0.6" } }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -313,7 +425,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -329,8 +440,7 @@ "node_modules/debug/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/define-data-property": { "version": "1.1.4", @@ -348,6 +458,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -365,6 +480,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, "node_modules/dotenv": { "version": "16.4.5", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", @@ -376,11 +499,24 @@ "url": "https://dotenvx.com" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -533,6 +669,33 @@ "node": ">= 0.6" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -555,6 +718,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -573,6 +756,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -638,6 +841,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -664,6 +872,18 @@ "node": ">= 0.8" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -681,6 +901,16 @@ "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", "dev": true }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -720,6 +950,14 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -751,6 +989,103 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -806,7 +1141,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -822,6 +1156,37 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -863,6 +1228,30 @@ "node": ">= 0.6" } }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/nodemon": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", @@ -891,6 +1280,20 @@ "url": "https://opencollective.com/nodemon" } }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -900,6 +1303,18 @@ "node": ">=0.10.0" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -927,6 +1342,14 @@ "node": ">= 0.8" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -935,6 +1358,14 @@ "node": ">= 0.8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -1057,6 +1488,21 @@ "node": ">=8.10.0" } }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1085,7 +1531,6 @@ "version": "7.6.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -1143,6 +1588,11 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -1181,6 +1631,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", @@ -1222,6 +1677,30 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/superstruct": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", @@ -1242,6 +1721,33 @@ "node": ">=4" } }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1271,6 +1777,11 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -1323,6 +1834,33 @@ "node": ">= 0.8" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -1330,6 +1868,11 @@ "engines": { "node": ">=0.4" } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/package.json b/package.json index 52e3a0a..3ffcaec 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,12 @@ { "dependencies": { "@prisma/client": "^5.4.2", + "bcrypt": "^5.1.1", "dotenv": "^16.3.1", "express": "^4.18.2", "is-email": "^1.0.2", "is-uuid": "^1.0.2", + "jsonwebtoken": "^9.0.2", "multer": "^1.4.5-lts.1", "prisma": "^5.4.2", "superstruct": "^1.0.3" diff --git a/routes/auth.js b/routes/auth.js new file mode 100644 index 0000000..5e7eee3 --- /dev/null +++ b/routes/auth.js @@ -0,0 +1,97 @@ +import { PrismaClient } from "@prisma/client"; +import bcrypt from "bcrypt"; +import dotenv from "dotenv"; +import express from "express"; +import jwt from "jsonwebtoken"; +import { assert } from "superstruct"; +import { CreateUser } from "../structs.js"; +import asyncHandler from "../utils/asyncHandler.js"; +import { generateAccessToken, generateRefreshToken } from "../utils/tokens.js"; + +dotenv.config(); +const router = express.Router(); +const prisma = new PrismaClient(); + +const JWT_SECRET = process.env.JWT_SECRET; + +// 회원가입 +router.post( + "/signUp", + asyncHandler(async (req, res) => { + const { email, password, name, nickname } = req.body; + assert(req.body, CreateUser); + const hashedPassword = await bcrypt.hash(password, 10); + const existingUser = await prisma.user.findUnique({ + where: { email }, + }); + + if (existingUser) { + return res.status(400).json({ message: "이미 가입된 이메일입니다." }); + } + + await prisma.user.create({ + data: { + email, + password: hashedPassword, + name, + nickname, + }, + }); + + res.status(201).json({ message: "회원가입이 완료되었습니다." }); + }) +); +// 사용자 로그인 +router.post( + "/signIn", + asyncHandler(async (req, res) => { + const { email, password } = req.body; + + const user = await prisma.user.findUnique({ + where: { email }, + }); + + if (!user) { + return res.status(401).json({ message: "이메일과 비밀번호를 확인해주세요." }); + } + + const isPasswordValid = await bcrypt.compare(password, user.password); + + if (!isPasswordValid) { + return res.status(401).json({ message: "이메일과 비밀번호를 확인해주세요." }); + } + + const accessToken = generateAccessToken(user); + const refreshToken = generateRefreshToken(user); + + res.json({ accessToken, refreshToken }); + }) +); + +router.post( + "/refresh-token", + asyncHandler(async (req, res) => { + const { refreshToken } = req.body; + + if (!refreshToken) { + return res.status(401).json({ message: "토큰은 필수값입니다." }); + } + + try { + const decoded = jwt.verify(refreshToken, JWT_SECRET); + const user = await prisma.user.findUnique({ where: { id: decoded.userId } }); + + if (!user) { + return res.status(401).json({ message: "유효하지 않은 토큰입니다." }); + } + + const accessToken = generateAccessToken(user); + + res.json({ accessToken }); + } catch (error) { + return res.status(401).json({ message: "유효하지 않은 토큰입니다." }); + } + }) +); + +export default router; diff --git a/structs.js b/structs.js index 74e0e00..0b2d149 100644 --- a/structs.js +++ b/structs.js @@ -1,20 +1,20 @@ +import isEmail from "is-email"; import * as s from "superstruct"; - const PositivePrice = s.refine(s.number(), "PositivePrice", (value) => value > 0 && value < 1000000000); export const CreateProduct = s.object({ ownerId: s.number(), images: s.array(s.string()), - tags: s.array(s.string()), + tags: s.array(s.size(s.string(), 1, 32)), price: PositivePrice, description: s.string(), - name: s.string(), + name: s.size(s.string(), 1, 60), }); export const PatchProduct = s.partial(CreateProduct); export const CreateArticle = s.object({ - title: s.string(), + title: s.size(s.string(), 1, 60), content: s.string(), imageUrl: s.optional(s.string()), writer: s.optional(s.string()), @@ -28,3 +28,10 @@ export const CreateComment = s.object({ }); export const PatchComment = s.partial(CreateComment); + +export const CreateUser = s.object({ + email: s.define("Email", isEmail), + password: s.size(s.string(), 1, 32), + name: s.size(s.string(), 1, 16), + nickname: s.size(s.string(), 1, 16), +}); diff --git a/utils/tokens.js b/utils/tokens.js new file mode 100644 index 0000000..a916fe3 --- /dev/null +++ b/utils/tokens.js @@ -0,0 +1,14 @@ +import dotenv from "dotenv"; +import jwt from "jsonwebtoken"; + +dotenv.config(); + +const { JWT_SECRET, JWT_ACCESS_EXPIRES_IN, JWT_REFRESH_EXPIRES_IN } = process.env; + +export const generateAccessToken = (user) => { + return jwt.sign({ userId: user.id }, JWT_SECRET, { expiresIn: JWT_ACCESS_EXPIRES_IN }); +}; + +export const generateRefreshToken = (user) => { + return jwt.sign({ userId: user.id }, JWT_SECRET, { expiresIn: JWT_REFRESH_EXPIRES_IN }); +}; From 6fb96d5529dbdc79bccf1480404b1f692a5c63ae Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Mon, 27 May 2024 16:09:45 +0900 Subject: [PATCH 25/60] =?UTF-8?q?[#M10]=20feat=20:=20=EB=9D=BC=EC=9A=B0?= =?UTF-8?q?=ED=8A=B8=20=EA=B2=BD=EB=A1=9C=20=ED=86=B5=ED=95=A9,=20API?= =?UTF-8?q?=EC=97=90=20=EC=9D=B8=EA=B0=80=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- http/auth.http | 4 +- http/products.http | 8 + middlewares/authenticate.js | 1 + routes/articles.js | 377 ++++++++++++++++++------------------ routes/images.js | 4 +- routes/products.js | 343 ++++++++++++++++---------------- 6 files changed, 366 insertions(+), 371 deletions(-) diff --git a/http/auth.http b/http/auth.http index da4cb67..e60573d 100644 --- a/http/auth.http +++ b/http/auth.http @@ -2,7 +2,7 @@ POST http://localhost:3000/auth/signUp Content-Type: application/json { - "email":"test4@gmail.com", + "email":"test5@gmail.com", "password":"pandapower", "name":"김판다", "nickname":"판다의 왕" @@ -15,7 +15,7 @@ POST http://localhost:3000/auth/signIn Content-Type: application/json { - "email":"test4@gmail.com", + "email":"test5@gmail.com", "password":"pandapower" } diff --git a/http/products.http b/http/products.http index 1126069..3c7b86a 100644 --- a/http/products.http +++ b/http/products.http @@ -18,6 +18,7 @@ GET http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 ### # 상품 등록 POST http://localhost:3000/products +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE Content-Type: application/json { @@ -32,6 +33,7 @@ Content-Type: application/json ### # 상품 수정 PATCH http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE Content-Type: application/json { @@ -44,14 +46,17 @@ Content-Type: application/json ### # 상품 삭제 DELETE http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE ### # 상품 좋아요 PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/like +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE ### # 상품 좋아요 취소 PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/unlike +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE ### # 상품 댓글 조회 @@ -64,6 +69,7 @@ GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments ### # 상품 댓글 등록 POST http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE Content-Type: application/json { @@ -74,6 +80,7 @@ Content-Type: application/json ### # 상품 댓글 수정 PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/4db38f1c-53c5-40c4-98ce-bcaa0ba7904d +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE Content-Type: application/json { @@ -82,4 +89,5 @@ Content-Type: application/json ### # 상품 댓글 삭제 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE DELETE http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/4db38f1c-53c5-40c4-98ce-bcaa0ba7904d \ No newline at end of file diff --git a/middlewares/authenticate.js b/middlewares/authenticate.js index f891647..739b741 100644 --- a/middlewares/authenticate.js +++ b/middlewares/authenticate.js @@ -10,6 +10,7 @@ const authenticate = (req, res, next) => { if (!authHeader) { return res.status(401).json({ message: "No token provided" }); } + console.log(authHeader); const token = authHeader.split(" ")[1]; diff --git a/routes/articles.js b/routes/articles.js index ae32411..c42ced9 100644 --- a/routes/articles.js +++ b/routes/articles.js @@ -1,134 +1,130 @@ import { PrismaClient } from "@prisma/client"; import express from "express"; import { assert } from "superstruct"; +import authenticate from "../middlewares/authenticate.js"; import { CreateArticle, CreateComment, PatchArticle, PatchComment } from "../structs.js"; import asyncHandler from "../utils/asyncHandler.js"; const prisma = new PrismaClient(); const router = express.Router(); -// 게시글 목록 조회 -router.get( - "/", - asyncHandler(async (req, res) => { - /** - * 쿼리 파라미터 - * - offset : 가져올 데이터의 시작 지점 - * - limit : 한 번에 가져올 데이터의 개수 - * - orderBy : 정렬 기준 like, recent (기본값: recent) - */ - const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; - const order = orderBy === "like" ? { likeCount: "desc" } : { createdAt: "desc" }; - const articles = await prisma.article.findMany({ - select: { - id: true, - title: true, - content: true, - imageUrl: true, - createdAt: true, - writer: true, - }, - orderBy: order, - skip: parseInt(offset), - take: parseInt(limit), - where: { - OR: [ - { - title: { - contains: keyword, - mode: "insensitive", + +router + .route("/") + .get( + asyncHandler(async (req, res) => { + /** + * 쿼리 파라미터 + * - offset : 가져올 데이터의 시작 지점 + * - limit : 한 번에 가져올 데이터의 개수 + * - orderBy : 정렬 기준 like, recent (기본값: recent) + */ + const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; + const order = orderBy === "like" ? { likeCount: "desc" } : { createdAt: "desc" }; + const articles = await prisma.article.findMany({ + select: { + id: true, + title: true, + content: true, + imageUrl: true, + createdAt: true, + writer: true, + }, + orderBy: order, + skip: parseInt(offset), + take: parseInt(limit), + where: { + OR: [ + { + title: { + contains: keyword, + mode: "insensitive", + }, }, - }, - { - content: { - contains: keyword, - mode: "insensitive", + { + content: { + contains: keyword, + mode: "insensitive", + }, }, - }, - ], - }, - }); - // 좋아요가 많은 상위 4개의 글 조회 - const bestArticles = await prisma.article.findMany({ - orderBy: { - likeCount: "desc", - }, - take: 4, - }); - - res.send({ articles, bestArticles }); - }) -); - -// 게시글 상세 조회 -router.get( - "/:id", - asyncHandler(async (req, res) => { - const { id } = req.params; - const article = await prisma.article.findUniqueOrThrow({ - where: { - id, - }, - select: { - id: true, - title: true, - content: true, - imageUrl: true, - createdAt: true, - likeCount: true, - writer: true, - }, - }); - res.send(article); - }) -); - -// 게시글 등록 -router.post( - "/", - asyncHandler(async (req, res) => { - assert(req.body, CreateArticle); - const article = await prisma.article.create({ - data: req.body, - }); - res.status(201).send(article); - }) -); + ], + }, + }); + // 좋아요가 많은 상위 4개의 글 조회 + const bestArticles = await prisma.article.findMany({ + orderBy: { + likeCount: "desc", + }, + take: 4, + }); -// 게시글 수정 -router.patch( - "/:id", - asyncHandler(async (req, res) => { - assert(req.body, PatchArticle); - const { id } = req.params; - const article = await prisma.article.update({ - where: { - id, - }, - data: req.body, - }); + res.send({ articles, bestArticles }); + }) + ) + .post( + authenticate, + asyncHandler(async (req, res) => { + assert(req.body, CreateArticle); + const article = await prisma.article.create({ + data: req.body, + }); + res.status(201).send(article); + }) + ); - res.send(article); - }) -); +router + .route("/:id") + .get( + asyncHandler(async (req, res) => { + const { id } = req.params; + const article = await prisma.article.findUniqueOrThrow({ + where: { + id, + }, + select: { + id: true, + title: true, + content: true, + imageUrl: true, + createdAt: true, + likeCount: true, + writer: true, + }, + }); + res.send(article); + }) + ) + .patch( + authenticate, + asyncHandler(async (req, res) => { + assert(req.body, PatchArticle); + const { id } = req.params; + const article = await prisma.article.update({ + where: { + id, + }, + data: req.body, + }); -// 게시글 삭제 -router.delete( - "/:id", - asyncHandler(async (req, res) => { - const { id } = req.params; - await prisma.article.delete({ - where: { - id, - }, - }); + res.send(article); + }) + ) + .delete( + authenticate, + asyncHandler(async (req, res) => { + const { id } = req.params; + await prisma.article.delete({ + where: { + id, + }, + }); - res.sendStatus(204); - }) -); + res.sendStatus(204); + }) + ); -// 게시글 좋아요 router.patch( "/:id/like", + authenticate, asyncHandler(async (req, res) => { const article = await prisma.article.findUniqueOrThrow({ where: { @@ -166,9 +162,9 @@ router.patch( }) ); -// 게시글 좋아요 취소 router.patch( "/:id/unlike", + authenticate, asyncHandler(async (req, res) => { const article = await prisma.article.findUniqueOrThrow({ where: { @@ -206,90 +202,87 @@ router.patch( }) ); -// 자유게시판 댓글 목록 조회 -router.get( - "/:id/comments", - asyncHandler(async (req, res) => { - const { id } = req.params; - const { cursor } = req.query; - let queryOptions = { - take: 10, - orderBy: { - createdAt: "desc", - }, - where: { - articleId: id, - }, - select: { - id: true, - content: true, - createdAt: true, - writer: true, - }, - }; - - if (cursor) { - queryOptions = { - ...queryOptions, - cursor: { - id: cursor, +router + .route("/:id/comments") + .get( + asyncHandler(async (req, res) => { + const { id } = req.params; + const { cursor } = req.query; + let queryOptions = { + take: 10, + orderBy: { + createdAt: "desc", + }, + where: { + articleId: id, + }, + select: { + id: true, + content: true, + createdAt: true, + writer: true, }, - skip: 1, }; - } - const comments = await prisma.comment.findMany(queryOptions); - res.send(comments); - }) -); + if (cursor) { + queryOptions = { + ...queryOptions, + cursor: { + id: cursor, + }, + skip: 1, + }; + } -// 자유게시판 댓글 등록 -router.post( - "/:id/comments", - asyncHandler(async (req, res) => { - assert(req.body, CreateComment); - const { id } = req.params; + const comments = await prisma.comment.findMany(queryOptions); + res.send(comments); + }) + ) + .post( + authenticate, + asyncHandler(async (req, res) => { + assert(req.body, CreateComment); + const { id } = req.params; - const comment = await prisma.comment.create({ - data: { - ...req.body, - articleId: id, - }, - }); - res.status(201).send(comment); - }) -); - -// 자유게시판 댓글 수정 -router.patch( - "/:id/comments/:commentId", - asyncHandler(async (req, res) => { - assert(req.body, PatchComment); - const { commentId } = req.params; - const comment = await prisma.comment.update({ - where: { - id: commentId, - }, - data: req.body, - }); + const comment = await prisma.comment.create({ + data: { + ...req.body, + articleId: id, + }, + }); + res.status(201).send(comment); + }) + ); - res.send(comment); - }) -); +router + .route("/:id/comments/:commentId") + .patch( + authenticate, + asyncHandler(async (req, res) => { + assert(req.body, PatchComment); + const { commentId } = req.params; + const comment = await prisma.comment.update({ + where: { + id: commentId, + }, + data: req.body, + }); -// 중고마켓 댓글 삭제 -router.delete( - "/:id/comments/:commentId", - asyncHandler(async (req, res) => { - const { commentId } = req.params; - await prisma.comment.delete({ - where: { - id: commentId, - }, - }); + res.send(comment); + }) + ) + .delete( + authenticate, + asyncHandler(async (req, res) => { + const { commentId } = req.params; + await prisma.comment.delete({ + where: { + id: commentId, + }, + }); - res.sendStatus(204); - }) -); + res.sendStatus(204); + }) + ); export default router; diff --git a/routes/images.js b/routes/images.js index 8b0876c..33dbcae 100644 --- a/routes/images.js +++ b/routes/images.js @@ -2,7 +2,7 @@ import { PrismaClient } from "@prisma/client"; import express from "express"; import multer from "multer"; import path from "path"; - +import authenticate from "../middlewares/authenticate.js"; const prisma = new PrismaClient(); const SERVER_URL = "http://localhost:3000"; @@ -21,7 +21,7 @@ const storage = multer.diskStorage({ const upload = multer({ storage: storage }); // 이미지 업로드 -router.post("/upload", upload.single("image"), async (req, res) => { +router.post("/upload", authenticate, upload.single("image"), async (req, res) => { const file = req.file; console.log(req); if (!file) { diff --git a/routes/products.js b/routes/products.js index 2bea203..3f234c4 100644 --- a/routes/products.js +++ b/routes/products.js @@ -1,109 +1,105 @@ import { PrismaClient } from "@prisma/client"; import express from "express"; import { assert } from "superstruct"; +import authenticate from "../middlewares/authenticate.js"; import { CreateComment, CreateProduct, PatchComment, PatchProduct } from "../structs.js"; import asyncHandler from "../utils/asyncHandler.js"; const prisma = new PrismaClient(); -const router = express.Router(); // 상품 목록 조회 -router.get( - "/", - asyncHandler(async (req, res) => { - /** - * 쿼리 파라미터 - * - offset : 가져올 데이터의 시작 지점 - * - limit : 한 번에 가져올 데이터의 개수 - * - orderBy : 정렬 기준 favorite, recent (기본값: recent) - * - keyword : 검색 키워드 - */ - const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; - const order = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; - const products = await prisma.product.findMany({ - orderBy: order, - skip: parseInt(offset), - take: parseInt(limit), - where: { - OR: [ - { - name: { - contains: keyword, - mode: "insensitive", +const router = express.Router(); +router + .route("/") + .get( + asyncHandler(async (req, res) => { + /** + * 쿼리 파라미터 + * - offset : 가져올 데이터의 시작 지점 + * - limit : 한 번에 가져올 데이터의 개수 + * - orderBy : 정렬 기준 favorite, recent (기본값: recent) + * - keyword : 검색 키워드 + */ + const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; + const order = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; + const products = await prisma.product.findMany({ + orderBy: order, + skip: parseInt(offset), + take: parseInt(limit), + where: { + OR: [ + { + name: { + contains: keyword, + mode: "insensitive", + }, }, - }, - { - description: { - contains: keyword, - mode: "insensitive", + { + description: { + contains: keyword, + mode: "insensitive", + }, }, - }, - ], - }, - }); - res.send(products); - }) -); - -// 상품 상세 조회 -router.get( - "/:id", - asyncHandler(async (req, res) => { - const { id } = req.params; - const product = await prisma.product.findUniqueOrThrow({ - where: { - id, - }, - }); - res.send(product); - }) -); - -// 상품 등록 -router.post( - "/", - asyncHandler(async (req, res) => { - assert(req.body, CreateProduct); - const product = await prisma.product.create({ - data: req.body, - }); - res.status(201).send(product); - }) -); - -// 상품 수정 -router.patch( - "/:id", - asyncHandler(async (req, res) => { - assert(req.body, PatchProduct); - const { id } = req.params; - const product = await prisma.product.update({ - where: { - id, - }, - data: req.body, - }); - - res.send(product); - }) -); - -// 상품 삭제 -router.delete( - "/:id", - asyncHandler(async (req, res) => { - const { id } = req.params; - await prisma.product.delete({ - where: { - id, - }, - }); + ], + }, + }); + res.send(products); + }) + ) + .post( + authenticate, + asyncHandler(async (req, res) => { + assert(req.body, CreateProduct); + const product = await prisma.product.create({ + data: req.body, + }); + res.status(201).send(product); + }) + ); + +router + .route("/:id") + .get( + asyncHandler(async (req, res) => { + const { id } = req.params; + const product = await prisma.product.findUniqueOrThrow({ + where: { + id, + }, + }); + res.send(product); + }) + ) + .patch( + authenticate, + asyncHandler(async (req, res) => { + assert(req.body, PatchProduct); + const { id } = req.params; + const product = await prisma.product.update({ + where: { + id, + }, + data: req.body, + }); + + res.send(product); + }) + ) + .delete( + authenticate, + asyncHandler(async (req, res) => { + const { id } = req.params; + await prisma.product.delete({ + where: { + id, + }, + }); - res.sendStatus(204); - }) -); + res.sendStatus(204); + }) + ); -// 상품 좋아요 router.patch( "/:id/like", + authenticate, asyncHandler(async (req, res) => { const product = await prisma.product.findUniqueOrThrow({ where: { @@ -132,9 +128,9 @@ router.patch( }) ); -// 상품 좋아요 취소 router.patch( "/:id/unlike", + authenticate, asyncHandler(async (req, res) => { const product = await prisma.product.findUniqueOrThrow({ where: { @@ -163,90 +159,87 @@ router.patch( }) ); -// 중고마켓 댓글 목록 조회 -router.get( - "/:id/comments", - asyncHandler(async (req, res) => { - const { id } = req.params; - const { cursor } = req.query; - let queryOptions = { - take: 10, - orderBy: { - createdAt: "desc", - }, - where: { - productId: id, - }, - select: { - id: true, - content: true, - createdAt: true, - writer: true, - }, - }; - - if (cursor) { - queryOptions = { - ...queryOptions, - cursor: { - id: cursor, +router + .route("/:id/comments") + .get( + asyncHandler(async (req, res) => { + const { id } = req.params; + const { cursor } = req.query; + let queryOptions = { + take: 10, + orderBy: { + createdAt: "desc", + }, + where: { + productId: id, + }, + select: { + id: true, + content: true, + createdAt: true, + writer: true, }, - skip: 1, }; - } - - const comments = await prisma.comment.findMany(queryOptions); - res.send(comments); - }) -); - -// 중고마켓 댓글 등록 -router.post( - "/:id/comments", - asyncHandler(async (req, res) => { - assert(req.body, CreateComment); - const { id } = req.params; - - const comment = await prisma.comment.create({ - data: { - ...req.body, - productId: id, - }, - }); - res.status(201).send(comment); - }) -); - -// 중고마켓 댓글 수정 -router.patch( - "/:id/comments/:commentId", - asyncHandler(async (req, res) => { - assert(req.body, PatchComment); - const { commentId } = req.params; - const comment = await prisma.comment.update({ - where: { - id: commentId, - }, - data: req.body, - }); - - res.send(comment); - }) -); -// 중고마켓 댓글 삭제 -router.delete( - "/:id/comments/:commentId", - asyncHandler(async (req, res) => { - const { commentId } = req.params; - await prisma.comment.delete({ - where: { - id: commentId, - }, - }); + if (cursor) { + queryOptions = { + ...queryOptions, + cursor: { + id: cursor, + }, + skip: 1, + }; + } + + const comments = await prisma.comment.findMany(queryOptions); + res.send(comments); + }) + ) + .post( + authenticate, + asyncHandler(async (req, res) => { + assert(req.body, CreateComment); + const { id } = req.params; + + const comment = await prisma.comment.create({ + data: { + ...req.body, + productId: id, + }, + }); + res.status(201).send(comment); + }) + ); + +router + .route("/:id/comments/:commentId") + .patch( + authenticate, + asyncHandler(async (req, res) => { + assert(req.body, PatchComment); + const { commentId } = req.params; + const comment = await prisma.comment.update({ + where: { + id: commentId, + }, + data: req.body, + }); + + res.send(comment); + }) + ) + .delete( + authenticate, + asyncHandler(async (req, res) => { + const { commentId } = req.params; + await prisma.comment.delete({ + where: { + id: commentId, + }, + }); - res.sendStatus(204); - }) -); + res.sendStatus(204); + }) + ); export default router; From 3a16ac9983bd66eec7fbb4bef1fe273359c3093a Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Mon, 27 May 2024 16:13:20 +0900 Subject: [PATCH 26/60] =?UTF-8?q?[#M10]=20feat=20:=20jwt=20sliding=20sessi?= =?UTF-8?q?on=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- http/auth.http | 2 +- routes/auth.js | 8 ++++---- utils/tokens.js | 9 +++++++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/http/auth.http b/http/auth.http index e60573d..c5339ae 100644 --- a/http/auth.http +++ b/http/auth.http @@ -25,5 +25,5 @@ POST http://localhost:3000/auth/refresh-token Content-Type: application/json { - "refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjcsImlhdCI6MTcxNjc5MTY3NiwiZXhwIjoxNzE3Mzk2NDc2fQ.wcGjW1SsWm7OKELCcKI-1aA9rmxt1FxmE9SYAJJjgwc" + "refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5Mzk0NywiZXhwIjoxNzE3Mzk4NzQ3fQ.bBxra1mgW2Pe4s9KcD_8Z5QmuFAIqZhjwKEupNpkXbs" } \ No newline at end of file diff --git a/routes/auth.js b/routes/auth.js index 5e7eee3..6152f5f 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -6,7 +6,7 @@ import jwt from "jsonwebtoken"; import { assert } from "superstruct"; import { CreateUser } from "../structs.js"; import asyncHandler from "../utils/asyncHandler.js"; -import { generateAccessToken, generateRefreshToken } from "../utils/tokens.js"; +import { generateAccessToken, generateRefreshToken, regenerateRefreshToken } from "../utils/tokens.js"; dotenv.config(); const router = express.Router(); @@ -67,7 +67,6 @@ router.post( res.json({ accessToken, refreshToken }); }) ); - router.post( "/refresh-token", asyncHandler(async (req, res) => { @@ -78,7 +77,8 @@ router.post( } try { - const decoded = jwt.verify(refreshToken, JWT_SECRET); + const newRefreshToken = regenerateRefreshToken(refreshToken); + const decoded = jwt.verify(newRefreshToken, JWT_SECRET); const user = await prisma.user.findUnique({ where: { id: decoded.userId } }); if (!user) { @@ -87,7 +87,7 @@ router.post( const accessToken = generateAccessToken(user); - res.json({ accessToken }); + res.json({ accessToken, refreshToken: newRefreshToken }); } catch (error) { return res.status(401).json({ message: "유효하지 않은 토큰입니다." }); } diff --git a/utils/tokens.js b/utils/tokens.js index a916fe3..12d5d2e 100644 --- a/utils/tokens.js +++ b/utils/tokens.js @@ -12,3 +12,12 @@ export const generateAccessToken = (user) => { export const generateRefreshToken = (user) => { return jwt.sign({ userId: user.id }, JWT_SECRET, { expiresIn: JWT_REFRESH_EXPIRES_IN }); }; + +export const regenerateRefreshToken = (refreshToken) => { + try { + const decoded = jwt.verify(refreshToken, JWT_SECRET); + return jwt.sign({ userId: decoded.userId }, JWT_SECRET, { expiresIn: "7d" }); + } catch (error) { + throw new Error("Invalid refresh token"); + } +}; From 98e2a967465b2943132a46943f6b4a6ec5442452 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Mon, 27 May 2024 16:39:23 +0900 Subject: [PATCH 27/60] =?UTF-8?q?[#M10]=20fix=20:=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=A2=8B=EC=95=84=EC=9A=94,=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=B7=A8=EC=86=8C=EC=8B=9C=20=EC=9C=A0=EC=A0=80=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - mock, seed 데이터 수정 --- http/products.http | 4 +- middlewares/authenticate.js | 1 - .../migration.sql | 15 ++++++ .../migration.sql | 18 +++++++ prisma/mock.js | 24 ++++++++- prisma/schema.prisma | 8 +-- prisma/seed.js | 16 +++++- routes/products.js | 54 +++++++++++++++---- 8 files changed, 120 insertions(+), 20 deletions(-) create mode 100644 prisma/migrations/20240527072552_change_favorite_model/migration.sql create mode 100644 prisma/migrations/20240527074901_rename_owner_id_to_user_id/migration.sql diff --git a/http/products.http b/http/products.http index 3c7b86a..e0afdbf 100644 --- a/http/products.http +++ b/http/products.http @@ -51,12 +51,12 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhd ### # 상품 좋아요 PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/like -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5NDc3MCwiZXhwIjoxNzE2Nzk1NjcwfQ.4jHyaxo0BgeSCSfTGAwnTlMLyRZGEJPoEOqUe-Xdo9w ### # 상품 좋아요 취소 PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/unlike -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5NDc3MCwiZXhwIjoxNzE2Nzk1NjcwfQ.4jHyaxo0BgeSCSfTGAwnTlMLyRZGEJPoEOqUe-Xdo9w ### # 상품 댓글 조회 diff --git a/middlewares/authenticate.js b/middlewares/authenticate.js index 739b741..f891647 100644 --- a/middlewares/authenticate.js +++ b/middlewares/authenticate.js @@ -10,7 +10,6 @@ const authenticate = (req, res, next) => { if (!authHeader) { return res.status(401).json({ message: "No token provided" }); } - console.log(authHeader); const token = authHeader.split(" ")[1]; diff --git a/prisma/migrations/20240527072552_change_favorite_model/migration.sql b/prisma/migrations/20240527072552_change_favorite_model/migration.sql new file mode 100644 index 0000000..171efba --- /dev/null +++ b/prisma/migrations/20240527072552_change_favorite_model/migration.sql @@ -0,0 +1,15 @@ +/* + Warnings: + + - A unique constraint covering the columns `[userId,productId]` on the table `Favorite` will be added. If there are existing duplicate values, this will fail. + - A unique constraint covering the columns `[userId,articleId]` on the table `Favorite` will be added. If there are existing duplicate values, this will fail. + +*/ +-- DropIndex +DROP INDEX "Favorite_userId_productId_articleId_key"; + +-- CreateIndex +CREATE UNIQUE INDEX "Favorite_userId_productId_key" ON "Favorite"("userId", "productId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Favorite_userId_articleId_key" ON "Favorite"("userId", "articleId"); diff --git a/prisma/migrations/20240527074901_rename_owner_id_to_user_id/migration.sql b/prisma/migrations/20240527074901_rename_owner_id_to_user_id/migration.sql new file mode 100644 index 0000000..b019051 --- /dev/null +++ b/prisma/migrations/20240527074901_rename_owner_id_to_user_id/migration.sql @@ -0,0 +1,18 @@ +/* + Warnings: + + - The primary key for the `Favorite` table will be changed. If it partially fails, the table could be left without primary key constraint. + - You are about to drop the column `ownerId` on the `Product` table. All the data in the column will be lost. + - You are about to alter the column `price` on the `Product` table. The data in that column could be lost. The data in that column will be cast from `DoublePrecision` to `Integer`. + +*/ +-- AlterTable +ALTER TABLE "Favorite" DROP CONSTRAINT "Favorite_pkey", +ALTER COLUMN "id" DROP DEFAULT, +ALTER COLUMN "id" SET DATA TYPE TEXT, +ADD CONSTRAINT "Favorite_pkey" PRIMARY KEY ("id"); +DROP SEQUENCE "Favorite_id_seq"; + +-- AlterTable +ALTER TABLE "Product" DROP COLUMN "ownerId", +ALTER COLUMN "price" SET DATA TYPE INTEGER; diff --git a/prisma/mock.js b/prisma/mock.js index a68eed2..5cf4342 100644 --- a/prisma/mock.js +++ b/prisma/mock.js @@ -2,17 +2,16 @@ export const PRODUCTS = [ { id: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", favoriteCount: 7, - ownerId: 1, images: ["https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg"], tags: ["판다인형", "인형", "판다"], price: 700000, description: "판다인형 판다", name: "판다인형", + userId: 1, }, { id: "d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9", favoriteCount: 2, - ownerId: 2, images: [ "https://view01.wemep.co.kr/wmp-product/4/879/2515748794/pm_ebifv5nrjsyf.jpg?1683280710&f=webp&w=460&h=460", ], @@ -20,6 +19,7 @@ export const PRODUCTS = [ price: 7000, description: "판다인형 안판다", name: "판다인형 안파는 판다", + userId: 1, }, ]; @@ -141,3 +141,23 @@ export const COMMENTS = [ articleId: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", }, ]; + +export const USERS = [ + { + id: 1, + email: "test@gmail.com", + name: "김판다", + nickname: "판다의 왕", + password: "$2b$10$cq6uUbVgrWG9UG6Gpu/k3un1aTLE8XzMfAyU2NhS2FIY93M.CFXqO", + createdAt: new Date(), + updatedAt: new Date(), + }, +]; + +export const FAVORITE = [ + { + id: "1a2b3c4d-5e6f-7g8h-9i0j-1k2l3m4n5o6p", + userId: 1, + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, +]; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index dae5e66..b1d6c8f 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -30,11 +30,10 @@ model Product { id String @id @default(uuid()) name String description String - price Float + price Int tags String[] images String[] favoriteCount Int @default(0) - ownerId Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt comments Comment[] @@ -90,7 +89,7 @@ model Image { } model Favorite { - id Int @id @default(autoincrement()) + id String @id @default(uuid()) createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id], onDelete: Cascade) userId Int @@ -99,5 +98,6 @@ model Favorite { article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) articleId String? - @@unique([userId, productId, articleId]) + @@unique([userId, productId]) + @@unique([userId, articleId]) } diff --git a/prisma/seed.js b/prisma/seed.js index 92f7f42..7e067cf 100644 --- a/prisma/seed.js +++ b/prisma/seed.js @@ -1,8 +1,14 @@ import { PrismaClient } from "@prisma/client"; -import { ARTICLES, COMMENTS, PRODUCTS } from "./mock.js"; +import { ARTICLES, COMMENTS, FAVORITE, PRODUCTS, USERS } from "./mock.js"; const prisma = new PrismaClient(); async function main() { + await prisma.user.deleteMany(); + + await prisma.user.createMany({ + data: USERS, + skipDuplicates: true, + }); await prisma.product.deleteMany(); await prisma.product.createMany({ @@ -16,6 +22,14 @@ async function main() { data: ARTICLES, skipDuplicates: true, }); + + await prisma.favorite.deleteMany(); + + await prisma.favorite.createMany({ + data: FAVORITE, + skipDuplicates: true, + }); + await prisma.comment.deleteMany(); await prisma.comment.createMany({ diff --git a/routes/products.js b/routes/products.js index 3f234c4..035a71a 100644 --- a/routes/products.js +++ b/routes/products.js @@ -101,26 +101,43 @@ router.patch( "/:id/like", authenticate, asyncHandler(async (req, res) => { + const { id: productId } = req.params; + const { userId } = req; const product = await prisma.product.findUniqueOrThrow({ where: { - id: req.params.id, + id: productId, }, }); - if (product.isFavorite) { + const favorite = await prisma.favorite.findUnique({ + where: { + userId_productId: { + userId, + productId, + }, + }, + }); + + if (favorite) { res.status(400).send({ message: "이미 좋아요 처리된 상품입니다." }); return; } + await prisma.favorite.create({ + data: { + userId, + productId, + }, + }); + const updatedProduct = await prisma.product.update({ where: { - id: req.params.id, + id: productId, }, data: { favoriteCount: { increment: 1, }, - isFavorite: true, }, }); @@ -132,26 +149,43 @@ router.patch( "/:id/unlike", authenticate, asyncHandler(async (req, res) => { + const { id: productId } = req.params; + const { userId } = req; const product = await prisma.product.findUniqueOrThrow({ where: { - id: req.params.id, + id: productId, }, }); - if (!product.isFavorite) { - res.status(400).send({ message: "아직 좋아요 처리되지 않은 상품입니다." }); - return; + const favorite = await prisma.favorite.findUnique({ + where: { + userId_productId: { + userId, + productId, + }, + }, + }); + + if (!favorite) { + return res.status(400).send({ message: "아직 좋아요 처리되지 않은 상품입니다." }); } + await prisma.favorite.delete({ + where: { + userId_productId: { + userId, + productId, + }, + }, + }); const updatedProduct = await prisma.product.update({ where: { - id: req.params.id, + id: productId, }, data: { favoriteCount: { decrement: 1, }, - isFavorite: false, }, }); From 94a985538c060c2fd63b8620e903ca68c17cc29e Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Mon, 27 May 2024 16:54:12 +0900 Subject: [PATCH 28/60] =?UTF-8?q?[#M10]=20fix=20:=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EC=8B=9C=20=EC=9D=B8=EA=B0=80=20=EB=90=9C?= =?UTF-8?q?=20userId=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- http/products.http | 5 ++--- routes/products.js | 3 ++- structs.js | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/http/products.http b/http/products.http index e0afdbf..79fd882 100644 --- a/http/products.http +++ b/http/products.http @@ -18,7 +18,7 @@ GET http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 ### # 상품 등록 POST http://localhost:3000/products -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjc5NjIzMiwiZXhwIjoxNzE2Nzk3MTMyfQ.h5Jq-cMim3LixOqibNgMh3yAr0m03ajCXaxBUb25v3M Content-Type: application/json { @@ -26,8 +26,7 @@ Content-Type: application/json "description": "세종시청에서 교환원합니다.", "price": 20000, "tags": ["판다", "불곰"], - "images": ["https://www.wishbucket.io/_next/image?url=https%3A%2F%2Fd2gfz7wkiigkmv.cloudfront.net%2Fpickin%2F2%2F1%2F2%2FHereyhSJRMOmUw7I5uWAxg&w=640&q=75","https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg"], - "ownerId":1 + "images": ["https://www.wishbucket.io/_next/image?url=https%3A%2F%2Fd2gfz7wkiigkmv.cloudfront.net%2Fpickin%2F2%2F1%2F2%2FHereyhSJRMOmUw7I5uWAxg&w=640&q=75","https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg"] } ### diff --git a/routes/products.js b/routes/products.js index 035a71a..b809c28 100644 --- a/routes/products.js +++ b/routes/products.js @@ -48,8 +48,9 @@ router authenticate, asyncHandler(async (req, res) => { assert(req.body, CreateProduct); + const { userId } = req; const product = await prisma.product.create({ - data: req.body, + data: { ...req.body, userId }, }); res.status(201).send(product); }) diff --git a/structs.js b/structs.js index 0b2d149..a92e0c9 100644 --- a/structs.js +++ b/structs.js @@ -3,7 +3,6 @@ import * as s from "superstruct"; const PositivePrice = s.refine(s.number(), "PositivePrice", (value) => value > 0 && value < 1000000000); export const CreateProduct = s.object({ - ownerId: s.number(), images: s.array(s.string()), tags: s.array(s.size(s.string(), 1, 32)), price: PositivePrice, From 00ab5514915ea42b1fa235ee9aa9692314eddbc8 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Tue, 28 May 2024 11:49:23 +0900 Subject: [PATCH 29/60] =?UTF-8?q?[#M10]=20feat=20:=20morgan=EC=9D=84=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EC=97=AC=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=EC=9D=98=20=EC=83=81=EC=84=B8=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A5=BC=20=EB=A1=9C=EA=B7=B8=EB=A1=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 20 +++++++++++ package-lock.json | 84 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 ++ 3 files changed, 106 insertions(+) diff --git a/app.js b/app.js index e8f8057..7a94b64 100644 --- a/app.js +++ b/app.js @@ -1,10 +1,30 @@ import express from "express"; +import fs from "fs"; +import moment from "moment-timezone"; +import morgan from "morgan"; +import path, { dirname } from "path"; +import { fileURLToPath } from "url"; import articlesRouter from "./routes/articles.js"; import authRouter from "./routes/auth.js"; import imagesRouter from "./routes/images.js"; import productsRouter from "./routes/products.js"; +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + const app = express(); + +morgan.token("date", (req, res, tz) => { + return moment().tz(tz).format("YYYY-MM-DD HH:mm:ss"); +}); +// 커스텀 포맷 설정: 한국 시간대의 현재 시간을 포함 +const customFormat = ":method :url :status :res[content-length] - :response-time ms - :date[Asia/Seoul]"; + +// 로그 파일 스트림 생성 +const accessLogStream = fs.createWriteStream(path.join(__dirname, "access.log"), { flags: "a" }); + +// morgan 미들웨어 설정 (로그 파일에 기록) +app.use(morgan(customFormat, { stream: accessLogStream })); app.use(express.json()); app.use(express.urlencoded({ extended: true })); diff --git a/package-lock.json b/package-lock.json index 9d0d87d..09bccb8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,8 @@ "is-email": "^1.0.2", "is-uuid": "^1.0.2", "jsonwebtoken": "^9.0.2", + "moment-timezone": "^0.5.45", + "morgan": "^1.10.0", "multer": "^1.4.5-lts.1", "prisma": "^5.4.2", "superstruct": "^1.0.3" @@ -191,6 +193,22 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/bcrypt": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", @@ -1198,6 +1216,64 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -1342,6 +1418,14 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", diff --git a/package.json b/package.json index 3ffcaec..87a3db6 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,8 @@ "is-email": "^1.0.2", "is-uuid": "^1.0.2", "jsonwebtoken": "^9.0.2", + "moment-timezone": "^0.5.45", + "morgan": "^1.10.0", "multer": "^1.4.5-lts.1", "prisma": "^5.4.2", "superstruct": "^1.0.3" From 2f4ae013febe56c9fe1bc14b19c70ca90e91952d Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Tue, 28 May 2024 12:29:00 +0900 Subject: [PATCH 30/60] =?UTF-8?q?[#M10]=20fix=20:=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20API=EB=93=A4=EC=9D=B4=20userId=EB=A5=BC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 상품 수정, 삭제 - 상품 댓글 등록, 수정, 삭제 --- http/auth.http | 2 +- http/products.http | 20 ++--- .../migration.sql | 11 +++ prisma/mock.js | 49 ++++++++++-- prisma/schema.prisma | 3 + routes/products.js | 76 +++++++++++++------ 6 files changed, 118 insertions(+), 43 deletions(-) create mode 100644 prisma/migrations/20240528031512_add_user_id_to_comment/migration.sql diff --git a/http/auth.http b/http/auth.http index c5339ae..4868f2e 100644 --- a/http/auth.http +++ b/http/auth.http @@ -15,7 +15,7 @@ POST http://localhost:3000/auth/signIn Content-Type: application/json { - "email":"test5@gmail.com", + "email":"test2@gmail.com", "password":"pandapower" } diff --git a/http/products.http b/http/products.http index 79fd882..315fe1a 100644 --- a/http/products.http +++ b/http/products.http @@ -18,7 +18,7 @@ GET http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 ### # 상품 등록 POST http://localhost:3000/products -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjc5NjIzMiwiZXhwIjoxNzE2Nzk3MTMyfQ.h5Jq-cMim3LixOqibNgMh3yAr0m03ajCXaxBUb25v3M +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NTcxNywiZXhwIjoxNzE2ODY2NjE3fQ.1zbdGjqysDNVmAGnkd-FWEt8jOUQQ58FoyqMryklj3E Content-Type: application/json { @@ -32,7 +32,7 @@ Content-Type: application/json ### # 상품 수정 PATCH http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NTMyNSwiZXhwIjoxNzE2ODY2MjI1fQ.yHZTsbdl-ZWTUM0_5RTe6wt2mAgF11uLTmN0MuLda9U Content-Type: application/json { @@ -44,13 +44,13 @@ Content-Type: application/json ### # 상품 삭제 -DELETE http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE +DELETE http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NTMyNSwiZXhwIjoxNzE2ODY2MjI1fQ.yHZTsbdl-ZWTUM0_5RTe6wt2mAgF11uLTmN0MuLda9U ### # 상품 좋아요 PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/like -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5NDc3MCwiZXhwIjoxNzE2Nzk1NjcwfQ.4jHyaxo0BgeSCSfTGAwnTlMLyRZGEJPoEOqUe-Xdo9w +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NjY3NiwiZXhwIjoxNzE2ODY3NTc2fQ.TiC1uKaRL28Y1WM-ADHCzo0Ply-l_IfYZx9e_rjyEqI ### # 상품 좋아요 취소 @@ -68,7 +68,7 @@ GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments ### # 상품 댓글 등록 POST http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NTcxNywiZXhwIjoxNzE2ODY2NjE3fQ.1zbdGjqysDNVmAGnkd-FWEt8jOUQQ58FoyqMryklj3E Content-Type: application/json { @@ -78,8 +78,8 @@ Content-Type: application/json ### # 상품 댓글 수정 -PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/4db38f1c-53c5-40c4-98ce-bcaa0ba7904d -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE +PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/9d7d8a72-693e-44d3-bf72-889c9ebac0d9 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NTcxNywiZXhwIjoxNzE2ODY2NjE3fQ.1zbdGjqysDNVmAGnkd-FWEt8jOUQQ58FoyqMryklj3E Content-Type: application/json { @@ -88,5 +88,5 @@ Content-Type: application/json ### # 상품 댓글 삭제 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5MzQwOSwiZXhwIjoxNzE2Nzk0MzA5fQ.uWsTo5_mKNsXmWdYpYlE492MMv_PV513S2mbs_bELTE -DELETE http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/4db38f1c-53c5-40c4-98ce-bcaa0ba7904d \ No newline at end of file +DELETE http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/9d7d8a72-693e-44d3-bf72-889c9ebac0d9 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NjY3NiwiZXhwIjoxNzE2ODY3NTc2fQ.TiC1uKaRL28Y1WM-ADHCzo0Ply-l_IfYZx9e_rjyEqI \ No newline at end of file diff --git a/prisma/migrations/20240528031512_add_user_id_to_comment/migration.sql b/prisma/migrations/20240528031512_add_user_id_to_comment/migration.sql new file mode 100644 index 0000000..b5f13a6 --- /dev/null +++ b/prisma/migrations/20240528031512_add_user_id_to_comment/migration.sql @@ -0,0 +1,11 @@ +/* + Warnings: + + - Added the required column `userId` to the `Comment` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "Comment" ADD COLUMN "userId" INTEGER NOT NULL; + +-- AddForeignKey +ALTER TABLE "Comment" ADD CONSTRAINT "Comment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/mock.js b/prisma/mock.js index 5cf4342..255b921 100644 --- a/prisma/mock.js +++ b/prisma/mock.js @@ -15,11 +15,11 @@ export const PRODUCTS = [ images: [ "https://view01.wemep.co.kr/wmp-product/4/879/2515748794/pm_ebifv5nrjsyf.jpg?1683280710&f=webp&w=460&h=460", ], - tags: ["판다인형", "인형", "판다"], + tags: ["판다인형", "인형", "판다", "불곰"], price: 7000, description: "판다인형 안판다", - name: "판다인형 안파는 판다", - userId: 1, + name: "불곰사세요", + userId: 2, }, ]; @@ -30,7 +30,7 @@ export const ARTICLES = [ content: "판다인형 구매 후기입니다.", imageUrl: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", likeCount: 7, - writer: "판다인형 수집가", + userId: 1, }, { id: "7c8b9d2e-5d45-4c9f-9b4b-7626f3c9c9a9", @@ -38,7 +38,7 @@ export const ARTICLES = [ content: "판다인형 판매 후기입니다.", imageUrl: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", likeCount: 2, - writer: "판다인형 중개인", + userId: 1, }, { id: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", @@ -46,7 +46,7 @@ export const ARTICLES = [ content: "불곰인형 구하는 곳 아시는분 계신가요?", imageUrl: "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg", likeCount: 3, - writer: "불곰인형 수집가", + userId: 2, }, ]; @@ -56,89 +56,106 @@ export const COMMENTS = [ content: "판다인형 너무 귀여워요!", writer: "판다인형 수집가", articleId: "2c027764-d7ef-4a94-8399-f15ffbf8f4da", + userId: 1, }, { id: "2b3c4d5e-6f7g-8h9i-0j1k-2l3m4n5o6p7q", content: "판다인형 너무 귀여워요1", writer: "판다인형 중개인", productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + userId: 1, }, { content: "판다인형 너무 귀여워요2", writer: "판다인형 중개인", productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + userId: 1, }, { content: "판다인형 너무 귀여워요3", writer: "판다인형 중개인", productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + userId: 1, }, { content: "판다인형 너무 귀여워요4", writer: "판다인형 중개인", productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + userId: 1, }, { content: "판다인형 너무 귀여워요5", writer: "판다인형 중개인", productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + userId: 1, }, { content: "판다인형 너무 귀여워요6", writer: "판다인형 중개인", productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + userId: 1, }, { content: "판다인형 너무 귀여워요7", writer: "판다인형 중개인", productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + userId: 1, }, { content: "판다인형 너무 귀여워요8", writer: "판다인형 중개인", productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + userId: 1, }, { content: "판다인형 너무 귀여워요9", writer: "판다인형 중개인", productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + userId: 1, }, { content: "판다인형 너무 귀여워요10", writer: "판다인형 중개인", productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + userId: 1, }, { content: "판다인형 너무 귀여워요11", writer: "판다인형 중개인", productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + userId: 1, }, { content: "판다인형 너무 귀여워요12", writer: "판다인형 중개인", productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + userId: 1, }, { id: "3c4d5e6f-7g8h-9i0j-1k2l-3m4n5o6p7q8r", content: "불곰인형 너무 귀여워요!", writer: "불곰인형 수집가", articleId: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", + userId: 2, }, { id: "3c4d5e6f-7g8h-9i0j-1k2l-3m4n5o6p7q8r", content: "불곰인형 너무 귀여워요1", writer: "불곰인형 수집가", articleId: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", + userId: 2, }, { content: "불곰인형 너무 귀여워요2", writer: "불곰인형 수집가", articleId: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", + userId: 2, }, { content: "불곰인형 너무 귀여워요3", writer: "불곰인형 수집가", articleId: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", + userId: 2, }, ]; @@ -148,7 +165,25 @@ export const USERS = [ email: "test@gmail.com", name: "김판다", nickname: "판다의 왕", - password: "$2b$10$cq6uUbVgrWG9UG6Gpu/k3un1aTLE8XzMfAyU2NhS2FIY93M.CFXqO", + password: "$2b$10$2vHNtEq54uvrSksq8CPadugrnhYwcPjltPp6z66E85HJJqMLCXGN.", + createdAt: new Date(), + updatedAt: new Date(), + }, + { + id: 2, + email: "test2@gmail.com", + name: "박불곰", + nickname: "킹오브불곰", + password: "$2b$10$2vHNtEq54uvrSksq8CPadugrnhYwcPjltPp6z66E85HJJqMLCXGN.", + createdAt: new Date(), + updatedAt: new Date(), + }, + { + id: 1, + email: "test@gmail.com", + name: "김판다", + nickname: "판다의 왕", + password: "$2b$10$2vHNtEq54uvrSksq8CPadugrnhYwcPjltPp6z66E85HJJqMLCXGN.", createdAt: new Date(), updatedAt: new Date(), }, diff --git a/prisma/schema.prisma b/prisma/schema.prisma index b1d6c8f..3c3d127 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -24,6 +24,7 @@ model User { products Product[] articles Article[] favorites Favorite[] + Comment Comment[] } model Product { @@ -69,6 +70,8 @@ model Comment { productId String? article Article? @relation(fields: [articleId], references: [id], onDelete: SetNull) articleId String? + userId Int + User User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([productId]) @@index([articleId]) diff --git a/routes/products.js b/routes/products.js index b809c28..a2bf84c 100644 --- a/routes/products.js +++ b/routes/products.js @@ -72,25 +72,42 @@ router .patch( authenticate, asyncHandler(async (req, res) => { + const { id: productId } = req.params; + const { userId } = req; + const product = await prisma.product.findUniqueOrThrow({ + where: { id: productId }, + }); + + if (product.userId !== userId) { + return res.status(403).json({ error: "상품을 수정할 권한이 없습니다." }); + } assert(req.body, PatchProduct); - const { id } = req.params; - const product = await prisma.product.update({ + + const updatedProduct = await prisma.product.update({ where: { - id, + id: productId, }, data: req.body, }); - res.send(product); + res.send(updatedProduct); }) ) .delete( authenticate, asyncHandler(async (req, res) => { - const { id } = req.params; + const { id: productId } = req.params; + const { userId } = req; + const product = await prisma.product.findUniqueOrThrow({ + where: { id: productId }, + }); + + if (product.userId !== userId) { + return res.status(403).json({ error: "상품을 삭제할 권한이 없습니다." }); + } await prisma.product.delete({ where: { - id, + id: productId, }, }); @@ -104,11 +121,6 @@ router.patch( asyncHandler(async (req, res) => { const { id: productId } = req.params; const { userId } = req; - const product = await prisma.product.findUniqueOrThrow({ - where: { - id: productId, - }, - }); const favorite = await prisma.favorite.findUnique({ where: { @@ -152,11 +164,6 @@ router.patch( asyncHandler(async (req, res) => { const { id: productId } = req.params; const { userId } = req; - const product = await prisma.product.findUniqueOrThrow({ - where: { - id: productId, - }, - }); const favorite = await prisma.favorite.findUnique({ where: { @@ -179,6 +186,7 @@ router.patch( }, }, }); + const updatedProduct = await prisma.product.update({ where: { id: productId, @@ -234,12 +242,15 @@ router authenticate, asyncHandler(async (req, res) => { assert(req.body, CreateComment); - const { id } = req.params; + + const { userId } = req; + const { id: productId } = req.params; const comment = await prisma.comment.create({ data: { ...req.body, - productId: id, + productId, + userId, }, }); res.status(201).send(comment); @@ -252,21 +263,36 @@ router authenticate, asyncHandler(async (req, res) => { assert(req.body, PatchComment); + const { userId } = req; + const { content } = req.body; const { commentId } = req.params; - const comment = await prisma.comment.update({ - where: { - id: commentId, - }, - data: req.body, + const comment = await prisma.comment.findUniqueOrThrow({ + where: { id: commentId }, }); - - res.send(comment); + if (comment.userId !== userId) { + return res.status(403).json({ error: "이 댓글을 수정할 권한이 없습니다." }); + } + const updatedComment = await prisma.comment.update({ + where: { id: commentId }, + data: { content }, + }); + res.send(updatedComment); }) ) .delete( authenticate, asyncHandler(async (req, res) => { const { commentId } = req.params; + const { userId } = req; + + const comment = await prisma.comment.findUniqueOrThrow({ + where: { id: commentId }, + }); + + if (comment.userId !== userId) { + return res.status(403).json({ error: "이 댓글을 삭제할 권한이 없습니다." }); + } + await prisma.comment.delete({ where: { id: commentId, From 33d0c3923f96210614b58ae7ee78f6bd9fc45fc9 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Tue, 28 May 2024 12:42:29 +0900 Subject: [PATCH 31/60] =?UTF-8?q?[#M10]=20fix=20:=20=EC=9E=90=EC=9C=A0?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=ED=8C=90=20=EA=B4=80=EB=A0=A8=20API=EB=93=A4?= =?UTF-8?q?=EC=9D=B4=20userId=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- http/articles.http | 16 ++++-- routes/articles.js | 126 +++++++++++++++++++++++++++++++-------------- routes/products.js | 13 +++-- 3 files changed, 109 insertions(+), 46 deletions(-) diff --git a/http/articles.http b/http/articles.http index ad5c723..e7add53 100644 --- a/http/articles.http +++ b/http/articles.http @@ -9,6 +9,7 @@ GET http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da ### # 게시글 등록 POST http://localhost:3000/articles +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ Content-Type: application/json { @@ -19,7 +20,8 @@ Content-Type: application/json ### # 게시글 수정 -PATCH http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da +PATCH http://localhost:3000/articles/9c96039f-e56d-470e-847f-aa24b8da981c +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ Content-Type: application/json { @@ -29,15 +31,18 @@ Content-Type: application/json ### # 게시글 삭제 -DELETE http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da +DELETE http://localhost:3000/articles/9c96039f-e56d-470e-847f-aa24b8da981c +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ ### # 게시글 좋아요 PATCH http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/like +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ ### # 게시글 좋아요 취소 PATCH http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/unlike +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ @@ -54,6 +59,7 @@ GET http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments # 자유게시판 댓글 등록 POST http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments Content-Type: application/json +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ { "content":"판다가 너무 귀여워요2" @@ -61,8 +67,9 @@ Content-Type: application/json ### # 자유게시판 댓글 수정 -PATCH http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments/1a2b3c4d-5e6f-7g8h-9i0j-1k2l3m4n5o6p +PATCH http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments/98b65e20-e12b-43fb-8b04-6525b019eb8b Content-Type: application/json +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ { "content":"판다가 너무 귀여워요 수정" @@ -70,4 +77,5 @@ Content-Type: application/json ### # 자유게시판 댓글 삭제 -DELETE http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments/1a2b3c4d-5e6f-7g8h-9i0j-1k2l3m4n5o6p \ No newline at end of file +DELETE http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments/98b65e20-e12b-43fb-8b04-6525b019eb8b +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ \ No newline at end of file diff --git a/routes/articles.js b/routes/articles.js index c42ced9..881cb3f 100644 --- a/routes/articles.js +++ b/routes/articles.js @@ -64,8 +64,9 @@ router authenticate, asyncHandler(async (req, res) => { assert(req.body, CreateArticle); + const { userId } = req; const article = await prisma.article.create({ - data: req.body, + data: { ...req.body, userId }, }); res.status(201).send(article); }) @@ -97,24 +98,45 @@ router authenticate, asyncHandler(async (req, res) => { assert(req.body, PatchArticle); - const { id } = req.params; - const article = await prisma.article.update({ + + const { id: articleId } = req.params; + const { userId } = req; + + const article = await prisma.article.findUniqueOrThrow({ + where: { id: articleId }, + }); + + if (article.userId !== userId) { + return res.status(403).json({ error: "게시글을 수정할 권한이 없습니다." }); + } + + const updatedArticle = await prisma.article.update({ where: { - id, + id: articleId, }, data: req.body, }); - res.send(article); + res.send(updatedArticle); }) ) .delete( authenticate, asyncHandler(async (req, res) => { - const { id } = req.params; + const { id: articleId } = req.params; + const { userId } = req; + + const article = await prisma.article.findUniqueOrThrow({ + where: { id: articleId }, + }); + + if (article.userId !== userId) { + return res.status(403).json({ error: "게시글을 삭제할 권한이 없습니다." }); + } + await prisma.article.delete({ where: { - id, + id: articleId, }, }); @@ -126,17 +148,14 @@ router.patch( "/:id/like", authenticate, asyncHandler(async (req, res) => { - const article = await prisma.article.findUniqueOrThrow({ - where: { - id: req.params.id, - }, - }); + const { id: articleId } = req.params; + const { userId } = req; const favorite = await prisma.favorite.findUnique({ where: { - userId_productId_articleId: { - userId: req.userId, - articleId: req.params.id, + userId_articleId: { + userId, + articleId, }, }, }); @@ -146,15 +165,21 @@ router.patch( return; } + await prisma.favorite.create({ + data: { + userId, + articleId, + }, + }); + const updatedArticle = await prisma.article.update({ where: { - id: req.params.id, + id: articleId, }, data: { likeCount: { increment: 1, }, - isLiked: true, }, }); @@ -166,17 +191,14 @@ router.patch( "/:id/unlike", authenticate, asyncHandler(async (req, res) => { - const article = await prisma.article.findUniqueOrThrow({ - where: { - id: req.params.id, - }, - }); + const { id: articleId } = req.params; + const { userId } = req; const favorite = await prisma.favorite.findUnique({ where: { - userId_productId_articleId: { - userId: req.userId, - articleId: req.params.id, + userId_articleId: { + userId, + articleId, }, }, }); @@ -186,15 +208,23 @@ router.patch( return; } + await prisma.favorite.delete({ + where: { + userId_articleId: { + userId, + articleId, + }, + }, + }); + const updatedArticle = await prisma.article.update({ where: { - id: req.params.id, + id: articleId, }, data: { likeCount: { decrement: 1, }, - isLiked: false, }, }); @@ -242,12 +272,14 @@ router authenticate, asyncHandler(async (req, res) => { assert(req.body, CreateComment); - const { id } = req.params; + const { userId } = req; + const { id: articleId } = req.params; const comment = await prisma.comment.create({ data: { ...req.body, - articleId: id, + articleId, + userId, }, }); res.status(201).send(comment); @@ -260,25 +292,43 @@ router authenticate, asyncHandler(async (req, res) => { assert(req.body, PatchComment); + + const { userId } = req; + const { content } = req.body; const { commentId } = req.params; - const comment = await prisma.comment.update({ - where: { - id: commentId, - }, - data: req.body, + + const comment = await prisma.comment.findUniqueOrThrow({ + where: { id: commentId }, }); - res.send(comment); + if (comment.userId !== userId) { + return res.status(403).json({ error: "이 댓글을 수정할 권한이 없습니다." }); + } + + const updatedComment = await prisma.comment.update({ + where: { id: commentId }, + data: { content }, + }); + + res.send(updatedComment); }) ) .delete( authenticate, asyncHandler(async (req, res) => { const { commentId } = req.params; + const { userId } = req; + + const comment = await prisma.comment.findUniqueOrThrow({ + where: { id: commentId }, + }); + + if (comment.userId !== userId) { + return res.status(403).json({ error: "이 댓글을 삭제할 권한이 없습니다." }); + } + await prisma.comment.delete({ - where: { - id: commentId, - }, + where: { id: commentId }, }); res.sendStatus(204); diff --git a/routes/products.js b/routes/products.js index a2bf84c..eec8014 100644 --- a/routes/products.js +++ b/routes/products.js @@ -72,8 +72,11 @@ router .patch( authenticate, asyncHandler(async (req, res) => { + assert(req.body, PatchProduct); + const { id: productId } = req.params; const { userId } = req; + const product = await prisma.product.findUniqueOrThrow({ where: { id: productId }, }); @@ -81,7 +84,6 @@ router if (product.userId !== userId) { return res.status(403).json({ error: "상품을 수정할 권한이 없습니다." }); } - assert(req.body, PatchProduct); const updatedProduct = await prisma.product.update({ where: { @@ -98,6 +100,7 @@ router asyncHandler(async (req, res) => { const { id: productId } = req.params; const { userId } = req; + const product = await prisma.product.findUniqueOrThrow({ where: { id: productId }, }); @@ -263,15 +266,19 @@ router authenticate, asyncHandler(async (req, res) => { assert(req.body, PatchComment); + const { userId } = req; const { content } = req.body; const { commentId } = req.params; + const comment = await prisma.comment.findUniqueOrThrow({ where: { id: commentId }, }); + if (comment.userId !== userId) { return res.status(403).json({ error: "이 댓글을 수정할 권한이 없습니다." }); } + const updatedComment = await prisma.comment.update({ where: { id: commentId }, data: { content }, @@ -294,9 +301,7 @@ router } await prisma.comment.delete({ - where: { - id: commentId, - }, + where: { id: commentId }, }); res.sendStatus(204); From 1e79c48e0e6436cbe938e5e149bb64ebe935617d Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Tue, 28 May 2024 12:56:21 +0900 Subject: [PATCH 32/60] =?UTF-8?q?[#M10]=20feat=20:=20=EC=A2=8B=EC=95=84?= =?UTF-8?q?=EC=9A=94,=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EC=B7=A8=EC=86=8C?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=EC=97=90=20transaction=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- routes/articles.js | 69 +++++++++++++++++++++++----------------------- routes/images.js | 4 ++- routes/products.js | 68 +++++++++++++++++++++++---------------------- 3 files changed, 73 insertions(+), 68 deletions(-) diff --git a/routes/articles.js b/routes/articles.js index 881cb3f..09ce4f3 100644 --- a/routes/articles.js +++ b/routes/articles.js @@ -164,24 +164,24 @@ router.patch( res.status(400).send({ message: "이미 좋아요 처리된 게시글입니다." }); return; } - - await prisma.favorite.create({ - data: { - userId, - articleId, - }, - }); - - const updatedArticle = await prisma.article.update({ - where: { - id: articleId, - }, - data: { - likeCount: { - increment: 1, + const [createdFavorite, updatedArticle] = await prisma.$transaction([ + prisma.favorite.create({ + data: { + userId, + articleId, }, - }, - }); + }), + prisma.article.update({ + where: { + id: articleId, + }, + data: { + likeCount: { + increment: 1, + }, + }, + }), + ]); res.send(updatedArticle); }) @@ -208,25 +208,26 @@ router.patch( return; } - await prisma.favorite.delete({ - where: { - userId_articleId: { - userId, - articleId, + const [deletedFavorite, updatedArticle] = await prisma.$transaction([ + prisma.favorite.delete({ + where: { + userId_articleId: { + userId, + articleId, + }, }, - }, - }); - - const updatedArticle = await prisma.article.update({ - where: { - id: articleId, - }, - data: { - likeCount: { - decrement: 1, + }), + prisma.article.update({ + where: { + id: articleId, }, - }, - }); + data: { + likeCount: { + decrement: 1, + }, + }, + }), + ]); res.send(updatedArticle); }) diff --git a/routes/images.js b/routes/images.js index 33dbcae..e3ff815 100644 --- a/routes/images.js +++ b/routes/images.js @@ -23,12 +23,14 @@ const upload = multer({ storage: storage }); // 이미지 업로드 router.post("/upload", authenticate, upload.single("image"), async (req, res) => { const file = req.file; - console.log(req); + if (!file) { return res.status(400).send("이미지 파일을 선택해주세요."); } + const imagePath = file.path; const imageUrl = `${SERVER_URL}/${imagePath.replace(/\\/g, "/")}`; + const image = await prisma.image.create({ data: { imagePath: imagePath, diff --git a/routes/products.js b/routes/products.js index eec8014..9c8e011 100644 --- a/routes/products.js +++ b/routes/products.js @@ -139,23 +139,24 @@ router.patch( return; } - await prisma.favorite.create({ - data: { - userId, - productId, - }, - }); - - const updatedProduct = await prisma.product.update({ - where: { - id: productId, - }, - data: { - favoriteCount: { - increment: 1, + const [createdFavorite, updatedProduct] = await prisma.$transaction([ + prisma.favorite.create({ + data: { + userId, + productId, }, - }, - }); + }), + prisma.product.update({ + where: { + id: productId, + }, + data: { + likeCount: { + increment: 1, + }, + }, + }), + ]); res.send(updatedProduct); }) @@ -181,25 +182,26 @@ router.patch( return res.status(400).send({ message: "아직 좋아요 처리되지 않은 상품입니다." }); } - await prisma.favorite.delete({ - where: { - userId_productId: { - userId, - productId, + const [deletedFavorite, updatedProduct] = await prisma.$transaction([ + prisma.favorite.delete({ + where: { + userId_productId: { + userId, + productId, + }, }, - }, - }); - - const updatedProduct = await prisma.product.update({ - where: { - id: productId, - }, - data: { - favoriteCount: { - decrement: 1, + }), + prisma.product.update({ + where: { + id: productId, }, - }, - }); + data: { + likeCount: { + decrement: 1, + }, + }, + }), + ]); res.send(updatedProduct); }) From 3d46d255ba6dd8a9f6e8a92d5983b3818efd1167 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Tue, 28 May 2024 13:33:31 +0900 Subject: [PATCH 33/60] =?UTF-8?q?[#M10]=20feat=20:=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=ED=95=B8=EB=93=A4=EB=9F=AC=20=EB=AF=B8=EB=93=A4=EC=9B=A8?= =?UTF-8?q?=EC=96=B4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 11 +++++++---- middlewares/errorHandler.js | 14 ++++++++++++++ utils/tokens.js | 6 ++++-- 3 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 middlewares/errorHandler.js diff --git a/app.js b/app.js index 7a94b64..cfbfcdb 100644 --- a/app.js +++ b/app.js @@ -4,6 +4,7 @@ import moment from "moment-timezone"; import morgan from "morgan"; import path, { dirname } from "path"; import { fileURLToPath } from "url"; +import errorHandler from "./middlewares/errorHandler.js"; import articlesRouter from "./routes/articles.js"; import authRouter from "./routes/auth.js"; import imagesRouter from "./routes/images.js"; @@ -17,13 +18,11 @@ const app = express(); morgan.token("date", (req, res, tz) => { return moment().tz(tz).format("YYYY-MM-DD HH:mm:ss"); }); -// 커스텀 포맷 설정: 한국 시간대의 현재 시간을 포함 + const customFormat = ":method :url :status :res[content-length] - :response-time ms - :date[Asia/Seoul]"; -// 로그 파일 스트림 생성 const accessLogStream = fs.createWriteStream(path.join(__dirname, "access.log"), { flags: "a" }); -// morgan 미들웨어 설정 (로그 파일에 기록) app.use(morgan(customFormat, { stream: accessLogStream })); app.use(express.json()); app.use(express.urlencoded({ extended: true })); @@ -33,6 +32,10 @@ app.use("/articles", articlesRouter); app.use("/images", imagesRouter); app.use("/auth", authRouter); -app.listen(3000, () => { +app.use(errorHandler); + +const PORT = process.env.PORT || 3000; + +app.listen(PORT, () => { console.log("Server is running on port 3000"); }); diff --git a/middlewares/errorHandler.js b/middlewares/errorHandler.js new file mode 100644 index 0000000..50208e3 --- /dev/null +++ b/middlewares/errorHandler.js @@ -0,0 +1,14 @@ +const errorHandler = (err, req, res) => { + console.error(err.stack); + + const status = err.status || 500; + const message = err.message || "서버 오류가 발생했습니다."; + + res.status(status).json({ + error: { + message, + }, + }); +}; + +export default errorHandler; diff --git a/utils/tokens.js b/utils/tokens.js index 12d5d2e..4697c00 100644 --- a/utils/tokens.js +++ b/utils/tokens.js @@ -3,7 +3,9 @@ import jwt from "jsonwebtoken"; dotenv.config(); -const { JWT_SECRET, JWT_ACCESS_EXPIRES_IN, JWT_REFRESH_EXPIRES_IN } = process.env; +const JWT_SECRET = process.env.JWT_SECRET || "kingPanda"; +const JWT_ACCESS_EXPIRES_IN = process.env.JWT_ACCESS_EXPIRES_IN || "15m"; +const JWT_REFRESH_EXPIRES_IN = process.env.JWT_REFRESH_EXPIRES_IN || "7d"; export const generateAccessToken = (user) => { return jwt.sign({ userId: user.id }, JWT_SECRET, { expiresIn: JWT_ACCESS_EXPIRES_IN }); @@ -16,7 +18,7 @@ export const generateRefreshToken = (user) => { export const regenerateRefreshToken = (refreshToken) => { try { const decoded = jwt.verify(refreshToken, JWT_SECRET); - return jwt.sign({ userId: decoded.userId }, JWT_SECRET, { expiresIn: "7d" }); + return jwt.sign({ userId: decoded.userId }, JWT_SECRET, { expiresIn: JWT_REFRESH_EXPIRES_IN }); } catch (error) { throw new Error("Invalid refresh token"); } From 500f34e3537832c308d0e6648aff17c153826a6e Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Tue, 28 May 2024 14:58:14 +0900 Subject: [PATCH 34/60] =?UTF-8?q?[#M10]=20fix=20:=20MVC=20=ED=8C=A8?= =?UTF-8?q?=ED=84=B4=20=EC=A0=81=EC=9A=A9=20=EB=B0=8F=20CORS=20=EB=AF=B8?= =?UTF-8?q?=EB=93=A4=EC=9B=A8=EC=96=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 서버 코드를 MVC 패턴으로 리팩토링 - 이미지 업로드 기능 테스트를 위해 CORS 미들웨어 추가 --- app.js | 11 +- controllers/articleController.js | 86 +++++++ controllers/commentController.js | 60 +++++ controllers/imageController.js | 13 + controllers/productController.js | 73 ++++++ http/articles.http | 20 +- http/products.http | 20 +- middlewares/errorHandler.js | 21 +- package-lock.json | 13 + package.json | 1 + routes/articleRoutes.js | 28 +++ routes/articles.js | 339 --------------------------- routes/{auth.js => authRoutes.js} | 0 routes/{images.js => imageRoutes.js} | 23 +- routes/productRoutes.js | 28 +++ routes/products.js | 313 ------------------------- services/articleService.js | 173 ++++++++++++++ services/commentService.js | 106 +++++++++ services/imageService.js | 21 ++ services/productService.js | 156 ++++++++++++ test.html | 35 ++- utils/errors.js | 12 + 22 files changed, 843 insertions(+), 709 deletions(-) create mode 100644 controllers/articleController.js create mode 100644 controllers/commentController.js create mode 100644 controllers/imageController.js create mode 100644 controllers/productController.js create mode 100644 routes/articleRoutes.js delete mode 100644 routes/articles.js rename routes/{auth.js => authRoutes.js} (100%) rename routes/{images.js => imageRoutes.js} (50%) create mode 100644 routes/productRoutes.js delete mode 100644 routes/products.js create mode 100644 services/articleService.js create mode 100644 services/commentService.js create mode 100644 services/imageService.js create mode 100644 services/productService.js create mode 100644 utils/errors.js diff --git a/app.js b/app.js index cfbfcdb..4232adc 100644 --- a/app.js +++ b/app.js @@ -1,3 +1,4 @@ +import cors from "cors"; import express from "express"; import fs from "fs"; import moment from "moment-timezone"; @@ -5,11 +6,10 @@ import morgan from "morgan"; import path, { dirname } from "path"; import { fileURLToPath } from "url"; import errorHandler from "./middlewares/errorHandler.js"; -import articlesRouter from "./routes/articles.js"; -import authRouter from "./routes/auth.js"; -import imagesRouter from "./routes/images.js"; -import productsRouter from "./routes/products.js"; - +import articlesRouter from "./routes/articleRoutes.js"; +import authRouter from "./routes/authRoutes.js"; +import imagesRouter from "./routes/imageRoutes.js"; +import productsRouter from "./routes/productRoutes.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -26,6 +26,7 @@ const accessLogStream = fs.createWriteStream(path.join(__dirname, "access.log"), app.use(morgan(customFormat, { stream: accessLogStream })); app.use(express.json()); app.use(express.urlencoded({ extended: true })); +app.use(cors()); app.use("/products", productsRouter); app.use("/articles", articlesRouter); diff --git a/controllers/articleController.js b/controllers/articleController.js new file mode 100644 index 0000000..ea6b2bd --- /dev/null +++ b/controllers/articleController.js @@ -0,0 +1,86 @@ +import { assert } from "superstruct"; +import * as articleService from "../services/articleService.js"; +import { CreateArticle, PatchArticle } from "../structs.js"; +import asyncHandler from "../utils/asyncHandler.js"; +import AppError from "../utils/errors.js"; + +export const getArticles = asyncHandler(async (req, res) => { + const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; + const articles = await articleService.getArticles({ offset, limit, orderBy, keyword }); + const bestArticles = await articleService.getBestArticles(); + res.send({ articles, bestArticles }); +}); + +export const createArticle = asyncHandler(async (req, res) => { + assert(req.body, CreateArticle); + const { userId } = req; + const article = await articleService.createArticle({ ...req.body, userId }); + res.status(201).send(article); +}); + +export const getArticleById = asyncHandler(async (req, res) => { + const { id } = req.params; + const article = await articleService.getArticleById(id); + res.send(article); +}); + +export const updateArticle = asyncHandler(async (req, res, next) => { + assert(req.body, PatchArticle); + + const { id: articleId } = req.params; + const { userId } = req; + + try { + const updatedArticle = await articleService.updateArticle(articleId, userId, req.body); + res.send(updatedArticle); + } catch (error) { + if (error instanceof AppError) { + return res.status(error.statusCode).json({ message: error.message }); + } + } +}); + +export const deleteArticle = asyncHandler(async (req, res, next) => { + const { id: articleId } = req.params; + const { userId } = req; + + try { + await articleService.deleteArticle(articleId, userId); + res.sendStatus(204); + } catch (error) { + if (error instanceof AppError) { + return res.status(error.statusCode).json({ message: error.message }); + } + next(error); + } +}); + +export const likeArticle = asyncHandler(async (req, res, next) => { + const { id: articleId } = req.params; + const { userId } = req; + + try { + const updatedArticle = await articleService.likeArticle(articleId, userId); + res.send(updatedArticle); + } catch (error) { + if (error instanceof AppError) { + return res.status(error.statusCode).json({ message: error.message }); + } + next(error); + } +}); + +export const unlikeArticle = asyncHandler(async (req, res, next) => { + const { id: articleId } = req.params; + const { userId } = req; + + try { + const updatedArticle = await articleService.unlikeArticle(articleId, userId); + res.send(updatedArticle); + } catch (error) { + if (error instanceof AppError) { + return res.status(error.statusCode).json({ message: error.message }); + } + next(error); + } +}); diff --git a/controllers/commentController.js b/controllers/commentController.js new file mode 100644 index 0000000..f73fc09 --- /dev/null +++ b/controllers/commentController.js @@ -0,0 +1,60 @@ +import { assert } from "superstruct"; +import * as commentService from "../services/commentService.js"; +import { CreateComment, PatchComment } from "../structs.js"; +import asyncHandler from "../utils/asyncHandler.js"; + +export const getCommentsByProductId = asyncHandler(async (req, res) => { + const { id: productId } = req.params; + const { cursor } = req.query; + const comments = await commentService.getCommentsByProductId(productId, cursor); + res.send(comments); +}); + +export const getCommentsByArticleId = asyncHandler(async (req, res) => { + const { id: articleId } = req.params; + const { cursor } = req.query; + const comments = await commentService.getCommentsByArticleId(articleId, cursor); + res.send(comments); +}); + +export const createComment = asyncHandler(async (req, res) => { + assert(req.body, CreateComment); + + const { userId } = req; + + const commentData = { + ...req.body, + ...req.params, + userId, + }; + + const comment = await commentService.createComment(commentData); + res.status(201).send(comment); +}); + +export const updateComment = asyncHandler(async (req, res) => { + assert(req.body, PatchComment); + + const { userId } = req; + const { content } = req.body; + const { commentId } = req.params; + + try { + const updatedComment = await commentService.updateComment(commentId, userId, content); + res.send(updatedComment); + } catch (error) { + res.status(403).json({ message: error.message }); + } +}); + +export const deleteComment = asyncHandler(async (req, res) => { + const { commentId } = req.params; + const { userId } = req; + + try { + await commentService.deleteComment(commentId, userId); + res.sendStatus(204); + } catch (error) { + res.status(403).json({ message: error.message }); + } +}); diff --git a/controllers/imageController.js b/controllers/imageController.js new file mode 100644 index 0000000..76a3bd5 --- /dev/null +++ b/controllers/imageController.js @@ -0,0 +1,13 @@ +import * as imageService from "../services/imageService.js"; +import asyncHandler from "../utils/asyncHandler.js"; + +export const uploadImage = asyncHandler(async (req, res) => { + const file = req.file; + + try { + const imageUrl = await imageService.uploadImage(file); + res.status(200).json({ url: imageUrl }); + } catch (error) { + res.status(400).send(error.message); + } +}); diff --git a/controllers/productController.js b/controllers/productController.js new file mode 100644 index 0000000..9467511 --- /dev/null +++ b/controllers/productController.js @@ -0,0 +1,73 @@ +import { assert } from "superstruct"; +import * as productService from "../services/productService.js"; +import { CreateProduct, PatchProduct } from "../structs.js"; +import asyncHandler from "../utils/asyncHandler.js"; + +export const getProducts = asyncHandler(async (req, res) => { + const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; + const products = await productService.getProducts({ offset, limit, orderBy, keyword }); + res.send(products); +}); + +export const createProduct = asyncHandler(async (req, res) => { + assert(req.body, CreateProduct); + const { userId } = req; + const product = await productService.createProduct({ ...req.body, userId }); + res.status(201).send(product); +}); + +export const getProductById = asyncHandler(async (req, res) => { + const { id } = req.params; + const product = await productService.getProductById(id); + res.send(product); +}); + +export const updateProduct = asyncHandler(async (req, res) => { + assert(req.body, PatchProduct); + + const { id: productId } = req.params; + const { userId } = req; + + try { + const updatedProduct = await productService.updateProduct(productId, userId, req.body); + res.send(updatedProduct); + } catch (error) { + res.status(403).json({ message: error.message }); + } +}); + +export const deleteProduct = asyncHandler(async (req, res) => { + const { id: productId } = req.params; + const { userId } = req; + + try { + await productService.deleteProduct(productId, userId); + res.sendStatus(204); + } catch (error) { + res.status(403).json({ message: error.message }); + } +}); + +export const likeProduct = asyncHandler(async (req, res) => { + const { id: productId } = req.params; + const { userId } = req; + + try { + const updatedProduct = await productService.likeProduct(productId, userId); + res.send(updatedProduct); + } catch (error) { + res.status(400).json({ message: error.message }); + } +}); + +export const unlikeProduct = asyncHandler(async (req, res) => { + const { id: productId } = req.params; + const { userId } = req; + + try { + const updatedProduct = await productService.unlikeProduct(productId, userId); + res.send(updatedProduct); + } catch (error) { + res.status(400).json({ message: error.message }); + } +}); diff --git a/http/articles.http b/http/articles.http index e7add53..99e2a4a 100644 --- a/http/articles.http +++ b/http/articles.http @@ -9,7 +9,7 @@ GET http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da ### # 게시글 등록 POST http://localhost:3000/articles -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 Content-Type: application/json { @@ -20,8 +20,8 @@ Content-Type: application/json ### # 게시글 수정 -PATCH http://localhost:3000/articles/9c96039f-e56d-470e-847f-aa24b8da981c -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ +PATCH http://localhost:3000/articles/c058e3ae-00d2-4b5a-a0dc-acd284f03e7b +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 Content-Type: application/json { @@ -32,17 +32,17 @@ Content-Type: application/json ### # 게시글 삭제 DELETE http://localhost:3000/articles/9c96039f-e56d-470e-847f-aa24b8da981c -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 ### # 게시글 좋아요 PATCH http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/like -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 ### # 게시글 좋아요 취소 PATCH http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/unlike -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 @@ -59,7 +59,7 @@ GET http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments # 자유게시판 댓글 등록 POST http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments Content-Type: application/json -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 { "content":"판다가 너무 귀여워요2" @@ -67,9 +67,9 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhd ### # 자유게시판 댓글 수정 -PATCH http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments/98b65e20-e12b-43fb-8b04-6525b019eb8b +PATCH http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments/31599931-2aac-47fb-85ad-8de4c0a4a56d Content-Type: application/json -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 { "content":"판다가 너무 귀여워요 수정" @@ -78,4 +78,4 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhd ### # 자유게시판 댓글 삭제 DELETE http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments/98b65e20-e12b-43fb-8b04-6525b019eb8b -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NzYyMSwiZXhwIjoxNzE2ODY4NTIxfQ.fLV77AhiNJ_mlIzQ_dc5qv8v2gxth6_LKxSrUv3NXYQ \ No newline at end of file +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 \ No newline at end of file diff --git a/http/products.http b/http/products.http index 315fe1a..39b37f6 100644 --- a/http/products.http +++ b/http/products.http @@ -13,12 +13,12 @@ GET http://localhost:3000/products?keyword=판다 ### # 상품 상세 조회 -GET http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 +GET http://localhost:3000/products/d44e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 ### # 상품 등록 POST http://localhost:3000/products -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NTcxNywiZXhwIjoxNzE2ODY2NjE3fQ.1zbdGjqysDNVmAGnkd-FWEt8jOUQQ58FoyqMryklj3E +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 Content-Type: application/json { @@ -32,7 +32,7 @@ Content-Type: application/json ### # 상품 수정 PATCH http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NTMyNSwiZXhwIjoxNzE2ODY2MjI1fQ.yHZTsbdl-ZWTUM0_5RTe6wt2mAgF11uLTmN0MuLda9U +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 Content-Type: application/json { @@ -45,17 +45,17 @@ Content-Type: application/json ### # 상품 삭제 DELETE http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NTMyNSwiZXhwIjoxNzE2ODY2MjI1fQ.yHZTsbdl-ZWTUM0_5RTe6wt2mAgF11uLTmN0MuLda9U +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 ### # 상품 좋아요 PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/like -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NjY3NiwiZXhwIjoxNzE2ODY3NTc2fQ.TiC1uKaRL28Y1WM-ADHCzo0Ply-l_IfYZx9e_rjyEqI +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 ### # 상품 좋아요 취소 PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/unlike -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5NDc3MCwiZXhwIjoxNzE2Nzk1NjcwfQ.4jHyaxo0BgeSCSfTGAwnTlMLyRZGEJPoEOqUe-Xdo9w +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 ### # 상품 댓글 조회 @@ -68,7 +68,7 @@ GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments ### # 상품 댓글 등록 POST http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NTcxNywiZXhwIjoxNzE2ODY2NjE3fQ.1zbdGjqysDNVmAGnkd-FWEt8jOUQQ58FoyqMryklj3E +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 Content-Type: application/json { @@ -78,8 +78,8 @@ Content-Type: application/json ### # 상품 댓글 수정 -PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/9d7d8a72-693e-44d3-bf72-889c9ebac0d9 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NTcxNywiZXhwIjoxNzE2ODY2NjE3fQ.1zbdGjqysDNVmAGnkd-FWEt8jOUQQ58FoyqMryklj3E +PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/536a7b1b-83c9-42c1-93b9-c4755e7fc8d6 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 Content-Type: application/json { @@ -89,4 +89,4 @@ Content-Type: application/json ### # 상품 댓글 삭제 DELETE http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/9d7d8a72-693e-44d3-bf72-889c9ebac0d9 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg2NjY3NiwiZXhwIjoxNzE2ODY3NTc2fQ.TiC1uKaRL28Y1WM-ADHCzo0Ply-l_IfYZx9e_rjyEqI \ No newline at end of file +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 \ No newline at end of file diff --git a/middlewares/errorHandler.js b/middlewares/errorHandler.js index 50208e3..e042938 100644 --- a/middlewares/errorHandler.js +++ b/middlewares/errorHandler.js @@ -1,14 +1,19 @@ +import AppError from "../utils/errors.js"; + const errorHandler = (err, req, res) => { console.error(err.stack); - const status = err.status || 500; - const message = err.message || "서버 오류가 발생했습니다."; - - res.status(status).json({ - error: { - message, - }, - }); + if (err instanceof AppError) { + res.status(err.statusCode).json({ + status: err.status, + message: err.message, + }); + } else { + res.status(500).json({ + status: "error", + message: "서버 오류가 발생했습니다.", + }); + } }; export default errorHandler; diff --git a/package-lock.json b/package-lock.json index 09bccb8..880fe62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "dependencies": { "@prisma/client": "^5.4.2", "bcrypt": "^5.1.1", + "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", "is-email": "^1.0.2", @@ -439,6 +440,18 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", diff --git a/package.json b/package.json index 87a3db6..7334f69 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "dependencies": { "@prisma/client": "^5.4.2", "bcrypt": "^5.1.1", + "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", "is-email": "^1.0.2", diff --git a/routes/articleRoutes.js b/routes/articleRoutes.js new file mode 100644 index 0000000..bfba509 --- /dev/null +++ b/routes/articleRoutes.js @@ -0,0 +1,28 @@ +import express from "express"; +import * as articleController from "../controllers/articleController.js"; +import * as commentController from "../controllers/commentController.js"; +import authenticate from "../middlewares/authenticate.js"; +const router = express.Router(); +router.route("/").get(articleController.getArticles).post(authenticate, articleController.createArticle); + +router + .route("/:id") + .get(articleController.getArticleById) + .patch(authenticate, articleController.updateArticle) + .delete(authenticate, articleController.deleteArticle); + +router.route("/:id/like").patch(authenticate, articleController.likeArticle); + +router.route("/:id/unlike").patch(authenticate, articleController.unlikeArticle); + +router + .route("/:articleId/comments") + .get(commentController.getCommentsByProductId) + .post(authenticate, commentController.createComment); + +router + .route("/:articleId/comments/:commentId") + .patch(authenticate, commentController.updateComment) + .delete(authenticate, commentController.deleteComment); + +export default router; diff --git a/routes/articles.js b/routes/articles.js deleted file mode 100644 index 09ce4f3..0000000 --- a/routes/articles.js +++ /dev/null @@ -1,339 +0,0 @@ -import { PrismaClient } from "@prisma/client"; -import express from "express"; -import { assert } from "superstruct"; -import authenticate from "../middlewares/authenticate.js"; -import { CreateArticle, CreateComment, PatchArticle, PatchComment } from "../structs.js"; -import asyncHandler from "../utils/asyncHandler.js"; - -const prisma = new PrismaClient(); -const router = express.Router(); - -router - .route("/") - .get( - asyncHandler(async (req, res) => { - /** - * 쿼리 파라미터 - * - offset : 가져올 데이터의 시작 지점 - * - limit : 한 번에 가져올 데이터의 개수 - * - orderBy : 정렬 기준 like, recent (기본값: recent) - */ - const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; - const order = orderBy === "like" ? { likeCount: "desc" } : { createdAt: "desc" }; - const articles = await prisma.article.findMany({ - select: { - id: true, - title: true, - content: true, - imageUrl: true, - createdAt: true, - writer: true, - }, - orderBy: order, - skip: parseInt(offset), - take: parseInt(limit), - where: { - OR: [ - { - title: { - contains: keyword, - mode: "insensitive", - }, - }, - { - content: { - contains: keyword, - mode: "insensitive", - }, - }, - ], - }, - }); - // 좋아요가 많은 상위 4개의 글 조회 - const bestArticles = await prisma.article.findMany({ - orderBy: { - likeCount: "desc", - }, - take: 4, - }); - - res.send({ articles, bestArticles }); - }) - ) - .post( - authenticate, - asyncHandler(async (req, res) => { - assert(req.body, CreateArticle); - const { userId } = req; - const article = await prisma.article.create({ - data: { ...req.body, userId }, - }); - res.status(201).send(article); - }) - ); - -router - .route("/:id") - .get( - asyncHandler(async (req, res) => { - const { id } = req.params; - const article = await prisma.article.findUniqueOrThrow({ - where: { - id, - }, - select: { - id: true, - title: true, - content: true, - imageUrl: true, - createdAt: true, - likeCount: true, - writer: true, - }, - }); - res.send(article); - }) - ) - .patch( - authenticate, - asyncHandler(async (req, res) => { - assert(req.body, PatchArticle); - - const { id: articleId } = req.params; - const { userId } = req; - - const article = await prisma.article.findUniqueOrThrow({ - where: { id: articleId }, - }); - - if (article.userId !== userId) { - return res.status(403).json({ error: "게시글을 수정할 권한이 없습니다." }); - } - - const updatedArticle = await prisma.article.update({ - where: { - id: articleId, - }, - data: req.body, - }); - - res.send(updatedArticle); - }) - ) - .delete( - authenticate, - asyncHandler(async (req, res) => { - const { id: articleId } = req.params; - const { userId } = req; - - const article = await prisma.article.findUniqueOrThrow({ - where: { id: articleId }, - }); - - if (article.userId !== userId) { - return res.status(403).json({ error: "게시글을 삭제할 권한이 없습니다." }); - } - - await prisma.article.delete({ - where: { - id: articleId, - }, - }); - - res.sendStatus(204); - }) - ); - -router.patch( - "/:id/like", - authenticate, - asyncHandler(async (req, res) => { - const { id: articleId } = req.params; - const { userId } = req; - - const favorite = await prisma.favorite.findUnique({ - where: { - userId_articleId: { - userId, - articleId, - }, - }, - }); - - if (favorite) { - res.status(400).send({ message: "이미 좋아요 처리된 게시글입니다." }); - return; - } - const [createdFavorite, updatedArticle] = await prisma.$transaction([ - prisma.favorite.create({ - data: { - userId, - articleId, - }, - }), - prisma.article.update({ - where: { - id: articleId, - }, - data: { - likeCount: { - increment: 1, - }, - }, - }), - ]); - - res.send(updatedArticle); - }) -); - -router.patch( - "/:id/unlike", - authenticate, - asyncHandler(async (req, res) => { - const { id: articleId } = req.params; - const { userId } = req; - - const favorite = await prisma.favorite.findUnique({ - where: { - userId_articleId: { - userId, - articleId, - }, - }, - }); - - if (!favorite) { - res.status(400).send({ message: "아직 좋아요 처리되지 않은 게시글입니다." }); - return; - } - - const [deletedFavorite, updatedArticle] = await prisma.$transaction([ - prisma.favorite.delete({ - where: { - userId_articleId: { - userId, - articleId, - }, - }, - }), - prisma.article.update({ - where: { - id: articleId, - }, - data: { - likeCount: { - decrement: 1, - }, - }, - }), - ]); - - res.send(updatedArticle); - }) -); - -router - .route("/:id/comments") - .get( - asyncHandler(async (req, res) => { - const { id } = req.params; - const { cursor } = req.query; - let queryOptions = { - take: 10, - orderBy: { - createdAt: "desc", - }, - where: { - articleId: id, - }, - select: { - id: true, - content: true, - createdAt: true, - writer: true, - }, - }; - - if (cursor) { - queryOptions = { - ...queryOptions, - cursor: { - id: cursor, - }, - skip: 1, - }; - } - - const comments = await prisma.comment.findMany(queryOptions); - res.send(comments); - }) - ) - .post( - authenticate, - asyncHandler(async (req, res) => { - assert(req.body, CreateComment); - const { userId } = req; - const { id: articleId } = req.params; - - const comment = await prisma.comment.create({ - data: { - ...req.body, - articleId, - userId, - }, - }); - res.status(201).send(comment); - }) - ); - -router - .route("/:id/comments/:commentId") - .patch( - authenticate, - asyncHandler(async (req, res) => { - assert(req.body, PatchComment); - - const { userId } = req; - const { content } = req.body; - const { commentId } = req.params; - - const comment = await prisma.comment.findUniqueOrThrow({ - where: { id: commentId }, - }); - - if (comment.userId !== userId) { - return res.status(403).json({ error: "이 댓글을 수정할 권한이 없습니다." }); - } - - const updatedComment = await prisma.comment.update({ - where: { id: commentId }, - data: { content }, - }); - - res.send(updatedComment); - }) - ) - .delete( - authenticate, - asyncHandler(async (req, res) => { - const { commentId } = req.params; - const { userId } = req; - - const comment = await prisma.comment.findUniqueOrThrow({ - where: { id: commentId }, - }); - - if (comment.userId !== userId) { - return res.status(403).json({ error: "이 댓글을 삭제할 권한이 없습니다." }); - } - - await prisma.comment.delete({ - where: { id: commentId }, - }); - - res.sendStatus(204); - }) - ); - -export default router; diff --git a/routes/auth.js b/routes/authRoutes.js similarity index 100% rename from routes/auth.js rename to routes/authRoutes.js diff --git a/routes/images.js b/routes/imageRoutes.js similarity index 50% rename from routes/images.js rename to routes/imageRoutes.js index e3ff815..f413c71 100644 --- a/routes/images.js +++ b/routes/imageRoutes.js @@ -1,10 +1,8 @@ -import { PrismaClient } from "@prisma/client"; import express from "express"; import multer from "multer"; import path from "path"; +import * as imageController from "../controllers/imageController.js"; import authenticate from "../middlewares/authenticate.js"; -const prisma = new PrismaClient(); -const SERVER_URL = "http://localhost:3000"; const router = express.Router(); @@ -21,23 +19,6 @@ const storage = multer.diskStorage({ const upload = multer({ storage: storage }); // 이미지 업로드 -router.post("/upload", authenticate, upload.single("image"), async (req, res) => { - const file = req.file; - - if (!file) { - return res.status(400).send("이미지 파일을 선택해주세요."); - } - - const imagePath = file.path; - const imageUrl = `${SERVER_URL}/${imagePath.replace(/\\/g, "/")}`; - - const image = await prisma.image.create({ - data: { - imagePath: imagePath, - }, - }); - - res.status(200).json({ url: imageUrl }); -}); +router.post("/upload", authenticate, upload.single("image"), imageController.uploadImage); export default router; diff --git a/routes/productRoutes.js b/routes/productRoutes.js new file mode 100644 index 0000000..49386ad --- /dev/null +++ b/routes/productRoutes.js @@ -0,0 +1,28 @@ +import express from "express"; +import * as commentController from "../controllers/commentController.js"; +import * as productController from "../controllers/productController.js"; +import authenticate from "../middlewares/authenticate.js"; +const router = express.Router(); + +router.route("/").get(productController.getProducts).post(authenticate, productController.createProduct); + +router + .route("/:id") + .get(productController.getProductById) + .patch(authenticate, productController.updateProduct) + .delete(authenticate, productController.deleteProduct); + +router.route("/:id/like").patch(authenticate, productController.likeProduct); + +router.route("/:id/unlike").patch(authenticate, productController.unlikeProduct); +router + .route("/:productId/comments") + .get(commentController.getCommentsByProductId) + .post(authenticate, commentController.createComment); + +router + .route("/:productId/comments/:commentId") + .patch(authenticate, commentController.updateComment) + .delete(authenticate, commentController.deleteComment); + +export default router; diff --git a/routes/products.js b/routes/products.js deleted file mode 100644 index 9c8e011..0000000 --- a/routes/products.js +++ /dev/null @@ -1,313 +0,0 @@ -import { PrismaClient } from "@prisma/client"; -import express from "express"; -import { assert } from "superstruct"; -import authenticate from "../middlewares/authenticate.js"; -import { CreateComment, CreateProduct, PatchComment, PatchProduct } from "../structs.js"; -import asyncHandler from "../utils/asyncHandler.js"; - -const prisma = new PrismaClient(); -const router = express.Router(); -router - .route("/") - .get( - asyncHandler(async (req, res) => { - /** - * 쿼리 파라미터 - * - offset : 가져올 데이터의 시작 지점 - * - limit : 한 번에 가져올 데이터의 개수 - * - orderBy : 정렬 기준 favorite, recent (기본값: recent) - * - keyword : 검색 키워드 - */ - const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; - const order = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; - const products = await prisma.product.findMany({ - orderBy: order, - skip: parseInt(offset), - take: parseInt(limit), - where: { - OR: [ - { - name: { - contains: keyword, - mode: "insensitive", - }, - }, - { - description: { - contains: keyword, - mode: "insensitive", - }, - }, - ], - }, - }); - res.send(products); - }) - ) - .post( - authenticate, - asyncHandler(async (req, res) => { - assert(req.body, CreateProduct); - const { userId } = req; - const product = await prisma.product.create({ - data: { ...req.body, userId }, - }); - res.status(201).send(product); - }) - ); - -router - .route("/:id") - .get( - asyncHandler(async (req, res) => { - const { id } = req.params; - const product = await prisma.product.findUniqueOrThrow({ - where: { - id, - }, - }); - res.send(product); - }) - ) - .patch( - authenticate, - asyncHandler(async (req, res) => { - assert(req.body, PatchProduct); - - const { id: productId } = req.params; - const { userId } = req; - - const product = await prisma.product.findUniqueOrThrow({ - where: { id: productId }, - }); - - if (product.userId !== userId) { - return res.status(403).json({ error: "상품을 수정할 권한이 없습니다." }); - } - - const updatedProduct = await prisma.product.update({ - where: { - id: productId, - }, - data: req.body, - }); - - res.send(updatedProduct); - }) - ) - .delete( - authenticate, - asyncHandler(async (req, res) => { - const { id: productId } = req.params; - const { userId } = req; - - const product = await prisma.product.findUniqueOrThrow({ - where: { id: productId }, - }); - - if (product.userId !== userId) { - return res.status(403).json({ error: "상품을 삭제할 권한이 없습니다." }); - } - await prisma.product.delete({ - where: { - id: productId, - }, - }); - - res.sendStatus(204); - }) - ); - -router.patch( - "/:id/like", - authenticate, - asyncHandler(async (req, res) => { - const { id: productId } = req.params; - const { userId } = req; - - const favorite = await prisma.favorite.findUnique({ - where: { - userId_productId: { - userId, - productId, - }, - }, - }); - - if (favorite) { - res.status(400).send({ message: "이미 좋아요 처리된 상품입니다." }); - return; - } - - const [createdFavorite, updatedProduct] = await prisma.$transaction([ - prisma.favorite.create({ - data: { - userId, - productId, - }, - }), - prisma.product.update({ - where: { - id: productId, - }, - data: { - likeCount: { - increment: 1, - }, - }, - }), - ]); - - res.send(updatedProduct); - }) -); - -router.patch( - "/:id/unlike", - authenticate, - asyncHandler(async (req, res) => { - const { id: productId } = req.params; - const { userId } = req; - - const favorite = await prisma.favorite.findUnique({ - where: { - userId_productId: { - userId, - productId, - }, - }, - }); - - if (!favorite) { - return res.status(400).send({ message: "아직 좋아요 처리되지 않은 상품입니다." }); - } - - const [deletedFavorite, updatedProduct] = await prisma.$transaction([ - prisma.favorite.delete({ - where: { - userId_productId: { - userId, - productId, - }, - }, - }), - prisma.product.update({ - where: { - id: productId, - }, - data: { - likeCount: { - decrement: 1, - }, - }, - }), - ]); - - res.send(updatedProduct); - }) -); - -router - .route("/:id/comments") - .get( - asyncHandler(async (req, res) => { - const { id } = req.params; - const { cursor } = req.query; - let queryOptions = { - take: 10, - orderBy: { - createdAt: "desc", - }, - where: { - productId: id, - }, - select: { - id: true, - content: true, - createdAt: true, - writer: true, - }, - }; - - if (cursor) { - queryOptions = { - ...queryOptions, - cursor: { - id: cursor, - }, - skip: 1, - }; - } - - const comments = await prisma.comment.findMany(queryOptions); - res.send(comments); - }) - ) - .post( - authenticate, - asyncHandler(async (req, res) => { - assert(req.body, CreateComment); - - const { userId } = req; - const { id: productId } = req.params; - - const comment = await prisma.comment.create({ - data: { - ...req.body, - productId, - userId, - }, - }); - res.status(201).send(comment); - }) - ); - -router - .route("/:id/comments/:commentId") - .patch( - authenticate, - asyncHandler(async (req, res) => { - assert(req.body, PatchComment); - - const { userId } = req; - const { content } = req.body; - const { commentId } = req.params; - - const comment = await prisma.comment.findUniqueOrThrow({ - where: { id: commentId }, - }); - - if (comment.userId !== userId) { - return res.status(403).json({ error: "이 댓글을 수정할 권한이 없습니다." }); - } - - const updatedComment = await prisma.comment.update({ - where: { id: commentId }, - data: { content }, - }); - res.send(updatedComment); - }) - ) - .delete( - authenticate, - asyncHandler(async (req, res) => { - const { commentId } = req.params; - const { userId } = req; - - const comment = await prisma.comment.findUniqueOrThrow({ - where: { id: commentId }, - }); - - if (comment.userId !== userId) { - return res.status(403).json({ error: "이 댓글을 삭제할 권한이 없습니다." }); - } - - await prisma.comment.delete({ - where: { id: commentId }, - }); - - res.sendStatus(204); - }) - ); - -export default router; diff --git a/services/articleService.js b/services/articleService.js new file mode 100644 index 0000000..3832800 --- /dev/null +++ b/services/articleService.js @@ -0,0 +1,173 @@ +import { PrismaClient } from "@prisma/client"; + +const prisma = new PrismaClient(); + +export const getArticles = async ({ offset, limit, orderBy, keyword }) => { + const order = orderBy === "like" ? { likeCount: "desc" } : { createdAt: "desc" }; + const articles = await prisma.article.findMany({ + select: { + id: true, + title: true, + content: true, + imageUrl: true, + createdAt: true, + writer: true, + }, + orderBy: order, + skip: parseInt(offset), + take: parseInt(limit), + where: { + OR: [ + { + title: { + contains: keyword, + mode: "insensitive", + }, + }, + { + content: { + contains: keyword, + mode: "insensitive", + }, + }, + ], + }, + }); + + return articles; +}; + +export const getBestArticles = async () => { + const bestArticles = await prisma.article.findMany({ + orderBy: { + likeCount: "desc", + }, + take: 4, + }); + + return bestArticles; +}; + +export const createArticle = async (articleData) => { + return await prisma.article.create({ + data: articleData, + }); +}; + +export const getArticleById = async (id) => { + return await prisma.article.findUniqueOrThrow({ + where: { id }, + select: { + id: true, + title: true, + content: true, + imageUrl: true, + createdAt: true, + likeCount: true, + writer: true, + }, + }); +}; + +export const updateArticle = async (articleId, userId, articleData) => { + const article = await prisma.article.findUniqueOrThrow({ + where: { id: articleId }, + }); + + if (article.userId !== userId) { + throw new AppError("게시글을 수정할 권한이 없습니다.", 403); + } + + return await prisma.article.update({ + where: { id: articleId }, + data: articleData, + }); +}; + +export const deleteArticle = async (articleId, userId) => { + const article = await prisma.article.findUniqueOrThrow({ + where: { id: articleId }, + }); + + if (article.userId !== userId) { + throw new AppError("게시글을 삭제할 권한이 없습니다.", 403); + } + + await prisma.article.delete({ + where: { id: articleId }, + }); +}; + +export const likeArticle = async (articleId, userId) => { + const favorite = await prisma.favorite.findUnique({ + where: { + userId_articleId: { + userId, + articleId, + }, + }, + }); + + if (favorite) { + throw new AppError("이미 좋아요 처리된 게시글입니다.", 409); + } + + const [createdFavorite, updatedArticle] = await prisma.$transaction([ + prisma.favorite.create({ + data: { + userId, + articleId, + }, + }), + prisma.article.update({ + where: { + id: articleId, + }, + data: { + likeCount: { + increment: 1, + }, + }, + }), + ]); + + return updatedArticle; +}; + +export const unlikeArticle = async (articleId, userId) => { + const favorite = await prisma.favorite.findUnique({ + where: { + userId_articleId: { + userId, + articleId, + }, + }, + }); + + if (!favorite) { + throw new AppError("아직 좋아요 처리되지 않은 게시글입니다.", 400); + } + + const [deletedFavorite, updatedArticle] = await prisma.$transaction([ + prisma.favorite.delete({ + where: { + userId_articleId: { + userId, + articleId, + }, + }, + }), + prisma.article.update({ + where: { + id: articleId, + }, + data: { + likeCount: { + decrement: 1, + }, + }, + }), + ]); + + return updatedArticle; +}; diff --git a/services/commentService.js b/services/commentService.js new file mode 100644 index 0000000..68df378 --- /dev/null +++ b/services/commentService.js @@ -0,0 +1,106 @@ +import { PrismaClient } from "@prisma/client"; +import AppError from "../utils/errors.js"; + +const prisma = new PrismaClient(); + +export const getCommentsByProductId = async (productId, cursor) => { + let queryOptions = { + take: 10, + orderBy: { + createdAt: "desc", + }, + where: { + productId: productId, + }, + select: { + id: true, + content: true, + createdAt: true, + writer: true, + }, + }; + + if (cursor) { + queryOptions = { + ...queryOptions, + cursor: { + id: cursor, + }, + skip: 1, + }; + } + + return await prisma.comment.findMany(queryOptions); +}; + +export const getCommentsByArticleId = async (articleId, cursor) => { + let queryOptions = { + take: 10, + orderBy: { + createdAt: "desc", + }, + where: { + articleId: articleId, + }, + select: { + id: true, + content: true, + createdAt: true, + writer: true, + }, + }; + + if (cursor) { + queryOptions = { + ...queryOptions, + cursor: { + id: cursor, + }, + skip: 1, + }; + } + + return await prisma.comment.findMany(queryOptions); +}; + +export const createComment = async (commentData) => { + return await prisma.comment.create({ + data: commentData, + }); +}; + +export const updateComment = async (commentId, userId, content) => { + const comment = await prisma.comment.findUnique({ + where: { id: commentId }, + }); + + if (!comment) { + throw new AppError("존재하지 않는 댓글입니다.", 404); + } + + if (comment.userId !== userId) { + throw new AppError("이 댓글을 수정할 권한이 없습니다.", 403); + } + + return await prisma.comment.update({ + where: { id: commentId }, + data: { content }, + }); +}; + +export const deleteComment = async (commentId, userId) => { + const comment = await prisma.comment.findUnique({ + where: { id: commentId }, + }); + + if (!comment) { + throw new AppError("존재하지 않는 댓글입니다.", 404); + } + + if (comment.userId !== userId) { + throw new AppError("이 댓글을 삭제할 권한이 없습니다.", 403); + } + await prisma.comment.delete({ + where: { id: commentId }, + }); +}; diff --git a/services/imageService.js b/services/imageService.js new file mode 100644 index 0000000..0950480 --- /dev/null +++ b/services/imageService.js @@ -0,0 +1,21 @@ +import { PrismaClient } from "@prisma/client"; + +const prisma = new PrismaClient(); +const SERVER_URL = "http://localhost:3000"; + +export const uploadImage = async (file) => { + if (!file) { + throw new Error("이미지 파일을 선택해주세요."); + } + + const imagePath = file.path; + const imageUrl = `${SERVER_URL}/${imagePath.replace(/\\/g, "/")}`; + + const image = await prisma.image.create({ + data: { + imagePath: imagePath, + }, + }); + + return imageUrl; +}; diff --git a/services/productService.js b/services/productService.js new file mode 100644 index 0000000..e8a3b7a --- /dev/null +++ b/services/productService.js @@ -0,0 +1,156 @@ +import { PrismaClient } from "@prisma/client"; +import AppError from "../utils/errors.js"; +const prisma = new PrismaClient(); + +export const getProducts = async ({ offset, limit, orderBy, keyword }) => { + const order = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; + return await prisma.product.findMany({ + orderBy: order, + skip: parseInt(offset), + take: parseInt(limit), + where: { + OR: [ + { + name: { + contains: keyword, + mode: "insensitive", + }, + }, + { + description: { + contains: keyword, + mode: "insensitive", + }, + }, + ], + }, + }); +}; + +export const createProduct = async (productData) => { + return await prisma.product.create({ + data: productData, + }); +}; + +export const getProductById = async (id) => { + const product = await prisma.product.findUnique({ + where: { id }, + }); + + if (!product) { + throw new AppError("존재하지 않는 상품입니다.", 404); + } + return product; +}; + +export const updateProduct = async (productId, userId, productData) => { + const product = await prisma.product.findUnique({ + where: { id: productId }, + }); + + if (!product) { + throw new AppError("존재하지 않는 상품입니다.", 404); + } + + if (product.userId !== userId) { + throw new AppError("상품을 수정할 권한이 없습니다.", 403); + } + + return await prisma.product.update({ + where: { id: productId }, + data: productData, + }); +}; + +export const deleteProduct = async (productId, userId) => { + const product = await prisma.product.findUnique({ + where: { id: productId }, + }); + + if (!product) { + throw new AppError("존재하지 않는 상품입니다.", 404); + } + + if (product.userId !== userId) { + throw new AppError("상품을 삭제할 권한이 없습니다.", 403); + } + + await prisma.product.delete({ + where: { id: productId }, + }); +}; + +export const likeProduct = async (productId, userId) => { + const favorite = await prisma.favorite.findUnique({ + where: { + userId_productId: { + userId, + productId, + }, + }, + }); + + if (favorite) { + throw AppError("이미 좋아요 처리된 상품입니다.", 409); + } + + const [createdFavorite, updatedProduct] = await prisma.$transaction([ + prisma.favorite.create({ + data: { + userId, + productId, + }, + }), + prisma.product.update({ + where: { + id: productId, + }, + data: { + favoriteCount: { + increment: 1, + }, + }, + }), + ]); + + return updatedProduct; +}; + +export const unlikeProduct = async (productId, userId) => { + const favorite = await prisma.favorite.findUnique({ + where: { + userId_productId: { + userId, + productId, + }, + }, + }); + + if (!favorite) { + throw AppError("아직 좋아요 처리되지 않은 상품입니다.", 409); + } + + const [deletedFavorite, updatedProduct] = await prisma.$transaction([ + prisma.favorite.delete({ + where: { + userId_productId: { + userId, + productId, + }, + }, + }), + prisma.product.update({ + where: { + id: productId, + }, + data: { + favoriteCount: { + decrement: 1, + }, + }, + }), + ]); + + return updatedProduct; +}; diff --git a/test.html b/test.html index 55b802b..4e32f08 100644 --- a/test.html +++ b/test.html @@ -4,14 +4,43 @@ - Document + Upload Image -
+ - +
+ + \ No newline at end of file diff --git a/utils/errors.js b/utils/errors.js new file mode 100644 index 0000000..c3a6992 --- /dev/null +++ b/utils/errors.js @@ -0,0 +1,12 @@ +class AppError extends Error { + constructor(message, statusCode) { + super(message); + this.statusCode = statusCode; + this.status = `${statusCode}`.startsWith("4") ? "fail" : "error"; + this.isOperational = true; + + Error.captureStackTrace(this, this.constructor); + } +} + +export default AppError; From 520f7512d61ea556fe7527f610191faf95928790 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Tue, 28 May 2024 15:55:48 +0900 Subject: [PATCH 35/60] =?UTF-8?q?[#M10]=20feat:=20=EA=B5=AC=EA=B8=80=20OAu?= =?UTF-8?q?th=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=EB=B0=8F=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 구글 OAuth 로그인 후 JWT 토큰 생성 구현 - 유저 기능에 MVC 패턴 적용 --- app.js | 5 + config/passport.js | 59 ++++++++ controllers/authController.js | 74 ++++++++++ middlewares/errorHandler.js | 6 +- package-lock.json | 136 ++++++++++++++++++ package.json | 3 + .../migration.sql | 11 ++ .../migration.sql | 2 + prisma/schema.prisma | 3 +- routes/authRoutes.js | 99 ++----------- services/authService.js | 32 +++++ 11 files changed, 338 insertions(+), 92 deletions(-) create mode 100644 config/passport.js create mode 100644 controllers/authController.js create mode 100644 prisma/migrations/20240528063148_add_google_auth/migration.sql create mode 100644 prisma/migrations/20240528063710_make_password_optional/migration.sql create mode 100644 services/authService.js diff --git a/app.js b/app.js index 4232adc..47c0734 100644 --- a/app.js +++ b/app.js @@ -1,10 +1,12 @@ import cors from "cors"; import express from "express"; +import session from "express-session"; import fs from "fs"; import moment from "moment-timezone"; import morgan from "morgan"; import path, { dirname } from "path"; import { fileURLToPath } from "url"; +import passport from "./config/passport.js"; import errorHandler from "./middlewares/errorHandler.js"; import articlesRouter from "./routes/articleRoutes.js"; import authRouter from "./routes/authRoutes.js"; @@ -27,6 +29,9 @@ app.use(morgan(customFormat, { stream: accessLogStream })); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(cors()); +app.use(session({ secret: "secret", resave: false, saveUninitialized: true })); +app.use(passport.initialize()); +app.use(passport.session()); app.use("/products", productsRouter); app.use("/articles", articlesRouter); diff --git a/config/passport.js b/config/passport.js new file mode 100644 index 0000000..6a14c18 --- /dev/null +++ b/config/passport.js @@ -0,0 +1,59 @@ +import { PrismaClient } from "@prisma/client"; +import dotenv from "dotenv"; +import passport from "passport"; +import { Strategy as GoogleStrategy } from "passport-google-oauth20"; +import { generateAccessToken, generateRefreshToken } from "../utils/tokens.js"; + +dotenv.config(); +const prisma = new PrismaClient(); + +const GOOGLE_CLIENT_ID = process.env.GOOGLE_CLIENT_ID; +const GOOGLE_CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET; + +passport.use( + new GoogleStrategy( + { + clientID: GOOGLE_CLIENT_ID, + clientSecret: GOOGLE_CLIENT_SECRET, + callbackURL: "http://localhost:3000/auth/google/callback", + }, + async (accessToken, refreshToken, profile, done) => { + const { id, displayName, emails } = profile; + + try { + let user = await prisma.user.findUnique({ + where: { googleId: id }, + }); + + if (!user) { + user = await prisma.user.create({ + data: { + googleId: id, + email: emails[0].value, + name: displayName, + nickname: displayName, + password: null, + }, + }); + } + + const accessTokenJwt = generateAccessToken(user); + const refreshTokenJwt = generateRefreshToken(user); + + done(null, { user, accessToken: accessTokenJwt, refreshToken: refreshTokenJwt }); + } catch (error) { + done(error, null); + } + } + ) +); + +passport.serializeUser((userWithTokens, done) => { + done(null, userWithTokens); +}); + +passport.deserializeUser((userWithTokens, done) => { + done(null, userWithTokens); +}); + +export default passport; diff --git a/controllers/authController.js b/controllers/authController.js new file mode 100644 index 0000000..accb542 --- /dev/null +++ b/controllers/authController.js @@ -0,0 +1,74 @@ +import dotenv from "dotenv"; +import jwt from "jsonwebtoken"; +import { assert } from "superstruct"; +import { createUser, findUserByEmail, findUserById, validatePassword } from "../services/authService.js"; +import { CreateUser } from "../structs.js"; +import { generateAccessToken, generateRefreshToken, regenerateRefreshToken } from "../utils/tokens.js"; + +dotenv.config(); +const JWT_SECRET = process.env.JWT_SECRET; + +export const signUp = async (req, res) => { + const { email, password, name, nickname } = req.body; + assert(req.body, CreateUser); + + const existingUser = await findUserByEmail(email); + + if (existingUser) { + return res.status(400).json({ message: "이미 가입된 이메일입니다." }); + } + + await createUser(email, password, name, nickname); + + res.status(201).json({ message: "회원가입이 완료되었습니다." }); +}; + +export const signIn = async (req, res) => { + const { email, password } = req.body; + + const user = await findUserByEmail(email); + + if (!user) { + return res.status(401).json({ message: "이메일과 비밀번호를 확인해주세요." }); + } + + const isPasswordValid = await validatePassword(password, user.password); + + if (!isPasswordValid) { + return res.status(401).json({ message: "이메일과 비밀번호를 확인해주세요." }); + } + + const accessToken = generateAccessToken(user); + const refreshToken = generateRefreshToken(user); + + res.json({ accessToken, refreshToken }); +}; + +export const refreshToken = async (req, res) => { + const { refreshToken } = req.body; + + if (!refreshToken) { + return res.status(401).json({ message: "토큰은 필수값입니다." }); + } + + try { + const newRefreshToken = regenerateRefreshToken(refreshToken); + const decoded = jwt.verify(newRefreshToken, JWT_SECRET); + const user = await findUserById(decoded.userId); + + if (!user) { + return res.status(401).json({ message: "유효하지 않은 토큰입니다." }); + } + + const accessToken = generateAccessToken(user); + + res.json({ accessToken, refreshToken: newRefreshToken }); + } catch (error) { + return res.status(401).json({ message: "유효하지 않은 토큰입니다." }); + } +}; + +export const googleCallback = (req, res) => { + const { accessToken, refreshToken } = req.user; + res.json({ accessToken, refreshToken }); +}; diff --git a/middlewares/errorHandler.js b/middlewares/errorHandler.js index e042938..c01422f 100644 --- a/middlewares/errorHandler.js +++ b/middlewares/errorHandler.js @@ -1,8 +1,8 @@ import AppError from "../utils/errors.js"; -const errorHandler = (err, req, res) => { - console.error(err.stack); - +const errorHandler = (err, req, res, next) => { + console.error("Error handler triggered:", err.stack); + console.log("Response object:", res); if (err instanceof AppError) { res.status(err.statusCode).json({ status: err.status, diff --git a/package-lock.json b/package-lock.json index 880fe62..49a7618 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,12 +10,15 @@ "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", + "express-session": "^1.18.0", "is-email": "^1.0.2", "is-uuid": "^1.0.2", "jsonwebtoken": "^9.0.2", "moment-timezone": "^0.5.45", "morgan": "^1.10.0", "multer": "^1.4.5-lts.1", + "passport": "^0.7.0", + "passport-google-oauth20": "^2.0.0", "prisma": "^5.4.2", "superstruct": "^1.0.3" }, @@ -194,6 +197,14 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -629,6 +640,42 @@ "node": ">= 0.10.0" } }, + "node_modules/express-session": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz", + "integrity": "sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ==", + "dependencies": { + "cookie": "0.6.0", + "cookie-signature": "1.0.7", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" + }, + "node_modules/express-session/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express-session/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1404,6 +1451,11 @@ "set-blocking": "^2.0.0" } }, + "node_modules/oauth": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.10.0.tgz", + "integrity": "sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q==" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -1455,6 +1507,61 @@ "node": ">= 0.8" } }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-google-oauth20": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", + "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", + "dependencies": { + "passport-oauth2": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-oauth2": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.8.0.tgz", + "integrity": "sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA==", + "dependencies": { + "base64url": "3.x.x", + "oauth": "0.10.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -1468,6 +1575,11 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -1532,6 +1644,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -1896,6 +2016,22 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", diff --git a/package.json b/package.json index 7334f69..316134b 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,15 @@ "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", + "express-session": "^1.18.0", "is-email": "^1.0.2", "is-uuid": "^1.0.2", "jsonwebtoken": "^9.0.2", "moment-timezone": "^0.5.45", "morgan": "^1.10.0", "multer": "^1.4.5-lts.1", + "passport": "^0.7.0", + "passport-google-oauth20": "^2.0.0", "prisma": "^5.4.2", "superstruct": "^1.0.3" }, diff --git a/prisma/migrations/20240528063148_add_google_auth/migration.sql b/prisma/migrations/20240528063148_add_google_auth/migration.sql new file mode 100644 index 0000000..88eb841 --- /dev/null +++ b/prisma/migrations/20240528063148_add_google_auth/migration.sql @@ -0,0 +1,11 @@ +/* + Warnings: + + - A unique constraint covering the columns `[googleId]` on the table `User` will be added. If there are existing duplicate values, this will fail. + +*/ +-- AlterTable +ALTER TABLE "User" ADD COLUMN "googleId" TEXT; + +-- CreateIndex +CREATE UNIQUE INDEX "User_googleId_key" ON "User"("googleId"); diff --git a/prisma/migrations/20240528063710_make_password_optional/migration.sql b/prisma/migrations/20240528063710_make_password_optional/migration.sql new file mode 100644 index 0000000..0b600a7 --- /dev/null +++ b/prisma/migrations/20240528063710_make_password_optional/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "User" ALTER COLUMN "password" DROP NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 3c3d127..3915113 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -14,11 +14,12 @@ datasource db { model User { id Int @id @default(autoincrement()) + googleId String? @unique email String @unique name String? nickname String image String? - password String + password String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt products Product[] diff --git a/routes/authRoutes.js b/routes/authRoutes.js index 6152f5f..78ed954 100644 --- a/routes/authRoutes.js +++ b/routes/authRoutes.js @@ -1,97 +1,20 @@ -import { PrismaClient } from "@prisma/client"; -import bcrypt from "bcrypt"; -import dotenv from "dotenv"; import express from "express"; -import jwt from "jsonwebtoken"; -import { assert } from "superstruct"; -import { CreateUser } from "../structs.js"; +import passport from "../config/passport.js"; +import { googleCallback, refreshToken, signIn, signUp } from "../controllers/authController.js"; import asyncHandler from "../utils/asyncHandler.js"; -import { generateAccessToken, generateRefreshToken, regenerateRefreshToken } from "../utils/tokens.js"; -dotenv.config(); const router = express.Router(); -const prisma = new PrismaClient(); -const JWT_SECRET = process.env.JWT_SECRET; +router.post("/signUp", asyncHandler(signUp)); +router.post("/signIn", asyncHandler(signIn)); +router.post("/refresh-token", asyncHandler(refreshToken)); -// 회원가입 -router.post( - "/signUp", - asyncHandler(async (req, res) => { - const { email, password, name, nickname } = req.body; - assert(req.body, CreateUser); - const hashedPassword = await bcrypt.hash(password, 10); - const existingUser = await prisma.user.findUnique({ - where: { email }, - }); +router.get("/google", passport.authenticate("google", { scope: ["profile", "email"] })); +router.get("/google/callback", passport.authenticate("google", { failureRedirect: "/" }), googleCallback); - if (existingUser) { - return res.status(400).json({ message: "이미 가입된 이메일입니다." }); - } - - await prisma.user.create({ - data: { - email, - password: hashedPassword, - name, - nickname, - }, - }); - - res.status(201).json({ message: "회원가입이 완료되었습니다." }); - }) -); -// 사용자 로그인 -router.post( - "/signIn", - asyncHandler(async (req, res) => { - const { email, password } = req.body; - - const user = await prisma.user.findUnique({ - where: { email }, - }); - - if (!user) { - return res.status(401).json({ message: "이메일과 비밀번호를 확인해주세요." }); - } - - const isPasswordValid = await bcrypt.compare(password, user.password); - - if (!isPasswordValid) { - return res.status(401).json({ message: "이메일과 비밀번호를 확인해주세요." }); - } - - const accessToken = generateAccessToken(user); - const refreshToken = generateRefreshToken(user); - - res.json({ accessToken, refreshToken }); - }) -); -router.post( - "/refresh-token", - asyncHandler(async (req, res) => { - const { refreshToken } = req.body; - - if (!refreshToken) { - return res.status(401).json({ message: "토큰은 필수값입니다." }); - } - - try { - const newRefreshToken = regenerateRefreshToken(refreshToken); - const decoded = jwt.verify(newRefreshToken, JWT_SECRET); - const user = await prisma.user.findUnique({ where: { id: decoded.userId } }); - - if (!user) { - return res.status(401).json({ message: "유효하지 않은 토큰입니다." }); - } - - const accessToken = generateAccessToken(user); - - res.json({ accessToken, refreshToken: newRefreshToken }); - } catch (error) { - return res.status(401).json({ message: "유효하지 않은 토큰입니다." }); - } - }) -); +router.get("/logout", (req, res) => { + req.logout(); + res.redirect("/"); +}); export default router; diff --git a/services/authService.js b/services/authService.js new file mode 100644 index 0000000..f736007 --- /dev/null +++ b/services/authService.js @@ -0,0 +1,32 @@ +import { PrismaClient } from "@prisma/client"; +import bcrypt from "bcrypt"; + +const prisma = new PrismaClient(); + +export const createUser = async (email, password, name, nickname) => { + const hashedPassword = await bcrypt.hash(password, 10); + return prisma.user.create({ + data: { + email, + password: hashedPassword, + name, + nickname, + }, + }); +}; + +export const findUserByEmail = async (email) => { + return prisma.user.findUnique({ + where: { email }, + }); +}; + +export const findUserById = async (id) => { + return prisma.user.findUnique({ + where: { id }, + }); +}; + +export const validatePassword = async (inputPassword, storedPassword) => { + return bcrypt.compare(inputPassword, storedPassword); +}; From acec3d653c7850f20ca8d886acadda705993219a Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Wed, 29 May 2024 07:54:18 +0900 Subject: [PATCH 36/60] =?UTF-8?q?[#M10]=20feat:=20Swagger=20API=20?= =?UTF-8?q?=EB=AA=85=EC=84=B8=EC=84=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 12 +- http/articles.http | 2 +- http/auth.http | 2 +- middlewares/authenticate.js | 2 +- package-lock.json | 236 +++++++++- package.json | 4 +- routes/articleRoutes.js | 900 +++++++++++++++++++++++++++++++++++- routes/authRoutes.js | 203 ++++++++ routes/imageRoutes.js | 48 +- routes/productRoutes.js | 829 +++++++++++++++++++++++++++++++++ services/articleService.js | 2 +- swagger/swaggerOptions.js | 42 ++ 12 files changed, 2273 insertions(+), 9 deletions(-) create mode 100644 swagger/swaggerOptions.js diff --git a/app.js b/app.js index 47c0734..44513bb 100644 --- a/app.js +++ b/app.js @@ -1,10 +1,13 @@ import cors from "cors"; +import dotenv from "dotenv"; import express from "express"; import session from "express-session"; import fs from "fs"; import moment from "moment-timezone"; import morgan from "morgan"; import path, { dirname } from "path"; +import swaggerJsdoc from "swagger-jsdoc"; +import swaggerUi from "swagger-ui-express"; import { fileURLToPath } from "url"; import passport from "./config/passport.js"; import errorHandler from "./middlewares/errorHandler.js"; @@ -12,11 +15,18 @@ import articlesRouter from "./routes/articleRoutes.js"; import authRouter from "./routes/authRoutes.js"; import imagesRouter from "./routes/imageRoutes.js"; import productsRouter from "./routes/productRoutes.js"; +import swaggerOptions from "./swagger/swaggerOptions.js"; +dotenv.config(); +const { JWT_SECRET } = process.env; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const app = express(); +const specs = swaggerJsdoc(swaggerOptions); + +app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(specs)); + morgan.token("date", (req, res, tz) => { return moment().tz(tz).format("YYYY-MM-DD HH:mm:ss"); }); @@ -29,7 +39,7 @@ app.use(morgan(customFormat, { stream: accessLogStream })); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(cors()); -app.use(session({ secret: "secret", resave: false, saveUninitialized: true })); +app.use(session({ secret: JWT_SECRET, resave: false, saveUninitialized: true })); app.use(passport.initialize()); app.use(passport.session()); diff --git a/http/articles.http b/http/articles.http index 99e2a4a..510a021 100644 --- a/http/articles.http +++ b/http/articles.http @@ -9,7 +9,7 @@ GET http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da ### # 게시글 등록 POST http://localhost:3000/articles -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg4MjIxMCwiZXhwIjoxNzE2ODgzMTEwfQ.HKPt_52tCohwFBk5yESkDiChtWpqd7pf531uQsI47kY Content-Type: application/json { diff --git a/http/auth.http b/http/auth.http index 4868f2e..aeaf407 100644 --- a/http/auth.http +++ b/http/auth.http @@ -2,7 +2,7 @@ POST http://localhost:3000/auth/signUp Content-Type: application/json { - "email":"test5@gmail.com", + "email":"test52@gmail.com", "password":"pandapower", "name":"김판다", "nickname":"판다의 왕" diff --git a/middlewares/authenticate.js b/middlewares/authenticate.js index f891647..cb54af3 100644 --- a/middlewares/authenticate.js +++ b/middlewares/authenticate.js @@ -8,7 +8,7 @@ const JWT_SECRET = process.env.JWT_SECRET; const authenticate = (req, res, next) => { const authHeader = req.headers.authorization; if (!authHeader) { - return res.status(401).json({ message: "No token provided" }); + return res.status(401).json({ message: "인증 토큰이 제공되지 않았습니다." }); } const token = authHeader.split(" ")[1]; diff --git a/package-lock.json b/package-lock.json index 49a7618..4efa6b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,12 +20,59 @@ "passport": "^0.7.0", "passport-google-oauth20": "^2.0.0", "prisma": "^5.4.2", - "superstruct": "^1.0.3" + "superstruct": "^1.0.3", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.0" }, "devDependencies": { "nodemon": "^3.0.1" } }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", + "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "node_modules/@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==" + }, + "node_modules/@apidevtools/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^9.0.6", + "@apidevtools/openapi-schemas": "^2.0.4", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "call-me-maybe": "^1.0.1", + "z-schema": "^5.0.1" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" + }, "node_modules/@mapbox/node-pre-gyp": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", @@ -102,6 +149,11 @@ "@prisma/debug": "5.14.0" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -187,6 +239,11 @@ "node": ">= 6" } }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -350,6 +407,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -390,6 +452,14 @@ "color-support": "bin.js" } }, + "node_modules/commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "engines": { + "node": ">= 6" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -530,6 +600,17 @@ "node": ">=8" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dotenv": { "version": "16.4.5", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", @@ -591,6 +672,14 @@ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -1067,6 +1156,17 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/jsonwebtoken": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", @@ -1107,6 +1207,11 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" + }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -1117,6 +1222,11 @@ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, "node_modules/lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", @@ -1137,6 +1247,11 @@ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==" + }, "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -1499,6 +1614,12 @@ "wrappy": "1" } }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "peer": true + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -1938,6 +2059,75 @@ "node": ">=4" } }, + "node_modules/swagger-jsdoc": { + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", + "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", + "dependencies": { + "commander": "6.2.0", + "doctrine": "3.0.0", + "glob": "7.1.6", + "lodash.mergewith": "^4.6.2", + "swagger-parser": "^10.0.3", + "yaml": "2.0.0-1" + }, + "bin": { + "swagger-jsdoc": "bin/swagger-jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/swagger-jsdoc/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", + "dependencies": { + "@apidevtools/swagger-parser": "10.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/swagger-ui-dist": { + "version": "5.17.14", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz", + "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==" + }, + "node_modules/swagger-ui-express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz", + "integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==", + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -2059,6 +2249,14 @@ "node": ">= 0.4.0" } }, + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -2106,6 +2304,42 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yaml": { + "version": "2.0.0-1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", + "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/z-schema": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", + "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "commander": "^9.4.1" + } + }, + "node_modules/z-schema/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "optional": true, + "engines": { + "node": "^12.20.0 || >=14" + } } } } diff --git a/package.json b/package.json index 316134b..fad07ce 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,9 @@ "passport": "^0.7.0", "passport-google-oauth20": "^2.0.0", "prisma": "^5.4.2", - "superstruct": "^1.0.3" + "superstruct": "^1.0.3", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.0" }, "devDependencies": { "nodemon": "^3.0.1" diff --git a/routes/articleRoutes.js b/routes/articleRoutes.js index bfba509..c2d9e4d 100644 --- a/routes/articleRoutes.js +++ b/routes/articleRoutes.js @@ -3,23 +3,921 @@ import * as articleController from "../controllers/articleController.js"; import * as commentController from "../controllers/commentController.js"; import authenticate from "../middlewares/authenticate.js"; const router = express.Router(); -router.route("/").get(articleController.getArticles).post(authenticate, articleController.createArticle); +/** + * @swagger + * tags: + * name: Articles + * description: 자유게시판 + */ + +/** + * @swagger + * /articles: + * get: + * summary: 게시글 목록 조회 + * tags: [Articles] + * parameters: + * - in: query + * name: offset + * schema: + * type: integer + * example: 0 + * description: 가져올 데이터의 시작 지점 + * - in: query + * name: limit + * schema: + * type: integer + * example: 10 + * description: 한 번에 가져올 데이터의 개수 + * - in: query + * name: orderBy + * schema: + * type: string + * enum: [like, recent] + * example: recent + * description: 정렬 기준 + * - in: query + * name: keyword + * schema: + * type: string + * example: "게시글 제목" + * description: 검색 키워드 + * responses: + * 200: + * description: 게시글 목록 조회 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * articles: + * type: array + * items: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * title: + * type: string + * example: "게시글 제목" + * content: + * type: string + * example: "게시글 내용" + * imageUrl: + * type: string + * example: "http://example.com/image.jpg" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * likeCount: + * type: number + * example: 5 + * writer: + * type: string + * example: "작성자" + * bestArticles: + * type: array + * items: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * title: + * type: string + * example: "인기 게시글 제목" + * content: + * type: string + * example: "인기 게시글 내용" + * imageUrl: + * type: string + * example: "http://example.com/image.jpg" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * likeCount: + * type: number + * example: 10 + * writer: + * type: string + * example: "작성자" + * examples: + * application/json: + * value: + * articles: + * - id: "550e8400-e29b-41d4-a716-446655440000" + * title: "게시글 제목" + * content: "게시글 내용" + * imageUrl: "http://example.com/image.jpg" + * createdAt: "2023-01-01T00:00:00.000Z" + * likeCount: 5 + * writer: "작성자" + * bestArticles: + * - id: "550e8400-e29b-41d4-a716-446655440000" + * title: "인기 게시글 제목" + * content: "인기 게시글 내용" + * imageUrl: "http://example.com/image.jpg" + * createdAt: "2023-01-01T00:00:00.000Z" + * likeCount: 10 + * writer: "작성자" + * post: + * summary: 게시글 생성 + * tags: [Articles] + * security: + * - bearerAuth: [] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * title: + * type: string + * example: "게시글 제목" + * content: + * type: string + * example: "게시글 내용" + * imageUrl: + * type: string + * example: "http://example.com/image.jpg" + * responses: + * 201: + * description: 게시글 생성 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * title: + * type: string + * example: "게시글 제목" + * content: + * type: string + * example: "게시글 내용" + * imageUrl: + * type: string + * example: "http://example.com/image.jpg" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * likeCount: + * type: number + * example: 0 + * writer: + * type: string + * example: "작성자" + * examples: + * application/json: + * value: + * id: "550e8400-e29b-41d4-a716-446655440000" + * title: "게시글 제목" + * content: "게시글 내용" + * imageUrl: "http://example.com/image.jpg" + * createdAt: "2023-01-01T00:00:00.000Z" + * likeCount: 0 + * writer: "작성자" + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * + */ +router.route("/").get(articleController.getArticles).post(authenticate, articleController.createArticle); +/** + * @swagger + * /articles/{id}: + * get: + * summary: 특정 게시글 조회 + * tags: [Articles] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * responses: + * 200: + * description: 게시글 조회 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * title: + * type: string + * example: "게시글 제목" + * content: + * type: string + * example: "게시글 내용" + * imageUrl: + * type: string + * example: "http://example.com/image.jpg" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * likeCount: + * type: number + * example: 5 + * writer: + * type: string + * example: "작성자" + * examples: + * application/json: + * value: + * id: "550e8400-e29b-41d4-a716-446655440000" + * title: "게시글 제목" + * content: "게시글 내용" + * imageUrl: "http://example.com/image.jpg" + * createdAt: "2023-01-01T00:00:00.000Z" + * likeCount: 5 + * writer: "작성자" + * 404: + * description: 게시글을 찾을 수 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "존재하지 않는 게시글입니다." + * patch: + * summary: 게시글 수정 + * tags: [Articles] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * title: + * type: string + * example: "게시글 제목" + * content: + * type: string + * example: "게시글 내용" + * imageUrl: + * type: string + * example: "http://example.com/image.jpg" + * responses: + * 200: + * description: 게시글 수정 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * title: + * type: string + * example: "게시글 제목" + * content: + * type: string + * example: "게시글 내용" + * imageUrl: + * type: string + * example: "http://example.com/image.jpg" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * likeCount: + * type: number + * example: 5 + * writer: + * type: string + * example: "작성자" + * examples: + * application/json: + * value: + * id: "550e8400-e29b-41d4-a716-446655440000" + * title: "게시글 제목" + * content: "게시글 내용" + * imageUrl: "http://example.com/image.jpg" + * createdAt: "2023-01-01T00:00:00.000Z" + * likeCount: 5 + * writer: "작성자" + * 400: + * description: 유효성 검사 오류 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "유효성 검사 오류입니다." + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * 403: + * description: 권한 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "게시글을 수정할 권한이 없습니다." + * 404: + * description: 게시글을 찾을 수 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "존재하지 않는 게시글입니다." + * delete: + * summary: 게시글 삭제 + * tags: [Articles] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * responses: + * 204: + * description: 게시글 삭제 성공 + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * 403: + * description: 권한 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "게시글을 삭제할 권한이 없습니다." + * 404: + * description: 게시글을 찾을 수 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "존재하지 않는 게시글입니다." + */ router .route("/:id") .get(articleController.getArticleById) .patch(authenticate, articleController.updateArticle) .delete(authenticate, articleController.deleteArticle); +/** + * @swagger + * /articles/{id}/like: + * patch: + * summary: 게시글 좋아요 + * tags: [Articles] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * responses: + * 200: + * description: 게시글 좋아요 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * title: + * type: string + * example: "게시글 제목" + * content: + * type: string + * example: "게시글 내용" + * imageUrl: + * type: string + * example: "http://example.com/image.jpg" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * likeCount: + * type: number + * example: 6 + * writer: + * type: string + * example: "작성자" + * examples: + * application/json: + * value: + * id: "550e8400-e29b-41d4-a716-446655440000" + * title: "게시글 제목" + * content: "게시글 내용" + * imageUrl: "http://example.com/image.jpg" + * createdAt: "2023-01-01T00:00:00.000Z" + * likeCount: 6 + * writer: "작성자" + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * 409: + * description: 이미 좋아요 처리된 게시글 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "이미 좋아요 처리된 게시글입니다." + */ router.route("/:id/like").patch(authenticate, articleController.likeArticle); +/** + * @swagger + * /articles/{id}/unlike: + * patch: + * summary: 게시글 좋아요 취소 + * tags: [Articles] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * responses: + * 200: + * description: 게시글 좋아요 취소 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * title: + * type: string + * example: "게시글 제목" + * content: + * type: string + * example: "게시글 내용" + * imageUrl: + * type: string + * example: "http://example.com/image.jpg" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * likeCount: + * type: number + * example: 4 + * writer: + * type: string + * example: "작성자" + * examples: + * application/json: + * value: + * id: "550e8400-e29b-41d4-a716-446655440000" + * title: "게시글 제목" + * content: "게시글 내용" + * imageUrl: "http://example.com/image.jpg" + * createdAt: "2023-01-01T00:00:00.000Z" + * likeCount: 4 + * writer: "작성자" + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * 409: + * description: 아직 좋아요 처리되지 않은 게시글 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "아직 좋아요 처리되지 않은 게시글입니다." + */ router.route("/:id/unlike").patch(authenticate, articleController.unlikeArticle); +/** + * @swagger + * /articles/{articleId}/comments: + * get: + * summary: 특정 게시글의 댓글 목록 조회 + * tags: [Comments] + * parameters: + * - in: path + * name: articleId + * required: true + * schema: + * type: string + * responses: + * 200: + * description: 댓글 목록 조회 성공 + * content: + * application/json: + * schema: + * type: array + * items: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * content: + * type: string + * example: "댓글 내용" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * writer: + * type: string + * example: "작성자" + * examples: + * application/json: + * value: + * - id: "550e8400-e29b-41d4-a716-446655440000" + * content: "댓글 내용" + * createdAt: "2023-01-01T00:00:00.000Z" + * writer: "작성자" + * 404: + * description: 게시글을 찾을 수 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "존재하지 않는 게시글입니다." + * post: + * summary: 댓글 작성 + * tags: [Comments] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: articleId + * required: true + * schema: + * type: string + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * content: + * type: string + * example: "댓글 내용" + * responses: + * 201: + * description: 댓글 작성 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * content: + * type: string + * example: "댓글 내용" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * writer: + * type: string + * example: "작성자" + * examples: + * application/json: + * value: + * id: "550e8400-e29b-41d4-a716-446655440000" + * content: "댓글 내용" + * createdAt: "2023-01-01T00:00:00.000Z" + * writer: "작성자" + * 400: + * description: 유효성 검사 오류 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "유효성 검사 오류입니다." + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * 404: + * description: 게시글을 찾을 수 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "존재하지 않는 게시글입니다." + */ + +/** + * @swagger + * tags: + * name: Comments + * description: 댓글 + */ + router .route("/:articleId/comments") .get(commentController.getCommentsByProductId) .post(authenticate, commentController.createComment); +/** + * @swagger + * /articles/{articleId}/comments/{commentId}: + * patch: + * summary: 댓글 수정 + * tags: [Comments] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: articleId + * required: true + * schema: + * type: string + * - in: path + * name: commentId + * required: true + * schema: + * type: string + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * content: + * type: string + * example: "댓글 내용" + * responses: + * 200: + * description: 댓글 수정 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * content: + * type: string + * example: "댓글 내용" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * writer: + * type: string + * example: "작성자" + * examples: + * application/json: + * value: + * id: "550e8400-e29b-41d4-a716-446655440000" + * content: "댓글 내용" + * createdAt: "2023-01-01T00:00:00.000Z" + * writer: "작성자" + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * 403: + * description: 권한 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "이 댓글을 수정할 권한이 없습니다." + * 404: + * description: 댓글을 찾을 수 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "존재하지 않는 댓글입니다." + * delete: + * summary: 댓글 삭제 + * tags: [Comments] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: articleId + * required: true + * schema: + * type: string + * - in: path + * name: commentId + * required: true + * schema: + * type: string + * responses: + * 204: + * description: 댓글 삭제 성공 + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * 403: + * description: 권한 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "이 댓글을 삭제할 권한이 없습니다." + * 404: + * description: 댓글을 찾을 수 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "존재하지 않는 댓글입니다." + */ router .route("/:articleId/comments/:commentId") .patch(authenticate, commentController.updateComment) diff --git a/routes/authRoutes.js b/routes/authRoutes.js index 78ed954..0a598a6 100644 --- a/routes/authRoutes.js +++ b/routes/authRoutes.js @@ -5,13 +5,216 @@ import asyncHandler from "../utils/asyncHandler.js"; const router = express.Router(); +/** + * @swagger + * tags: + * name: Auth + * description: 사용자 인증 + */ + +/** + * @swagger + * /auth/signUp: + * post: + * summary: 사용자 회원가입 + * tags: [Auth] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - email + * - password + * - name + * - nickname + * properties: + * email: + * type: string + * example: "pandaking@example.com" + * password: + * type: string + * example: "password123" + * name: + * type: string + * example: "김판다" + * nickname: + * type: string + * example: "판다의 왕" + * responses: + * 201: + * description: 회원가입이 완료되었습니다. + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "회원가입이 완료되었습니다." + * 400: + * description: 이미 가입된 이메일입니다. + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "이미 가입된 이메일입니다." + */ router.post("/signUp", asyncHandler(signUp)); + +/** + * @swagger + * /auth/signIn: + * post: + * summary: 사용자 로그인 + * tags: [Auth] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - email + * - password + * properties: + * email: + * type: string + * example: "user@example.com" + * password: + * type: string + * example: "password123" + * responses: + * 200: + * description: 로그인 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * accessToken: + * type: string + * example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." + * refreshToken: + * type: string + * example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." + * 401: + * description: 이메일과 비밀번호를 확인해주세요. + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "이메일과 비밀번호를 확인해주세요." + */ router.post("/signIn", asyncHandler(signIn)); + +/** + * @swagger + * /auth/refresh-token: + * post: + * summary: JWT 토큰 갱신 + * tags: [Auth] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - refreshToken + * properties: + * refreshToken: + * type: string + * example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." + * responses: + * 200: + * description: 토큰 갱신 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * accessToken: + * type: string + * example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." + * refreshToken: + * type: string + * example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." + * 401: + * description: 유효하지 않은 토큰입니다. + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "유효하지 않은 토큰입니다." + */ router.post("/refresh-token", asyncHandler(refreshToken)); +/** + * @swagger + * /auth/google: + * get: + * summary: 구글 인증 + * tags: [Auth] + * responses: + * 302: + * description: 구글 인증 페이지로 리디렉션 + */ router.get("/google", passport.authenticate("google", { scope: ["profile", "email"] })); + +/** + * @swagger + * /auth/google/callback: + * get: + * summary: 구글 OAuth 콜백 + * tags: [Auth] + * responses: + * 200: + * description: 구글 인증 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * accessToken: + * type: string + * example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." + * refreshToken: + * type: string + * example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." + * 401: + * description: 구글 인증 실패 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "구글 인증 실패" + */ router.get("/google/callback", passport.authenticate("google", { failureRedirect: "/" }), googleCallback); +/** + * @swagger + * /auth/logout: + * get: + * summary: 로그아웃 + * tags: [Auth] + * responses: + * 302: + * description: 로그아웃 후 리디렉션 + */ router.get("/logout", (req, res) => { req.logout(); res.redirect("/"); diff --git a/routes/imageRoutes.js b/routes/imageRoutes.js index f413c71..4966f1a 100644 --- a/routes/imageRoutes.js +++ b/routes/imageRoutes.js @@ -18,7 +18,53 @@ const storage = multer.diskStorage({ const upload = multer({ storage: storage }); -// 이미지 업로드 +/** + * @swagger + * tags: + * name: Images + * description: 이미지 관리 + */ + +/** + * @swagger + * /images/upload: + * post: + * summary: 이미지 업로드 + * tags: [Images] + * security: + * - bearerAuth: [] + * requestBody: + * required: true + * content: + * multipart/form-data: + * schema: + * type: object + * properties: + * image: + * type: string + * format: binary + * responses: + * 200: + * description: 이미지 업로드 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * url: + * type: string + * example: "http://localhost:3000/uploads/image-123456789.jpg" + * 400: + * description: 이미지 파일이 선택되지 않음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "이미지 파일을 선택해주세요." + */ router.post("/upload", authenticate, upload.single("image"), imageController.uploadImage); export default router; diff --git a/routes/productRoutes.js b/routes/productRoutes.js index 49386ad..0ea88cd 100644 --- a/routes/productRoutes.js +++ b/routes/productRoutes.js @@ -4,22 +4,851 @@ import * as productController from "../controllers/productController.js"; import authenticate from "../middlewares/authenticate.js"; const router = express.Router(); +/** + * @swagger + * tags: + * name: Products + * description: 중고마켓 + */ + +/** + * @swagger + * /products: + * get: + * summary: 상품 목록 조회 + * tags: [Products] + * parameters: + * - in: query + * name: offset + * schema: + * type: integer + * example: 0 + * description: 가져올 데이터의 시작 지점 + * - in: query + * name: limit + * schema: + * type: integer + * example: 10 + * description: 한 번에 가져올 데이터의 개수 + * - in: query + * name: orderBy + * schema: + * type: string + * enum: [favorite, recent] + * example: recent + * description: 정렬 기준 + * - in: query + * name: keyword + * schema: + * type: string + * example: "상품 이름" + * description: 검색 키워드 + * responses: + * 200: + * description: 상품 목록 조회 성공 + * content: + * application/json: + * schema: + * type: array + * items: + * type: object + * properties: + * id: + * type: string + * example: "1" + * name: + * type: string + * example: "상품 이름" + * description: + * type: string + * example: "상품 설명" + * price: + * type: number + * example: 1000 + * favoriteCount: + * type: number + * example: 5 + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * examples: + * application/json: + * value: + * - id: "1" + * name: "상품 이름" + * description: "상품 설명" + * price: 1000 + * favoriteCount: 5 + * createdAt: "2023-01-01T00:00:00.000Z" + * post: + * summary: 상품 생성 + * tags: [Products] + * security: + * - bearerAuth: [] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * example: "상품 이름" + * description: + * type: string + * example: "상품 설명" + * price: + * type: number + * example: 1000 + * responses: + * 201: + * description: 상품 생성 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * example: "1" + * name: + * type: string + * example: "상품 이름" + * description: + * type: string + * example: "상품 설명" + * price: + * type: number + * example: 1000 + * favoriteCount: + * type: number + * example: 5 + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * examples: + * application/json: + * value: + * id: "1" + * name: "상품 이름" + * description: "상품 설명" + * price: 1000 + * favoriteCount: 5 + * createdAt: "2023-01-01T00:00:00.000Z" + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + */ router.route("/").get(productController.getProducts).post(authenticate, productController.createProduct); +/** + * @swagger + * /products/{id}: + * get: + * summary: 특정 상품 조회 + * tags: [Products] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * responses: + * 200: + * description: 상품 조회 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * example: "1" + * name: + * type: string + * example: "상품 이름" + * description: + * type: string + * example: "상품 설명" + * price: + * type: number + * example: 1000 + * favoriteCount: + * type: number + * example: 5 + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * examples: + * application/json: + * value: + * id: "1" + * name: "상품 이름" + * description: "상품 설명" + * price: 1000 + * favoriteCount: 5 + * createdAt: "2023-01-01T00:00:00.000Z" + * 404: + * description: 상품을 찾을 수 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "존재하지 않는 게시글입니다." + * patch: + * summary: 상품 수정 + * tags: [Products] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * example: "상품 이름" + * description: + * type: string + * example: "상품 설명" + * price: + * type: number + * example: 1000 + * responses: + * 200: + * description: 상품 수정 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * example: "1" + * name: + * type: string + * example: "상품 이름" + * description: + * type: string + * example: "상품 설명" + * price: + * type: number + * example: 1000 + * favoriteCount: + * type: number + * example: 5 + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * examples: + * application/json: + * value: + * id: "1" + * name: "상품 이름" + * description: "상품 설명" + * price: 1000 + * favoriteCount: 5 + * createdAt: "2023-01-01T00:00:00.000Z" + * 400: + * description: 유효성 검사 오류 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "유효성 검사 오류입니다." + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * 403: + * description: 권한 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "상품을 수정할 권한이 없습니다." + * 404: + * description: 상품을 찾을 수 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "존재하지 않는 게시글입니다." + * delete: + * summary: 상품 삭제 + * tags: [Products] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * responses: + * 204: + * description: 상품 삭제 성공 + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * 403: + * description: 권한 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "상품을 삭제할 권한이 없습니다." + * 404: + * description: 상품을 찾을 수 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "존재하지 않는 게시글입니다." + */ router .route("/:id") .get(productController.getProductById) .patch(authenticate, productController.updateProduct) .delete(authenticate, productController.deleteProduct); +/** + * @swagger + * /products/{id}/like: + * patch: + * summary: 상품 좋아요 + * tags: [Products] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * responses: + * 200: + * description: 상품 좋아요 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * example: "1" + * name: + * type: string + * example: "상품 이름" + * description: + * type: string + * example: "상품 설명" + * price: + * type: number + * example: 1000 + * favoriteCount: + * type: number + * example: 5 + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * examples: + * application/json: + * value: + * id: "1" + * name: "상품 이름" + * description: "상품 설명" + * price: 1000 + * favoriteCount: 6 + * createdAt: "2023-01-01T00:00:00.000Z" + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * 409: + * description: 이미 좋아요 처리된 상품 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "이미 좋아요 처리된 상품입니다." + */ router.route("/:id/like").patch(authenticate, productController.likeProduct); +/** + * @swagger + * /products/{id}/unlike: + * patch: + * summary: 상품 좋아요 취소 + * tags: [Products] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * responses: + * 200: + * description: 상품 좋아요 취소 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * example: "1" + * name: + * type: string + * example: "상품 이름" + * description: + * type: string + * example: "상품 설명" + * price: + * type: number + * example: 1000 + * favoriteCount: + * type: number + * example: 5 + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * examples: + * application/json: + * value: + * id: "1" + * name: "상품 이름" + * description: "상품 설명" + * price: 1000 + * favoriteCount: 4 + * createdAt: "2023-01-01T00:00:00.000Z" + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * 409: + * description: 아직 좋아요 처리되지 않은 상품 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "아직 좋아요 처리되지 않은 상품입니다." + */ router.route("/:id/unlike").patch(authenticate, productController.unlikeProduct); + +/** + * @swagger + * /products/{productId}/comments: + * get: + * summary: 특정 상품의 댓글 목록 조회 + * tags: [Comments] + * parameters: + * - in: path + * name: productId + * required: true + * schema: + * type: string + * responses: + * 200: + * description: 댓글 목록 조회 성공 + * content: + * application/json: + * schema: + * type: array + * items: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * content: + * type: string + * example: "댓글 내용" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * writer: + * type: string + * example: "작성자" + * examples: + * application/json: + * value: + * - id: "550e8400-e29b-41d4-a716-446655440000" + * content: "댓글 내용" + * createdAt: "2023-01-01T00:00:00.000Z" + * writer: "작성자" + * 404: + * description: 게시글을 찾을 수 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "존재하지 않는 게시글입니다." + * post: + * summary: 댓글 작성 + * tags: [Comments] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: articleId + * required: true + * schema: + * type: string + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * content: + * type: string + * example: "댓글 내용" + * responses: + * 201: + * description: 댓글 작성 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * content: + * type: string + * example: "댓글 내용" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * writer: + * type: string + * example: "작성자" + * examples: + * application/json: + * value: + * id: "550e8400-e29b-41d4-a716-446655440000" + * content: "댓글 내용" + * createdAt: "2023-01-01T00:00:00.000Z" + * writer: "작성자" + * 400: + * description: 유효성 검사 오류 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "유효성 검사 오류입니다." + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * 404: + * description: 게시글을 찾을 수 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "존재하지 않는 게시글입니다." + */ + router .route("/:productId/comments") .get(commentController.getCommentsByProductId) .post(authenticate, commentController.createComment); +/** + * @swagger + * /products/{productId}/comments/{commentId}: + * patch: + * summary: 댓글 수정 + * tags: [Comments] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: productId + * required: true + * schema: + * type: string + * - in: path + * name: commentId + * required: true + * schema: + * type: string + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * content: + * type: string + * example: "댓글 내용" + * responses: + * 200: + * description: 댓글 수정 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * content: + * type: string + * example: "댓글 내용" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * writer: + * type: string + * example: "작성자" + * examples: + * application/json: + * value: + * id: "550e8400-e29b-41d4-a716-446655440000" + * content: "댓글 내용" + * createdAt: "2023-01-01T00:00:00.000Z" + * writer: "작성자" + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * 403: + * description: 권한 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "이 댓글을 수정할 권한이 없습니다." + * 404: + * description: 댓글을 찾을 수 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "존재하지 않는 댓글입니다." + * delete: + * summary: 댓글 삭제 + * tags: [Comments] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: articleId + * required: true + * schema: + * type: string + * - in: path + * name: commentId + * required: true + * schema: + * type: string + * responses: + * 204: + * description: 댓글 삭제 성공 + * 401: + * description: 인증 필요 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * examples: + * noToken: + * summary: 토큰이 제공되지 않은 경우 + * value: + * message: "인증 토큰이 제공되지 않았습니다." + * invalidToken: + * summary: 유효하지 않은 토큰인 경우 + * value: + * message: "유효하지 않은 토큰입니다." + * 403: + * description: 권한 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "이 댓글을 삭제할 권한이 없습니다." + * 404: + * description: 댓글을 찾을 수 없음 + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: "존재하지 않는 댓글입니다." + */ + router .route("/:productId/comments/:commentId") .patch(authenticate, commentController.updateComment) diff --git a/services/articleService.js b/services/articleService.js index 3832800..ce3148c 100644 --- a/services/articleService.js +++ b/services/articleService.js @@ -145,7 +145,7 @@ export const unlikeArticle = async (articleId, userId) => { }); if (!favorite) { - throw new AppError("아직 좋아요 처리되지 않은 게시글입니다.", 400); + throw new AppError("아직 좋아요 처리되지 않은 게시글입니다.", 409); } const [deletedFavorite, updatedArticle] = await prisma.$transaction([ diff --git a/swagger/swaggerOptions.js b/swagger/swaggerOptions.js new file mode 100644 index 0000000..454df85 --- /dev/null +++ b/swagger/swaggerOptions.js @@ -0,0 +1,42 @@ +import { readFileSync } from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const packageJson = JSON.parse(readFileSync(path.join(__dirname, "../package.json"), "utf8")); +const { version } = packageJson; + +const swaggerOptions = { + swaggerDefinition: { + openapi: "3.0.0", + info: { + title: "Panda Market API", + version, + description: "API documentation for Panda Market", + }, + servers: [ + { + url: "http://localhost:3000", + description: "Development server", + }, + ], + components: { + securitySchemes: { + bearerAuth: { + type: "http", + scheme: "bearer", + bearerFormat: "JWT", + }, + }, + }, + security: [ + { + bearerAuth: [], + }, + ], + }, + apis: ["./routes/*.js"], +}; + +export default swaggerOptions; From bfaa9d68853f38c8f320e5a37f7592317b134ac8 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 30 May 2024 18:42:26 +0900 Subject: [PATCH 37/60] =?UTF-8?q?[#M11]=20refactor=20:=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=EC=A0=9D=ED=8A=B8=EB=A1=9C=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=EA=B7=B8=EB=A0=88=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Article 관련 로직을 타입스크립트로 수정 - Auth 관련 로직을 타입스크립트로 수정 --- controllers/articleController.js | 86 -- http/articles.http | 2 +- nodemon.json | 6 + package-lock.json | 1008 +++++++++++++++-- package.json | 26 +- app.js => src/app.ts | 22 +- config/passport.js => src/config/passport.ts | 0 src/controllers/articleController.ts | 116 ++ .../controllers/authController.ts | 24 +- .../controllers/commentController.ts | 0 .../controllers/imageController.ts | 0 .../controllers/productController.ts | 0 .../middlewares/authenticate.ts | 0 .../middlewares/errorHandler.ts | 0 .../20240522062619_init/migration.sql | 0 .../20240522094218_init_article/migration.sql | 0 .../20240523002157_init_comment/migration.sql | 0 .../migration.sql | 0 .../migration.sql | 0 .../migration.sql | 0 .../migration.sql | 0 .../migration.sql | 0 .../migration.sql | 0 .../migration.sql | 0 .../migration.sql | 0 .../prisma}/migrations/migration_lock.toml | 0 prisma/mock.js => src/prisma/mock.ts | 0 {prisma => src/prisma}/schema.prisma | 0 prisma/seed.js => src/prisma/seed.ts | 0 .../routes/articleRoutes.ts | 0 .../authRoutes.js => src/routes/authRoutes.ts | 0 .../routes/imageRoutes.ts | 0 .../routes/productRoutes.ts | 0 .../services/articleService.ts | 45 +- .../services/authService.ts | 8 +- .../services/commentService.ts | 0 .../services/imageService.ts | 0 .../services/productService.ts | 0 structs.js => src/structs.ts | 0 .../swagger/swaggerOptions.ts | 2 +- src/types/express/index.d.ts | 10 + .../utils/asyncHandler.ts | 0 utils/errors.js => src/utils/errors.ts | 6 +- utils/tokens.js => src/utils/tokens.ts | 0 tsconfig.json | 21 + 45 files changed, 1144 insertions(+), 238 deletions(-) delete mode 100644 controllers/articleController.js create mode 100644 nodemon.json rename app.js => src/app.ts (72%) rename config/passport.js => src/config/passport.ts (100%) create mode 100644 src/controllers/articleController.ts rename controllers/authController.js => src/controllers/authController.ts (72%) rename controllers/commentController.js => src/controllers/commentController.ts (100%) rename controllers/imageController.js => src/controllers/imageController.ts (100%) rename controllers/productController.js => src/controllers/productController.ts (100%) rename middlewares/authenticate.js => src/middlewares/authenticate.ts (100%) rename middlewares/errorHandler.js => src/middlewares/errorHandler.ts (100%) rename {prisma => src/prisma}/migrations/20240522062619_init/migration.sql (100%) rename {prisma => src/prisma}/migrations/20240522094218_init_article/migration.sql (100%) rename {prisma => src/prisma}/migrations/20240523002157_init_comment/migration.sql (100%) rename {prisma => src/prisma}/migrations/20240523072342_change_writer_to_optional/migration.sql (100%) rename {prisma => src/prisma}/migrations/20240527032014_add_product_and_article_image_model/migration.sql (100%) rename {prisma => src/prisma}/migrations/20240527043147_add_user_and_favorite_model_and_change_product_model/migration.sql (100%) rename {prisma => src/prisma}/migrations/20240527072552_change_favorite_model/migration.sql (100%) rename {prisma => src/prisma}/migrations/20240527074901_rename_owner_id_to_user_id/migration.sql (100%) rename {prisma => src/prisma}/migrations/20240528031512_add_user_id_to_comment/migration.sql (100%) rename {prisma => src/prisma}/migrations/20240528063148_add_google_auth/migration.sql (100%) rename {prisma => src/prisma}/migrations/20240528063710_make_password_optional/migration.sql (100%) rename {prisma => src/prisma}/migrations/migration_lock.toml (100%) rename prisma/mock.js => src/prisma/mock.ts (100%) rename {prisma => src/prisma}/schema.prisma (100%) rename prisma/seed.js => src/prisma/seed.ts (100%) rename routes/articleRoutes.js => src/routes/articleRoutes.ts (100%) rename routes/authRoutes.js => src/routes/authRoutes.ts (100%) rename routes/imageRoutes.js => src/routes/imageRoutes.ts (100%) rename routes/productRoutes.js => src/routes/productRoutes.ts (100%) rename services/articleService.js => src/services/articleService.ts (74%) rename services/authService.js => src/services/authService.ts (61%) rename services/commentService.js => src/services/commentService.ts (100%) rename services/imageService.js => src/services/imageService.ts (100%) rename services/productService.js => src/services/productService.ts (100%) rename structs.js => src/structs.ts (100%) rename swagger/swaggerOptions.js => src/swagger/swaggerOptions.ts (96%) create mode 100644 src/types/express/index.d.ts rename utils/asyncHandler.js => src/utils/asyncHandler.ts (100%) rename utils/errors.js => src/utils/errors.ts (65%) rename utils/tokens.js => src/utils/tokens.ts (100%) create mode 100644 tsconfig.json diff --git a/controllers/articleController.js b/controllers/articleController.js deleted file mode 100644 index ea6b2bd..0000000 --- a/controllers/articleController.js +++ /dev/null @@ -1,86 +0,0 @@ -import { assert } from "superstruct"; -import * as articleService from "../services/articleService.js"; -import { CreateArticle, PatchArticle } from "../structs.js"; -import asyncHandler from "../utils/asyncHandler.js"; -import AppError from "../utils/errors.js"; - -export const getArticles = asyncHandler(async (req, res) => { - const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; - const articles = await articleService.getArticles({ offset, limit, orderBy, keyword }); - const bestArticles = await articleService.getBestArticles(); - res.send({ articles, bestArticles }); -}); - -export const createArticle = asyncHandler(async (req, res) => { - assert(req.body, CreateArticle); - const { userId } = req; - const article = await articleService.createArticle({ ...req.body, userId }); - res.status(201).send(article); -}); - -export const getArticleById = asyncHandler(async (req, res) => { - const { id } = req.params; - const article = await articleService.getArticleById(id); - res.send(article); -}); - -export const updateArticle = asyncHandler(async (req, res, next) => { - assert(req.body, PatchArticle); - - const { id: articleId } = req.params; - const { userId } = req; - - try { - const updatedArticle = await articleService.updateArticle(articleId, userId, req.body); - res.send(updatedArticle); - } catch (error) { - if (error instanceof AppError) { - return res.status(error.statusCode).json({ message: error.message }); - } - } -}); - -export const deleteArticle = asyncHandler(async (req, res, next) => { - const { id: articleId } = req.params; - const { userId } = req; - - try { - await articleService.deleteArticle(articleId, userId); - res.sendStatus(204); - } catch (error) { - if (error instanceof AppError) { - return res.status(error.statusCode).json({ message: error.message }); - } - next(error); - } -}); - -export const likeArticle = asyncHandler(async (req, res, next) => { - const { id: articleId } = req.params; - const { userId } = req; - - try { - const updatedArticle = await articleService.likeArticle(articleId, userId); - res.send(updatedArticle); - } catch (error) { - if (error instanceof AppError) { - return res.status(error.statusCode).json({ message: error.message }); - } - next(error); - } -}); - -export const unlikeArticle = asyncHandler(async (req, res, next) => { - const { id: articleId } = req.params; - const { userId } = req; - - try { - const updatedArticle = await articleService.unlikeArticle(articleId, userId); - res.send(updatedArticle); - } catch (error) { - if (error instanceof AppError) { - return res.status(error.statusCode).json({ message: error.message }); - } - next(error); - } -}); diff --git a/http/articles.http b/http/articles.http index 510a021..d24ef42 100644 --- a/http/articles.http +++ b/http/articles.http @@ -1,5 +1,5 @@ # 게시글 목록 조회 -GET http://localhost:3000/articles?&limit=10&&orderBy=like +GET http://localhost:3000/articles?&offset=1&limit=10&&orderBy=like ### # 게시글 상세 조회 diff --git a/nodemon.json b/nodemon.json new file mode 100644 index 0000000..5401897 --- /dev/null +++ b/nodemon.json @@ -0,0 +1,6 @@ +{ + "watch": ["src"], + "ext": "ts", + "ignore": ["node_modules"], + "exec": "tsx src/app.ts" +} diff --git a/package-lock.json b/package-lock.json index 4efa6b8..e03dc21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,15 +7,12 @@ "dependencies": { "@prisma/client": "^5.4.2", "bcrypt": "^5.1.1", - "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", - "express-session": "^1.18.0", "is-email": "^1.0.2", "is-uuid": "^1.0.2", "jsonwebtoken": "^9.0.2", "moment-timezone": "^0.5.45", - "morgan": "^1.10.0", "multer": "^1.4.5-lts.1", "passport": "^0.7.0", "passport-google-oauth20": "^2.0.0", @@ -25,7 +22,22 @@ "swagger-ui-express": "^5.0.0" }, "devDependencies": { - "nodemon": "^3.0.1" + "@types/bcrypt": "^5.0.2", + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/express-session": "^1.18.0", + "@types/jsonwebtoken": "^9.0.6", + "@types/morgan": "^1.9.9", + "@types/node": "^20.12.13", + "@types/swagger-jsdoc": "^6.0.4", + "@types/swagger-ui-express": "^4.1.6", + "cors": "^2.8.5", + "express-session": "^1.18.0", + "morgan": "^1.10.0", + "nodemon": "^3.1.2", + "ts-node": "^10.9.2", + "tsx": "^4.11.0", + "typescript": "^5.4.5" } }, "node_modules/@apidevtools/json-schema-ref-parser": { @@ -68,6 +80,411 @@ "openapi-types": ">=7" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@jsdevtools/ono": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", @@ -149,11 +566,193 @@ "@prisma/debug": "5.14.0" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@types/bcrypt": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", + "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.2.tgz", + "integrity": "sha512-dPSEQElyVJ97BuGduAqQjpBocZWAs0GR94z+ptL7JXQJeJdHw2WBG3EWdFrK36b8Q6j8P4cXOMhgUoi0IIfIsg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express-session": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.18.0.tgz", + "integrity": "sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", + "integrity": "sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/morgan": { + "version": "1.9.9", + "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.9.tgz", + "integrity": "sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.12.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.13.tgz", + "integrity": "sha512-gBGeanV41c1L171rR7wjbMiEpEI/l5XFQdLLfhr/REwpgDy/4U8y89+i8kRiLzDyZdOkXh+cRaTetUnCYutoXA==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/swagger-jsdoc": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz", + "integrity": "sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ==", + "dev": true + }, + "node_modules/@types/swagger-ui-express": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz", + "integrity": "sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/serve-static": "*" + } + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -171,6 +770,27 @@ "node": ">= 0.6" } }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -182,6 +802,27 @@ "node": ">= 6.0.0" } }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -239,6 +880,12 @@ "node": ">= 6" } }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -266,6 +913,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, "dependencies": { "safe-buffer": "5.1.2" }, @@ -276,7 +924,8 @@ "node_modules/basic-auth/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "node_modules/bcrypt": { "version": "5.1.1", @@ -326,19 +975,6 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -525,6 +1161,7 @@ "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, "dependencies": { "object-assign": "^4", "vary": "^1" @@ -533,27 +1170,20 @@ "node": ">= 0.10" } }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "ms": "2.0.0" } }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -600,6 +1230,15 @@ "node": ">=8" } }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -667,6 +1306,44 @@ "node": ">= 0.4" } }, + "node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -733,6 +1410,7 @@ "version": "1.18.0", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz", "integrity": "sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ==", + "dev": true, "dependencies": { "cookie": "0.6.0", "cookie-signature": "1.0.7", @@ -750,33 +1428,8 @@ "node_modules/express-session/node_modules/cookie-signature": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" - }, - "node_modules/express-session/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express-session/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "dev": true }, "node_modules/fill-range": { "version": "7.1.1", @@ -807,19 +1460,6 @@ "node": ">= 0.8" } }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -923,6 +1563,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -1051,6 +1703,27 @@ "node": ">= 6" } }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1188,6 +1861,11 @@ "npm": ">=6" } }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/jwa": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", @@ -1279,6 +1957,12 @@ "semver": "bin/semver.js" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1414,6 +2098,7 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dev": true, "dependencies": { "basic-auth": "~2.0.1", "debug": "2.6.9", @@ -1425,23 +2110,11 @@ "node": ">= 0.8.0" } }, - "node_modules/morgan/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/morgan/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, "node_modules/morgan/node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, "dependencies": { "ee-first": "1.1.1" }, @@ -1450,9 +2123,9 @@ } }, "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/multer": { "version": "1.4.5-lts.1", @@ -1504,9 +2177,9 @@ } }, "node_modules/nodemon": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", - "integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.2.tgz", + "integrity": "sha512-/Ib/kloefDy+N0iRTxIUzyGcdW9lzlnca2Jsa5w73bs3npXjg+WInmiX6VY13mIb6SykkthYX/U5t0ukryGqBw==", "dev": true, "dependencies": { "chokidar": "^3.5.2", @@ -1531,6 +2204,29 @@ "url": "https://opencollective.com/nodemon" } }, + "node_modules/nodemon/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -1602,6 +2298,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -1769,6 +2466,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -1826,6 +2524,15 @@ "node": ">=8.10.0" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -1899,18 +2606,10 @@ "node": ">= 0.8.0" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { "version": "1.15.0", @@ -2189,6 +2888,68 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tsx": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.11.0.tgz", + "integrity": "sha512-vzGGELOgAupsNVssAmZjbUDfdm/pWP4R+Kg8TVdsonxbXk0bEpE1qh0yV6/QxUVXaVlNemgcPajGdJJ82n3stg==", + "dev": true, + "dependencies": { + "esbuild": "~0.20.2", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -2206,10 +2967,24 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dev": true, "dependencies": { "random-bytes": "~1.0.0" }, @@ -2228,6 +3003,12 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -2249,6 +3030,12 @@ "node": ">= 0.4.0" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, "node_modules/validator": { "version": "13.12.0", "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", @@ -2313,6 +3100,15 @@ "node": ">= 6" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/z-schema": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", diff --git a/package.json b/package.json index fad07ce..00e3ed6 100644 --- a/package.json +++ b/package.json @@ -2,15 +2,12 @@ "dependencies": { "@prisma/client": "^5.4.2", "bcrypt": "^5.1.1", - "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", - "express-session": "^1.18.0", "is-email": "^1.0.2", "is-uuid": "^1.0.2", "jsonwebtoken": "^9.0.2", "moment-timezone": "^0.5.45", - "morgan": "^1.10.0", "multer": "^1.4.5-lts.1", "passport": "^0.7.0", "passport-google-oauth20": "^2.0.0", @@ -20,14 +17,29 @@ "swagger-ui-express": "^5.0.0" }, "devDependencies": { - "nodemon": "^3.0.1" + "@types/bcrypt": "^5.0.2", + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/express-session": "^1.18.0", + "@types/jsonwebtoken": "^9.0.6", + "@types/morgan": "^1.9.9", + "@types/node": "^20.12.13", + "@types/swagger-jsdoc": "^6.0.4", + "@types/swagger-ui-express": "^4.1.6", + "cors": "^2.8.5", + "express-session": "^1.18.0", + "morgan": "^1.10.0", + "nodemon": "^3.1.2", + "ts-node": "^10.9.2", + "tsx": "^4.11.0", + "typescript": "^5.4.5" }, "type": "module", "scripts": { - "dev": "nodemon app.js", - "start": "node app.js" + "start": "tsx --loader ts-node/esm src/app.ts", + "dev": "nodemon" }, "prisma": { - "seed": "node prisma/seed.js" + "seed": "node prisma/seed.ts" } } diff --git a/app.js b/src/app.ts similarity index 72% rename from app.js rename to src/app.ts index 44513bb..883cd05 100644 --- a/app.js +++ b/src/app.ts @@ -9,15 +9,17 @@ import path, { dirname } from "path"; import swaggerJsdoc from "swagger-jsdoc"; import swaggerUi from "swagger-ui-express"; import { fileURLToPath } from "url"; -import passport from "./config/passport.js"; -import errorHandler from "./middlewares/errorHandler.js"; -import articlesRouter from "./routes/articleRoutes.js"; -import authRouter from "./routes/authRoutes.js"; -import imagesRouter from "./routes/imageRoutes.js"; -import productsRouter from "./routes/productRoutes.js"; -import swaggerOptions from "./swagger/swaggerOptions.js"; +import passport from "./config/passport"; +import errorHandler from "./middlewares/errorHandler"; +import articlesRouter from "./routes/articleRoutes"; +import authRouter from "./routes/authRoutes"; +import imagesRouter from "./routes/imageRoutes"; +import productsRouter from "./routes/productRoutes"; +import swaggerOptions from "./swagger/swaggerOptions"; dotenv.config(); -const { JWT_SECRET } = process.env; + +const JWT_SECRET = process.env.JWT_SECRET || "kingPanda"; + const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -27,8 +29,8 @@ const specs = swaggerJsdoc(swaggerOptions); app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(specs)); -morgan.token("date", (req, res, tz) => { - return moment().tz(tz).format("YYYY-MM-DD HH:mm:ss"); +morgan.token("date", (req, res, tz = "UTC") => { + return moment().tz(tz.toString()).format("YYYY-MM-DD HH:mm:ss"); }); const customFormat = ":method :url :status :res[content-length] - :response-time ms - :date[Asia/Seoul]"; diff --git a/config/passport.js b/src/config/passport.ts similarity index 100% rename from config/passport.js rename to src/config/passport.ts diff --git a/src/controllers/articleController.ts b/src/controllers/articleController.ts new file mode 100644 index 0000000..494ee34 --- /dev/null +++ b/src/controllers/articleController.ts @@ -0,0 +1,116 @@ +import { NextFunction, Request, Response } from "express"; +import { assert } from "superstruct"; +import * as articleService from "../services/articleService"; +import { CreateArticle, PatchArticle } from "../structs"; +import asyncHandler from "../utils/asyncHandler"; +import AppError from "../utils/errors"; + +interface GetArticlesQuery { + offset?: string; + limit?: string; + orderBy?: string; + keyword?: string; +} + +interface UserRequest extends Request { + userId: number; +} + +interface ArticleRequest extends Request { + userId: number; + body: { + title: string; + content: string; + imageUrl?: string; + }; +} + +// GET /articles +export const getArticles = asyncHandler(async (req: Request<{}, {}, {}, GetArticlesQuery>, res: Response) => { + const { offset = "0", limit = "10", orderBy = "recent", keyword = "" } = req.query as { [key: string]: string }; + const offsetNumber = parseInt(offset, 10); + const limitNumber = parseInt(limit, 10); + const articles = await articleService.getArticles({ offset: offsetNumber, limit: limitNumber, orderBy, keyword }); + const bestArticles = await articleService.getBestArticles(); + res.send({ articles, bestArticles }); +}); + +// POST /articles +export const createArticle = asyncHandler(async (req: ArticleRequest, res: Response) => { + assert(req.body, CreateArticle); + const { userId } = req; + const article = await articleService.createArticle({ ...req.body, userId }); + res.status(201).send(article); +}); + +// GET /articles/:id +export const getArticleById = asyncHandler(async (req: Request<{ id: string }>, res: Response) => { + const { id } = req.params; + const article = await articleService.getArticleById(id); + res.send(article); +}); + +// PATCH /articles/:id +export const updateArticle = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { + assert(req.body, PatchArticle); + const { id: articleId } = req.params; + const { userId } = req; + try { + const updatedArticle = await articleService.updateArticle(articleId, userId, req.body); + res.send(updatedArticle); + } catch (error) { + if (error instanceof AppError) { + return res.status(error.statusCode).json({ message: error.message }); + } + } +}); +// DELETE /articles/:id +export const deleteArticle = asyncHandler( + async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { + const { id: articleId } = req.params; + const { userId } = req; + try { + await articleService.deleteArticle(articleId, userId); + res.sendStatus(204); + } catch (error) { + if (error instanceof AppError) { + return res.status(error.statusCode).json({ message: error.message }); + } + next(error); + } + } +); + +// POST /articles/:id/like +export const likeArticle = asyncHandler( + async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { + const { id: articleId } = req.params; + const { userId } = req; + try { + const updatedArticle = await articleService.likeArticle(articleId, userId); + res.send(updatedArticle); + } catch (error) { + if (error instanceof AppError) { + return res.status(error.statusCode).json({ message: error.message }); + } + next(error); + } + } +); + +// POST /articles/:id/unlike +export const unlikeArticle = asyncHandler( + async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { + const { id: articleId } = req.params; + const { userId } = req; + try { + const updatedArticle = await articleService.unlikeArticle(articleId, userId); + res.send(updatedArticle); + } catch (error) { + if (error instanceof AppError) { + return res.status(error.statusCode).json({ message: error.message }); + } + next(error); + } + } +); diff --git a/controllers/authController.js b/src/controllers/authController.ts similarity index 72% rename from controllers/authController.js rename to src/controllers/authController.ts index accb542..428ebbf 100644 --- a/controllers/authController.js +++ b/src/controllers/authController.ts @@ -1,14 +1,15 @@ import dotenv from "dotenv"; +import { NextFunction, Request, Response } from "express"; import jwt from "jsonwebtoken"; import { assert } from "superstruct"; -import { createUser, findUserByEmail, findUserById, validatePassword } from "../services/authService.js"; -import { CreateUser } from "../structs.js"; -import { generateAccessToken, generateRefreshToken, regenerateRefreshToken } from "../utils/tokens.js"; +import { createUser, findUserByEmail, findUserById, validatePassword } from "../services/authService"; +import { CreateUser } from "../structs"; +import { generateAccessToken, generateRefreshToken, regenerateRefreshToken } from "../utils/tokens"; dotenv.config(); -const JWT_SECRET = process.env.JWT_SECRET; +const JWT_SECRET = process.env.JWT_SECRET || "kingPanda"; -export const signUp = async (req, res) => { +export const signUp = async (req: Request, res: Response) => { const { email, password, name, nickname } = req.body; assert(req.body, CreateUser); @@ -23,12 +24,12 @@ export const signUp = async (req, res) => { res.status(201).json({ message: "회원가입이 완료되었습니다." }); }; -export const signIn = async (req, res) => { +export const signIn = async (req: Request, res: Response) => { const { email, password } = req.body; const user = await findUserByEmail(email); - if (!user) { + if (!user || !user.password) { return res.status(401).json({ message: "이메일과 비밀번호를 확인해주세요." }); } @@ -44,7 +45,7 @@ export const signIn = async (req, res) => { res.json({ accessToken, refreshToken }); }; -export const refreshToken = async (req, res) => { +export const refreshToken = async (req: Request, res: Response) => { const { refreshToken } = req.body; if (!refreshToken) { @@ -53,7 +54,7 @@ export const refreshToken = async (req, res) => { try { const newRefreshToken = regenerateRefreshToken(refreshToken); - const decoded = jwt.verify(newRefreshToken, JWT_SECRET); + const decoded = jwt.verify(newRefreshToken, JWT_SECRET) as { userId: number }; const user = await findUserById(decoded.userId); if (!user) { @@ -68,7 +69,10 @@ export const refreshToken = async (req, res) => { } }; -export const googleCallback = (req, res) => { +export const googleCallback = (req: Request, res: Response, next: NextFunction) => { + if (!req.user) { + return next(new Error("사용자 정보를 찾을 수 없습니다.")); + } const { accessToken, refreshToken } = req.user; res.json({ accessToken, refreshToken }); }; diff --git a/controllers/commentController.js b/src/controllers/commentController.ts similarity index 100% rename from controllers/commentController.js rename to src/controllers/commentController.ts diff --git a/controllers/imageController.js b/src/controllers/imageController.ts similarity index 100% rename from controllers/imageController.js rename to src/controllers/imageController.ts diff --git a/controllers/productController.js b/src/controllers/productController.ts similarity index 100% rename from controllers/productController.js rename to src/controllers/productController.ts diff --git a/middlewares/authenticate.js b/src/middlewares/authenticate.ts similarity index 100% rename from middlewares/authenticate.js rename to src/middlewares/authenticate.ts diff --git a/middlewares/errorHandler.js b/src/middlewares/errorHandler.ts similarity index 100% rename from middlewares/errorHandler.js rename to src/middlewares/errorHandler.ts diff --git a/prisma/migrations/20240522062619_init/migration.sql b/src/prisma/migrations/20240522062619_init/migration.sql similarity index 100% rename from prisma/migrations/20240522062619_init/migration.sql rename to src/prisma/migrations/20240522062619_init/migration.sql diff --git a/prisma/migrations/20240522094218_init_article/migration.sql b/src/prisma/migrations/20240522094218_init_article/migration.sql similarity index 100% rename from prisma/migrations/20240522094218_init_article/migration.sql rename to src/prisma/migrations/20240522094218_init_article/migration.sql diff --git a/prisma/migrations/20240523002157_init_comment/migration.sql b/src/prisma/migrations/20240523002157_init_comment/migration.sql similarity index 100% rename from prisma/migrations/20240523002157_init_comment/migration.sql rename to src/prisma/migrations/20240523002157_init_comment/migration.sql diff --git a/prisma/migrations/20240523072342_change_writer_to_optional/migration.sql b/src/prisma/migrations/20240523072342_change_writer_to_optional/migration.sql similarity index 100% rename from prisma/migrations/20240523072342_change_writer_to_optional/migration.sql rename to src/prisma/migrations/20240523072342_change_writer_to_optional/migration.sql diff --git a/prisma/migrations/20240527032014_add_product_and_article_image_model/migration.sql b/src/prisma/migrations/20240527032014_add_product_and_article_image_model/migration.sql similarity index 100% rename from prisma/migrations/20240527032014_add_product_and_article_image_model/migration.sql rename to src/prisma/migrations/20240527032014_add_product_and_article_image_model/migration.sql diff --git a/prisma/migrations/20240527043147_add_user_and_favorite_model_and_change_product_model/migration.sql b/src/prisma/migrations/20240527043147_add_user_and_favorite_model_and_change_product_model/migration.sql similarity index 100% rename from prisma/migrations/20240527043147_add_user_and_favorite_model_and_change_product_model/migration.sql rename to src/prisma/migrations/20240527043147_add_user_and_favorite_model_and_change_product_model/migration.sql diff --git a/prisma/migrations/20240527072552_change_favorite_model/migration.sql b/src/prisma/migrations/20240527072552_change_favorite_model/migration.sql similarity index 100% rename from prisma/migrations/20240527072552_change_favorite_model/migration.sql rename to src/prisma/migrations/20240527072552_change_favorite_model/migration.sql diff --git a/prisma/migrations/20240527074901_rename_owner_id_to_user_id/migration.sql b/src/prisma/migrations/20240527074901_rename_owner_id_to_user_id/migration.sql similarity index 100% rename from prisma/migrations/20240527074901_rename_owner_id_to_user_id/migration.sql rename to src/prisma/migrations/20240527074901_rename_owner_id_to_user_id/migration.sql diff --git a/prisma/migrations/20240528031512_add_user_id_to_comment/migration.sql b/src/prisma/migrations/20240528031512_add_user_id_to_comment/migration.sql similarity index 100% rename from prisma/migrations/20240528031512_add_user_id_to_comment/migration.sql rename to src/prisma/migrations/20240528031512_add_user_id_to_comment/migration.sql diff --git a/prisma/migrations/20240528063148_add_google_auth/migration.sql b/src/prisma/migrations/20240528063148_add_google_auth/migration.sql similarity index 100% rename from prisma/migrations/20240528063148_add_google_auth/migration.sql rename to src/prisma/migrations/20240528063148_add_google_auth/migration.sql diff --git a/prisma/migrations/20240528063710_make_password_optional/migration.sql b/src/prisma/migrations/20240528063710_make_password_optional/migration.sql similarity index 100% rename from prisma/migrations/20240528063710_make_password_optional/migration.sql rename to src/prisma/migrations/20240528063710_make_password_optional/migration.sql diff --git a/prisma/migrations/migration_lock.toml b/src/prisma/migrations/migration_lock.toml similarity index 100% rename from prisma/migrations/migration_lock.toml rename to src/prisma/migrations/migration_lock.toml diff --git a/prisma/mock.js b/src/prisma/mock.ts similarity index 100% rename from prisma/mock.js rename to src/prisma/mock.ts diff --git a/prisma/schema.prisma b/src/prisma/schema.prisma similarity index 100% rename from prisma/schema.prisma rename to src/prisma/schema.prisma diff --git a/prisma/seed.js b/src/prisma/seed.ts similarity index 100% rename from prisma/seed.js rename to src/prisma/seed.ts diff --git a/routes/articleRoutes.js b/src/routes/articleRoutes.ts similarity index 100% rename from routes/articleRoutes.js rename to src/routes/articleRoutes.ts diff --git a/routes/authRoutes.js b/src/routes/authRoutes.ts similarity index 100% rename from routes/authRoutes.js rename to src/routes/authRoutes.ts diff --git a/routes/imageRoutes.js b/src/routes/imageRoutes.ts similarity index 100% rename from routes/imageRoutes.js rename to src/routes/imageRoutes.ts diff --git a/routes/productRoutes.js b/src/routes/productRoutes.ts similarity index 100% rename from routes/productRoutes.js rename to src/routes/productRoutes.ts diff --git a/services/articleService.js b/src/services/articleService.ts similarity index 74% rename from services/articleService.js rename to src/services/articleService.ts index ce3148c..9afffb4 100644 --- a/services/articleService.js +++ b/src/services/articleService.ts @@ -1,9 +1,27 @@ -import { PrismaClient } from "@prisma/client"; +import { Prisma, PrismaClient } from "@prisma/client"; +import AppError from "../utils/errors"; const prisma = new PrismaClient(); -export const getArticles = async ({ offset, limit, orderBy, keyword }) => { - const order = orderBy === "like" ? { likeCount: "desc" } : { createdAt: "desc" }; +interface getArticlesParams { + offset: number; + limit: number; + orderBy: string; + keyword: string; +} + +interface Article { + title: string; + content: string; + imageUrl?: string; + userId: number; + writer?: string; +} + +export const getArticles = async ({ offset, limit, orderBy, keyword }: getArticlesParams) => { + const order: Prisma.ArticleOrderByWithRelationInput = + orderBy === "like" ? { likeCount: "desc" } : { createdAt: "desc" }; + const articles = await prisma.article.findMany({ select: { id: true, @@ -14,8 +32,8 @@ export const getArticles = async ({ offset, limit, orderBy, keyword }) => { writer: true, }, orderBy: order, - skip: parseInt(offset), - take: parseInt(limit), + skip: offset, + take: limit, where: { OR: [ { @@ -48,13 +66,13 @@ export const getBestArticles = async () => { return bestArticles; }; -export const createArticle = async (articleData) => { +export const createArticle = async (articleData: Article) => { return await prisma.article.create({ data: articleData, }); }; -export const getArticleById = async (id) => { +export const getArticleById = async (id: string) => { return await prisma.article.findUniqueOrThrow({ where: { id }, select: { @@ -69,7 +87,7 @@ export const getArticleById = async (id) => { }); }; -export const updateArticle = async (articleId, userId, articleData) => { +export const updateArticle = async (articleId: string, userId: number, articleData: Partial
) => { const article = await prisma.article.findUniqueOrThrow({ where: { id: articleId }, }); @@ -80,11 +98,14 @@ export const updateArticle = async (articleId, userId, articleData) => { return await prisma.article.update({ where: { id: articleId }, - data: articleData, + data: { + ...articleData, + userId, + }, }); }; -export const deleteArticle = async (articleId, userId) => { +export const deleteArticle = async (articleId: string, userId: number) => { const article = await prisma.article.findUniqueOrThrow({ where: { id: articleId }, }); @@ -98,7 +119,7 @@ export const deleteArticle = async (articleId, userId) => { }); }; -export const likeArticle = async (articleId, userId) => { +export const likeArticle = async (articleId: string, userId: number) => { const favorite = await prisma.favorite.findUnique({ where: { userId_articleId: { @@ -134,7 +155,7 @@ export const likeArticle = async (articleId, userId) => { return updatedArticle; }; -export const unlikeArticle = async (articleId, userId) => { +export const unlikeArticle = async (articleId: string, userId: number) => { const favorite = await prisma.favorite.findUnique({ where: { userId_articleId: { diff --git a/services/authService.js b/src/services/authService.ts similarity index 61% rename from services/authService.js rename to src/services/authService.ts index f736007..6caac6c 100644 --- a/services/authService.js +++ b/src/services/authService.ts @@ -3,7 +3,7 @@ import bcrypt from "bcrypt"; const prisma = new PrismaClient(); -export const createUser = async (email, password, name, nickname) => { +export const createUser = async (email: string, password: string, name: string, nickname: string) => { const hashedPassword = await bcrypt.hash(password, 10); return prisma.user.create({ data: { @@ -15,18 +15,18 @@ export const createUser = async (email, password, name, nickname) => { }); }; -export const findUserByEmail = async (email) => { +export const findUserByEmail = async (email: string) => { return prisma.user.findUnique({ where: { email }, }); }; -export const findUserById = async (id) => { +export const findUserById = async (id: number) => { return prisma.user.findUnique({ where: { id }, }); }; -export const validatePassword = async (inputPassword, storedPassword) => { +export const validatePassword = async (inputPassword: string, storedPassword: string) => { return bcrypt.compare(inputPassword, storedPassword); }; diff --git a/services/commentService.js b/src/services/commentService.ts similarity index 100% rename from services/commentService.js rename to src/services/commentService.ts diff --git a/services/imageService.js b/src/services/imageService.ts similarity index 100% rename from services/imageService.js rename to src/services/imageService.ts diff --git a/services/productService.js b/src/services/productService.ts similarity index 100% rename from services/productService.js rename to src/services/productService.ts diff --git a/structs.js b/src/structs.ts similarity index 100% rename from structs.js rename to src/structs.ts diff --git a/swagger/swaggerOptions.js b/src/swagger/swaggerOptions.ts similarity index 96% rename from swagger/swaggerOptions.js rename to src/swagger/swaggerOptions.ts index 454df85..028a9da 100644 --- a/swagger/swaggerOptions.js +++ b/src/swagger/swaggerOptions.ts @@ -4,7 +4,7 @@ import { fileURLToPath } from "url"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -const packageJson = JSON.parse(readFileSync(path.join(__dirname, "../package.json"), "utf8")); +const packageJson = JSON.parse(readFileSync(path.join(__dirname, "../../package.json"), "utf8")); const { version } = packageJson; const swaggerOptions = { diff --git a/src/types/express/index.d.ts b/src/types/express/index.d.ts new file mode 100644 index 0000000..8066775 --- /dev/null +++ b/src/types/express/index.d.ts @@ -0,0 +1,10 @@ +declare namespace Express { + interface User { + accessToken: string; + refreshToken: string; + } + + interface Request { + user?: User; + } +} diff --git a/utils/asyncHandler.js b/src/utils/asyncHandler.ts similarity index 100% rename from utils/asyncHandler.js rename to src/utils/asyncHandler.ts diff --git a/utils/errors.js b/src/utils/errors.ts similarity index 65% rename from utils/errors.js rename to src/utils/errors.ts index c3a6992..289cd0a 100644 --- a/utils/errors.js +++ b/src/utils/errors.ts @@ -1,5 +1,9 @@ class AppError extends Error { - constructor(message, statusCode) { + public statusCode: number; + public status: string; + public isOperational: boolean; + + constructor(message: string, statusCode: number) { super(message); this.statusCode = statusCode; this.status = `${statusCode}`.startsWith("4") ? "fail" : "error"; diff --git a/utils/tokens.js b/src/utils/tokens.ts similarity index 100% rename from utils/tokens.js rename to src/utils/tokens.ts diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..d278dee --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES6", + "module": "esnext", + "moduleResolution": "node", + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "typeRoots": ["./node_modules/@types", "./types"] + }, + "ts-node": { + "esm": true + }, + + "include": ["src/**/*.ts"], + "exclude": ["node_modules"] +} From 3191f88f2671de0b07c01f3c91db9d889c769fdc Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Fri, 31 May 2024 10:31:28 +0900 Subject: [PATCH 38/60] =?UTF-8?q?[#M11]=20refactor=20:=20passport=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EB=A1=9C=EC=A7=81=EC=9D=84=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=EB=A1=9C=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 - prisma 폴더 위치 변경 --- package-lock.json | 42 + package.json | 2 + .../20240522062619_init/migration.sql | 0 .../20240522094218_init_article/migration.sql | 0 .../20240523002157_init_comment/migration.sql | 0 .../migration.sql | 0 .../migration.sql | 0 .../migration.sql | 0 .../migration.sql | 0 .../migration.sql | 0 .../migration.sql | 0 .../migration.sql | 0 .../migration.sql | 0 .../migrations/migration_lock.toml | 0 {src/prisma => prisma}/mock.ts | 0 {src/prisma => prisma}/schema.prisma | 0 {src/prisma => prisma}/seed.ts | 0 src/config/passport.ts | 47 +- src/types/express/index.d.ts | 2 + yarn.lock | 1981 +++++++++++++++++ 20 files changed, 2059 insertions(+), 15 deletions(-) rename {src/prisma => prisma}/migrations/20240522062619_init/migration.sql (100%) rename {src/prisma => prisma}/migrations/20240522094218_init_article/migration.sql (100%) rename {src/prisma => prisma}/migrations/20240523002157_init_comment/migration.sql (100%) rename {src/prisma => prisma}/migrations/20240523072342_change_writer_to_optional/migration.sql (100%) rename {src/prisma => prisma}/migrations/20240527032014_add_product_and_article_image_model/migration.sql (100%) rename {src/prisma => prisma}/migrations/20240527043147_add_user_and_favorite_model_and_change_product_model/migration.sql (100%) rename {src/prisma => prisma}/migrations/20240527072552_change_favorite_model/migration.sql (100%) rename {src/prisma => prisma}/migrations/20240527074901_rename_owner_id_to_user_id/migration.sql (100%) rename {src/prisma => prisma}/migrations/20240528031512_add_user_id_to_comment/migration.sql (100%) rename {src/prisma => prisma}/migrations/20240528063148_add_google_auth/migration.sql (100%) rename {src/prisma => prisma}/migrations/20240528063710_make_password_optional/migration.sql (100%) rename {src/prisma => prisma}/migrations/migration_lock.toml (100%) rename {src/prisma => prisma}/mock.ts (100%) rename {src/prisma => prisma}/schema.prisma (100%) rename {src/prisma => prisma}/seed.ts (100%) create mode 100644 yarn.lock diff --git a/package-lock.json b/package-lock.json index e03dc21..f9bc767 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,8 @@ "@types/jsonwebtoken": "^9.0.6", "@types/morgan": "^1.9.9", "@types/node": "^20.12.13", + "@types/passport": "^1.0.16", + "@types/passport-google-oauth20": "^2.0.16", "@types/swagger-jsdoc": "^6.0.4", "@types/swagger-ui-express": "^4.1.6", "cors": "^2.8.5", @@ -704,6 +706,46 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/oauth": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.5.tgz", + "integrity": "sha512-+oQ3C2Zx6ambINOcdIARF5Z3Tu3x//HipE889/fqo3sgpQZbe9c6ExdQFtN6qlhpR7p83lTZfPJt0tCAW29dog==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/passport": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.16.tgz", + "integrity": "sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-google-oauth20": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.16.tgz", + "integrity": "sha512-ayXK2CJ7uVieqhYOc6k/pIr5pcQxOLB6kBev+QUGS7oEZeTgIs1odDobXRqgfBPvXzl0wXCQHftV5220czZCPA==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-oauth2": "*" + } + }, + "node_modules/@types/passport-oauth2": { + "version": "1.4.17", + "resolved": "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.4.17.tgz", + "integrity": "sha512-ODiAHvso6JcWJ6ZkHHroVp05EHGhqQN533PtFNBkg8Fy5mERDqsr030AX81M0D69ZcaMvhF92SRckEk2B0HYYg==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/oauth": "*", + "@types/passport": "*" + } + }, "node_modules/@types/qs": { "version": "6.9.15", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", diff --git a/package.json b/package.json index 00e3ed6..7000a0a 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,8 @@ "@types/jsonwebtoken": "^9.0.6", "@types/morgan": "^1.9.9", "@types/node": "^20.12.13", + "@types/passport": "^1.0.16", + "@types/passport-google-oauth20": "^2.0.16", "@types/swagger-jsdoc": "^6.0.4", "@types/swagger-ui-express": "^4.1.6", "cors": "^2.8.5", diff --git a/src/prisma/migrations/20240522062619_init/migration.sql b/prisma/migrations/20240522062619_init/migration.sql similarity index 100% rename from src/prisma/migrations/20240522062619_init/migration.sql rename to prisma/migrations/20240522062619_init/migration.sql diff --git a/src/prisma/migrations/20240522094218_init_article/migration.sql b/prisma/migrations/20240522094218_init_article/migration.sql similarity index 100% rename from src/prisma/migrations/20240522094218_init_article/migration.sql rename to prisma/migrations/20240522094218_init_article/migration.sql diff --git a/src/prisma/migrations/20240523002157_init_comment/migration.sql b/prisma/migrations/20240523002157_init_comment/migration.sql similarity index 100% rename from src/prisma/migrations/20240523002157_init_comment/migration.sql rename to prisma/migrations/20240523002157_init_comment/migration.sql diff --git a/src/prisma/migrations/20240523072342_change_writer_to_optional/migration.sql b/prisma/migrations/20240523072342_change_writer_to_optional/migration.sql similarity index 100% rename from src/prisma/migrations/20240523072342_change_writer_to_optional/migration.sql rename to prisma/migrations/20240523072342_change_writer_to_optional/migration.sql diff --git a/src/prisma/migrations/20240527032014_add_product_and_article_image_model/migration.sql b/prisma/migrations/20240527032014_add_product_and_article_image_model/migration.sql similarity index 100% rename from src/prisma/migrations/20240527032014_add_product_and_article_image_model/migration.sql rename to prisma/migrations/20240527032014_add_product_and_article_image_model/migration.sql diff --git a/src/prisma/migrations/20240527043147_add_user_and_favorite_model_and_change_product_model/migration.sql b/prisma/migrations/20240527043147_add_user_and_favorite_model_and_change_product_model/migration.sql similarity index 100% rename from src/prisma/migrations/20240527043147_add_user_and_favorite_model_and_change_product_model/migration.sql rename to prisma/migrations/20240527043147_add_user_and_favorite_model_and_change_product_model/migration.sql diff --git a/src/prisma/migrations/20240527072552_change_favorite_model/migration.sql b/prisma/migrations/20240527072552_change_favorite_model/migration.sql similarity index 100% rename from src/prisma/migrations/20240527072552_change_favorite_model/migration.sql rename to prisma/migrations/20240527072552_change_favorite_model/migration.sql diff --git a/src/prisma/migrations/20240527074901_rename_owner_id_to_user_id/migration.sql b/prisma/migrations/20240527074901_rename_owner_id_to_user_id/migration.sql similarity index 100% rename from src/prisma/migrations/20240527074901_rename_owner_id_to_user_id/migration.sql rename to prisma/migrations/20240527074901_rename_owner_id_to_user_id/migration.sql diff --git a/src/prisma/migrations/20240528031512_add_user_id_to_comment/migration.sql b/prisma/migrations/20240528031512_add_user_id_to_comment/migration.sql similarity index 100% rename from src/prisma/migrations/20240528031512_add_user_id_to_comment/migration.sql rename to prisma/migrations/20240528031512_add_user_id_to_comment/migration.sql diff --git a/src/prisma/migrations/20240528063148_add_google_auth/migration.sql b/prisma/migrations/20240528063148_add_google_auth/migration.sql similarity index 100% rename from src/prisma/migrations/20240528063148_add_google_auth/migration.sql rename to prisma/migrations/20240528063148_add_google_auth/migration.sql diff --git a/src/prisma/migrations/20240528063710_make_password_optional/migration.sql b/prisma/migrations/20240528063710_make_password_optional/migration.sql similarity index 100% rename from src/prisma/migrations/20240528063710_make_password_optional/migration.sql rename to prisma/migrations/20240528063710_make_password_optional/migration.sql diff --git a/src/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml similarity index 100% rename from src/prisma/migrations/migration_lock.toml rename to prisma/migrations/migration_lock.toml diff --git a/src/prisma/mock.ts b/prisma/mock.ts similarity index 100% rename from src/prisma/mock.ts rename to prisma/mock.ts diff --git a/src/prisma/schema.prisma b/prisma/schema.prisma similarity index 100% rename from src/prisma/schema.prisma rename to prisma/schema.prisma diff --git a/src/prisma/seed.ts b/prisma/seed.ts similarity index 100% rename from src/prisma/seed.ts rename to prisma/seed.ts diff --git a/src/config/passport.ts b/src/config/passport.ts index 6a14c18..58263b8 100644 --- a/src/config/passport.ts +++ b/src/config/passport.ts @@ -1,14 +1,22 @@ -import { PrismaClient } from "@prisma/client"; +import { PrismaClient, User as PrismaUser } from "@prisma/client"; import dotenv from "dotenv"; +import { Request } from "express"; import passport from "passport"; -import { Strategy as GoogleStrategy } from "passport-google-oauth20"; -import { generateAccessToken, generateRefreshToken } from "../utils/tokens.js"; +import { Strategy as GoogleStrategy, Profile, VerifyCallback } from "passport-google-oauth20"; +import { generateAccessToken, generateRefreshToken } from "../utils/tokens"; dotenv.config(); const prisma = new PrismaClient(); -const GOOGLE_CLIENT_ID = process.env.GOOGLE_CLIENT_ID; -const GOOGLE_CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET; +const GOOGLE_CLIENT_ID = process.env.GOOGLE_CLIENT_ID || ""; +const GOOGLE_CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET || ""; + +interface UserWithTokens extends PrismaUser { + accessToken: string; + refreshToken: string; + username: string; + _id?: number; +} passport.use( new GoogleStrategy( @@ -16,8 +24,9 @@ passport.use( clientID: GOOGLE_CLIENT_ID, clientSecret: GOOGLE_CLIENT_SECRET, callbackURL: "http://localhost:3000/auth/google/callback", + passReqToCallback: true, }, - async (accessToken, refreshToken, profile, done) => { + async (req: Request, accessToken: string, refreshToken: string, profile: Profile, done: VerifyCallback) => { const { id, displayName, emails } = profile; try { @@ -29,9 +38,9 @@ passport.use( user = await prisma.user.create({ data: { googleId: id, - email: emails[0].value, - name: displayName, - nickname: displayName, + email: emails && emails[0] ? emails[0].value : "", + name: displayName || "", + nickname: displayName || "", password: null, }, }); @@ -40,20 +49,28 @@ passport.use( const accessTokenJwt = generateAccessToken(user); const refreshTokenJwt = generateRefreshToken(user); - done(null, { user, accessToken: accessTokenJwt, refreshToken: refreshTokenJwt }); + const userWithTokens: UserWithTokens = { + ...user, + accessToken: accessTokenJwt, + refreshToken: refreshTokenJwt, + username: displayName || "", + _id: user.id, + }; + + done(null, userWithTokens); } catch (error) { - done(error, null); + done(error, false); } } ) ); -passport.serializeUser((userWithTokens, done) => { - done(null, userWithTokens); +passport.serializeUser((user: Express.User, done) => { + done(null, user); }); -passport.deserializeUser((userWithTokens, done) => { - done(null, userWithTokens); +passport.deserializeUser((user: Express.User, done) => { + done(null, user); }); export default passport; diff --git a/src/types/express/index.d.ts b/src/types/express/index.d.ts index 8066775..f45b7f5 100644 --- a/src/types/express/index.d.ts +++ b/src/types/express/index.d.ts @@ -2,6 +2,8 @@ declare namespace Express { interface User { accessToken: string; refreshToken: string; + username: string; + _id?: number; } interface Request { diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..7079449 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1981 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@apidevtools/json-schema-ref-parser@^9.0.6": + version "9.1.2" + resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz#8ff5386b365d4c9faa7c8b566ff16a46a577d9b8" + integrity sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg== + dependencies: + "@jsdevtools/ono" "^7.1.3" + "@types/json-schema" "^7.0.6" + call-me-maybe "^1.0.1" + js-yaml "^4.1.0" + +"@apidevtools/openapi-schemas@^2.0.4": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz#9fa08017fb59d80538812f03fc7cac5992caaa17" + integrity sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ== + +"@apidevtools/swagger-methods@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz#b789a362e055b0340d04712eafe7027ddc1ac267" + integrity sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg== + +"@apidevtools/swagger-parser@10.0.3": + version "10.0.3" + resolved "https://registry.yarnpkg.com/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz#32057ae99487872c4dd96b314a1ab4b95d89eaf5" + integrity sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g== + dependencies: + "@apidevtools/json-schema-ref-parser" "^9.0.6" + "@apidevtools/openapi-schemas" "^2.0.4" + "@apidevtools/swagger-methods" "^3.0.2" + "@jsdevtools/ono" "^7.1.3" + call-me-maybe "^1.0.1" + z-schema "^5.0.1" + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@esbuild/aix-ppc64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537" + integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g== + +"@esbuild/android-arm64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9" + integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg== + +"@esbuild/android-arm@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995" + integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w== + +"@esbuild/android-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98" + integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg== + +"@esbuild/darwin-arm64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb" + integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA== + +"@esbuild/darwin-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0" + integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA== + +"@esbuild/freebsd-arm64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911" + integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw== + +"@esbuild/freebsd-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c" + integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw== + +"@esbuild/linux-arm64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5" + integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A== + +"@esbuild/linux-arm@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c" + integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg== + +"@esbuild/linux-ia32@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa" + integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig== + +"@esbuild/linux-loong64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5" + integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ== + +"@esbuild/linux-mips64el@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa" + integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA== + +"@esbuild/linux-ppc64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20" + integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg== + +"@esbuild/linux-riscv64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300" + integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg== + +"@esbuild/linux-s390x@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685" + integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ== + +"@esbuild/linux-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff" + integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw== + +"@esbuild/netbsd-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6" + integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ== + +"@esbuild/openbsd-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf" + integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ== + +"@esbuild/sunos-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f" + integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w== + +"@esbuild/win32-arm64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90" + integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ== + +"@esbuild/win32-ia32@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23" + integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ== + +"@esbuild/win32-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc" + integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ== + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jsdevtools/ono@^7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" + integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== + +"@mapbox/node-pre-gyp@^1.0.11": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa" + integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ== + dependencies: + detect-libc "^2.0.0" + https-proxy-agent "^5.0.0" + make-dir "^3.1.0" + node-fetch "^2.6.7" + nopt "^5.0.0" + npmlog "^5.0.1" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.11" + +"@prisma/client@^5.4.2": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.14.0.tgz#dadca5bb1137ddcebb454bbdaf89423823d3363f" + integrity sha512-akMSuyvLKeoU4LeyBAUdThP/uhVP3GuLygFE3MlYzaCb3/J8SfsYBE5PkaFuLuVpLyA6sFoW+16z/aPhNAESqg== + +"@prisma/debug@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.14.0.tgz#1227c705893c38284f7c63d72441480ebaa12605" + integrity sha512-iq56qBZuFfX3fCxoxT8gBX33lQzomBU0qIUaEj1RebsKVz1ob/BVH1XSBwwwvRVtZEV1b7Fxx2eVu34Ge/mg3w== + +"@prisma/engines-version@5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48": + version "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48" + resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48.tgz#019c3c75a5c3276e580685fe48cdbfd181176858" + integrity sha512-ip6pNkRo1UxWv+6toxNcYvItNYaqQjXdFNGJ+Nuk2eYtRoEdoF13wxo7/jsClJFFenMPVNVqXQDV0oveXnR1cA== + +"@prisma/engines@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.14.0.tgz#2ee91dd2220a726c27c906fbea788bbb3efdac6e" + integrity sha512-lgxkKZ6IEygVcw6IZZUlPIfLQ9hjSYAtHjZ5r64sCLDgVzsPFCi2XBBJgzPMkOQ5RHzUD4E/dVdpn9+ez8tk1A== + dependencies: + "@prisma/debug" "5.14.0" + "@prisma/engines-version" "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48" + "@prisma/fetch-engine" "5.14.0" + "@prisma/get-platform" "5.14.0" + +"@prisma/fetch-engine@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-5.14.0.tgz#45297c118d4ec3fea55129886edd5a429da1f6da" + integrity sha512-VrheA9y9DMURK5vu8OJoOgQpxOhas3qF0IBHJ8G/0X44k82kc8E0w98HCn2nhnbOOMwbWsJWXfLC2/F8n5u0gQ== + dependencies: + "@prisma/debug" "5.14.0" + "@prisma/engines-version" "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48" + "@prisma/get-platform" "5.14.0" + +"@prisma/get-platform@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-5.14.0.tgz#69112d3dde61905f59a65ed818f153e153ca40f0" + integrity sha512-/yAyBvcEjRv41ynZrhdrPtHgk47xLRRq/o5eWGcUpBJ1YrUZTYB8EoPiopnP7iQrMATK8stXQdPOoVlrzuTQZw== + dependencies: + "@prisma/debug" "5.14.0" + +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/bcrypt@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@types/bcrypt/-/bcrypt-5.0.2.tgz#22fddc11945ea4fbc3655b3e8b8847cc9f811477" + integrity sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ== + dependencies: + "@types/node" "*" + +"@types/body-parser@*": + version "1.19.5" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" + integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.38" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== + dependencies: + "@types/node" "*" + +"@types/cors@^2.8.17": + version "2.8.17" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b" + integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA== + dependencies: + "@types/node" "*" + +"@types/express-serve-static-core@^4.17.33": + version "4.19.3" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.3.tgz#e469a13e4186c9e1c0418fb17be8bc8ff1b19a7a" + integrity sha512-KOzM7MhcBFlmnlr/fzISFF5vGWVSvN6fTd4T+ExOt08bA/dA5kpSzY52nMsI1KDFmUREpJelPYyuslLRSjjgCg== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + "@types/send" "*" + +"@types/express-session@^1.18.0": + version "1.18.0" + resolved "https://registry.yarnpkg.com/@types/express-session/-/express-session-1.18.0.tgz#7c6f25c3604b28d6bc08a2e3929997bbc7672fa2" + integrity sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA== + dependencies: + "@types/express" "*" + +"@types/express@*", "@types/express@^4.17.21": + version "4.17.21" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/http-errors@*": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" + integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== + +"@types/json-schema@^7.0.6": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/jsonwebtoken@^9.0.6": + version "9.0.6" + resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz#d1af3544d99ad992fb6681bbe60676e06b032bd3" + integrity sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw== + dependencies: + "@types/node" "*" + +"@types/mime@^1": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== + +"@types/morgan@^1.9.9": + version "1.9.9" + resolved "https://registry.yarnpkg.com/@types/morgan/-/morgan-1.9.9.tgz#d60dec3979e16c203a000159daa07d3fb7270d7f" + integrity sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ== + dependencies: + "@types/node" "*" + +"@types/node@*", "@types/node@^20.12.13": + version "20.12.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.13.tgz#90ed3b8a4e52dd3c5dc5a42dde5b85b74ad8ed88" + integrity sha512-gBGeanV41c1L171rR7wjbMiEpEI/l5XFQdLLfhr/REwpgDy/4U8y89+i8kRiLzDyZdOkXh+cRaTetUnCYutoXA== + dependencies: + undici-types "~5.26.4" + +"@types/oauth@*": + version "0.9.5" + resolved "https://registry.yarnpkg.com/@types/oauth/-/oauth-0.9.5.tgz#acc4209bfa1c8d7d3aaf2c9ad0b32216a29616c1" + integrity sha512-+oQ3C2Zx6ambINOcdIARF5Z3Tu3x//HipE889/fqo3sgpQZbe9c6ExdQFtN6qlhpR7p83lTZfPJt0tCAW29dog== + dependencies: + "@types/node" "*" + +"@types/passport-google-oauth20@^2.0.16": + version "2.0.16" + resolved "https://registry.yarnpkg.com/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.16.tgz#9e39c1203d56496d89392538e6109626e253bc28" + integrity sha512-ayXK2CJ7uVieqhYOc6k/pIr5pcQxOLB6kBev+QUGS7oEZeTgIs1odDobXRqgfBPvXzl0wXCQHftV5220czZCPA== + dependencies: + "@types/express" "*" + "@types/passport" "*" + "@types/passport-oauth2" "*" + +"@types/passport-oauth2@*": + version "1.4.17" + resolved "https://registry.yarnpkg.com/@types/passport-oauth2/-/passport-oauth2-1.4.17.tgz#d5d54339d44f6883d03e69dc0cc0e2114067abb4" + integrity sha512-ODiAHvso6JcWJ6ZkHHroVp05EHGhqQN533PtFNBkg8Fy5mERDqsr030AX81M0D69ZcaMvhF92SRckEk2B0HYYg== + dependencies: + "@types/express" "*" + "@types/oauth" "*" + "@types/passport" "*" + +"@types/passport@*", "@types/passport@^1.0.16": + version "1.0.16" + resolved "https://registry.yarnpkg.com/@types/passport/-/passport-1.0.16.tgz#5a2918b180a16924c4d75c31254c31cdca5ce6cf" + integrity sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A== + dependencies: + "@types/express" "*" + +"@types/qs@*": + version "6.9.15" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" + integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== + +"@types/range-parser@*": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== + +"@types/send@*": + version "0.17.4" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + +"@types/serve-static@*": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" + integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== + dependencies: + "@types/http-errors" "*" + "@types/node" "*" + "@types/send" "*" + +"@types/swagger-jsdoc@^6.0.4": + version "6.0.4" + resolved "https://registry.yarnpkg.com/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz#bb4f60f3a5f103818e022f2e29ff8935113fb83d" + integrity sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ== + +"@types/swagger-ui-express@^4.1.6": + version "4.1.6" + resolved "https://registry.yarnpkg.com/@types/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz#d0929e3fabac1a96a8a9c6c7ee8d42362c5cdf48" + integrity sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg== + dependencies: + "@types/express" "*" + "@types/serve-static" "*" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-walk@^8.1.1: + version "8.3.2" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" + integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== + +acorn@^8.4.1: + version "8.11.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +append-field@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56" + integrity sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw== + +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +are-we-there-yet@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" + integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64url@3.x.x: + version "3.0.1" + resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" + integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== + +basic-auth@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" + integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== + dependencies: + safe-buffer "5.1.2" + +bcrypt@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-5.1.1.tgz#0f732c6dcb4e12e5b70a25e326a72965879ba6e2" + integrity sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.11" + node-addon-api "^5.0.0" + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +body-parser@1.20.2: + version "1.20.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" + integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== + dependencies: + bytes "3.1.2" + content-type "~1.0.5" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.2" + type-is "~1.6.18" + unpipe "1.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +busboy@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== + dependencies: + streamsearch "^1.1.0" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + +call-me-maybe@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" + integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== + +chokidar@^3.5.2: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + 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" + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +commander@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75" + integrity sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q== + +commander@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +concat-stream@^1.5.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +console-control-strings@^1.0.0, console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4, content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie-signature@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.7.tgz#ab5dd7ab757c54e60f37ef6550f481c426d10454" + integrity sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA== + +cookie@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cors@^2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@4, debug@^4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +depd@2.0.0, depd@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-libc@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" + integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +doctrine@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dotenv@^16.3.1: + version "16.4.5" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" + integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== + +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +esbuild@~0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.2.tgz#9d6b2386561766ee6b5a55196c6d766d28c87ea1" + integrity sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g== + optionalDependencies: + "@esbuild/aix-ppc64" "0.20.2" + "@esbuild/android-arm" "0.20.2" + "@esbuild/android-arm64" "0.20.2" + "@esbuild/android-x64" "0.20.2" + "@esbuild/darwin-arm64" "0.20.2" + "@esbuild/darwin-x64" "0.20.2" + "@esbuild/freebsd-arm64" "0.20.2" + "@esbuild/freebsd-x64" "0.20.2" + "@esbuild/linux-arm" "0.20.2" + "@esbuild/linux-arm64" "0.20.2" + "@esbuild/linux-ia32" "0.20.2" + "@esbuild/linux-loong64" "0.20.2" + "@esbuild/linux-mips64el" "0.20.2" + "@esbuild/linux-ppc64" "0.20.2" + "@esbuild/linux-riscv64" "0.20.2" + "@esbuild/linux-s390x" "0.20.2" + "@esbuild/linux-x64" "0.20.2" + "@esbuild/netbsd-x64" "0.20.2" + "@esbuild/openbsd-x64" "0.20.2" + "@esbuild/sunos-x64" "0.20.2" + "@esbuild/win32-arm64" "0.20.2" + "@esbuild/win32-ia32" "0.20.2" + "@esbuild/win32-x64" "0.20.2" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +express-session@^1.18.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.18.0.tgz#a6ae39d9091f2efba5f20fc5c65a3ce7c9ce16a3" + integrity sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ== + dependencies: + cookie "0.6.0" + cookie-signature "1.0.7" + debug "2.6.9" + depd "~2.0.0" + on-headers "~1.0.2" + parseurl "~1.3.3" + safe-buffer "5.2.1" + uid-safe "~2.1.5" + +express@^4.18.2: + version "4.19.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" + integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.2" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.6.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + +get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +get-tsconfig@^4.7.5: + version "4.7.5" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.5.tgz#5e012498579e9a6947511ed0cd403272c7acbbaf" + integrity sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw== + dependencies: + resolve-pkg-maps "^1.0.0" + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore-by-default@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-email@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-email/-/is-email-1.0.2.tgz#51a618e2ddc895988ceb550df9f587b3607560e5" + integrity sha512-UojUgD2EhDTBQ2SGKwrK9edce5phRzgLsP+V5+Uu2Swi+uvjVXgH3zduM3HhT9iaC/9Kq19/TYUbP0jPoi6ioA== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-uuid@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-uuid/-/is-uuid-1.0.2.tgz#ad1898ddf154947c25c8e54966f48604e9caecc4" + integrity sha512-tCByphFcJgf2qmiMo5hMCgNAquNSagOetVetDvBXswGkNfoyEMvGH1yDlF8cbZbKnbVBr4Y5/rlpMz9umxyBkQ== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsonwebtoken@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" + integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^7.5.4" + +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== + +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== + +lodash.mergewith@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" + integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== + +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== + +make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp@^0.5.4: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +moment-timezone@^0.5.45: + version "0.5.45" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.45.tgz#cb685acd56bac10e69d93c536366eb65aa6bcf5c" + integrity sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ== + dependencies: + moment "^2.29.4" + +moment@^2.29.4: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + +morgan@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" + integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== + dependencies: + basic-auth "~2.0.1" + debug "2.6.9" + depd "~2.0.0" + on-finished "~2.3.0" + on-headers "~1.0.2" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multer@^1.4.5-lts.1: + version "1.4.5-lts.1" + resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.5-lts.1.tgz#803e24ad1984f58edffbc79f56e305aec5cfd1ac" + integrity sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ== + dependencies: + append-field "^1.0.0" + busboy "^1.0.0" + concat-stream "^1.5.2" + mkdirp "^0.5.4" + object-assign "^4.1.1" + type-is "^1.6.4" + xtend "^4.0.0" + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +node-addon-api@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" + integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== + +node-fetch@^2.6.7: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +nodemon@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.2.tgz#e4041ef00b930c5bdc1ab68d897a88eb7b17c8c2" + integrity sha512-/Ib/kloefDy+N0iRTxIUzyGcdW9lzlnca2Jsa5w73bs3npXjg+WInmiX6VY13mIb6SykkthYX/U5t0ukryGqBw== + 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" + +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npmlog@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== + dependencies: + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" + +oauth@0.10.x: + version "0.10.0" + resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.10.0.tgz#3551c4c9b95c53ea437e1e21e46b649482339c58" + integrity sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q== + +object-assign@^4, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.13.1: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +passport-google-oauth20@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz#0d241b2d21ebd3dc7f2b60669ec4d587e3a674ef" + integrity sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ== + dependencies: + passport-oauth2 "1.x.x" + +passport-oauth2@1.x.x: + version "1.8.0" + resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.8.0.tgz#55725771d160f09bbb191828d5e3d559eee079c8" + integrity sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA== + dependencies: + base64url "3.x.x" + oauth "0.10.x" + passport-strategy "1.x.x" + uid2 "0.0.x" + utils-merge "1.x.x" + +passport-strategy@1.x.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" + integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== + +passport@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.7.0.tgz#3688415a59a48cf8068417a8a8092d4492ca3a05" + integrity sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + utils-merge "^1.0.1" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +pause@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" + integrity sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +prisma@^5.4.2: + version "5.14.0" + resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.14.0.tgz#ffc4696a43b044b636c3303b7aa98c13c2ade4dd" + integrity sha512-gCNZco7y5XtjrnQYeDJTiVZmT/ncqCr5RY1/Cf8X2wgLRmyh9ayPAGBNziI4qEE4S6SxCH5omQLVo9lmURaJ/Q== + dependencies: + "@prisma/engines" "5.14.0" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +pstree.remy@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== + +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +random-bytes@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" + integrity sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ== + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +readable-stream@^2.2.2: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^6.0.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.5, semver@^7.5.3, semver@^7.5.4: + version "7.6.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +side-channel@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + +signal-exit@^3.0.0: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +simple-update-notifier@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" + integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== + dependencies: + semver "^7.5.3" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +superstruct@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" + integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== + +supports-color@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +swagger-jsdoc@^6.2.8: + version "6.2.8" + resolved "https://registry.yarnpkg.com/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz#6d33d9fb07ff4a7c1564379c52c08989ec7d0256" + integrity sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ== + dependencies: + commander "6.2.0" + doctrine "3.0.0" + glob "7.1.6" + lodash.mergewith "^4.6.2" + swagger-parser "^10.0.3" + yaml "2.0.0-1" + +swagger-parser@^10.0.3: + version "10.0.3" + resolved "https://registry.yarnpkg.com/swagger-parser/-/swagger-parser-10.0.3.tgz#04cb01c18c3ac192b41161c77f81e79309135d03" + integrity sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg== + dependencies: + "@apidevtools/swagger-parser" "10.0.3" + +swagger-ui-dist@>=5.0.0: + version "5.17.14" + resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz#e2c222e5bf9e15ccf80ec4bc08b4aaac09792fd6" + integrity sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw== + +swagger-ui-express@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz#7a00a18dd909574cb0d628574a299b9ba53d4d49" + integrity sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA== + dependencies: + swagger-ui-dist ">=5.0.0" + +tar@^6.1.11: + version "6.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +touch@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.1.tgz#097a23d7b161476435e5c1344a95c0f75b4a5694" + integrity sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tsx@^4.11.0: + version "4.11.0" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.11.0.tgz#fdd8ce7ccaa0a84aed64c11e2fc5da314e1d8d14" + integrity sha512-vzGGELOgAupsNVssAmZjbUDfdm/pWP4R+Kg8TVdsonxbXk0bEpE1qh0yV6/QxUVXaVlNemgcPajGdJJ82n3stg== + dependencies: + esbuild "~0.20.2" + get-tsconfig "^4.7.5" + optionalDependencies: + fsevents "~2.3.3" + +type-is@^1.6.4, type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== + +typescript@^5.4.5: + version "5.4.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" + integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== + +uid-safe@~2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a" + integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA== + dependencies: + random-bytes "~1.0.0" + +uid2@0.0.x: + version "0.0.4" + resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.4.tgz#033f3b1d5d32505f5ce5f888b9f3b667123c0a44" + integrity sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA== + +undefsafe@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" + integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +utils-merge@1.0.1, utils-merge@1.x.x, utils-merge@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +validator@^13.7.0: + version "13.12.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.12.0.tgz#7d78e76ba85504da3fee4fd1922b385914d4b35f" + integrity sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg== + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +xtend@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@2.0.0-1: + version "2.0.0-1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.0.0-1.tgz#8c3029b3ee2028306d5bcf396980623115ff8d18" + integrity sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ== + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +z-schema@^5.0.1: + version "5.0.6" + resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-5.0.6.tgz#46d6a687b15e4a4369e18d6cb1c7b8618fc256c5" + integrity sha512-+XR1GhnWklYdfr8YaZv/iu+vY+ux7V5DS5zH1DQf6bO5ufrt/5cgNhVO5qyhsjFXvsqQb/f08DWE9b6uPscyAg== + dependencies: + lodash.get "^4.4.2" + lodash.isequal "^4.5.0" + validator "^13.7.0" + optionalDependencies: + commander "^10.0.0" From 4aa7303e8b84be8a52c183a94d3927a7d1ff811a Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Fri, 31 May 2024 14:10:51 +0900 Subject: [PATCH 39/60] =?UTF-8?q?[#M11]=20refactor=20:=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EC=BD=94=EB=93=9C=EB=A5=BC=20=ED=83=80=EC=9E=85?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Product, Article, Comment 모델의 User필드를 필수값으로 변경 --- http/articles.http | 26 +- http/auth.http | 2 +- http/products.http | 24 +- package-lock.json | 17 + package.json | 4 +- .../migration.sql | 24 + prisma/schema.prisma | 21 +- src/controllers/articleController.ts | 114 ++- src/controllers/authController.ts | 21 +- src/controllers/commentController.ts | 57 +- src/controllers/imageController.ts | 10 +- src/controllers/productController.ts | 68 +- src/middlewares/authenticate.ts | 16 +- src/middlewares/errorHandler.ts | 7 +- src/routes/articleRoutes.ts | 33 +- src/routes/authRoutes.ts | 2 +- src/routes/productRoutes.ts | 28 +- src/services/articleService.ts | 39 +- src/services/authService.ts | 25 +- src/services/commentService.ts | 49 +- src/services/imageService.ts | 4 +- src/services/productService.ts | 49 +- src/structs.ts | 2 +- src/utils/asyncHandler.ts | 12 +- src/utils/tokens.ts | 18 +- yarn.lock | 780 ++++++++---------- 26 files changed, 747 insertions(+), 705 deletions(-) create mode 100644 prisma/migrations/20240531031414_make_user_id_required/migration.sql diff --git a/http/articles.http b/http/articles.http index d24ef42..58cd57c 100644 --- a/http/articles.http +++ b/http/articles.http @@ -9,7 +9,7 @@ GET http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da ### # 게시글 등록 POST http://localhost:3000/articles -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg4MjIxMCwiZXhwIjoxNzE2ODgzMTEwfQ.HKPt_52tCohwFBk5yESkDiChtWpqd7pf531uQsI47kY +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODU1MiwiZXhwIjoxNzE3MTI5NDUyfQ.OAcMKEyrlzrtCOlz4HXu3mmDdEQ0s-oYBlbvlHWAJUY Content-Type: application/json { @@ -20,8 +20,8 @@ Content-Type: application/json ### # 게시글 수정 -PATCH http://localhost:3000/articles/c058e3ae-00d2-4b5a-a0dc-acd284f03e7b -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 +PATCH http://localhost:3000/articles/dc196ae3-0d72-4f4d-9057-a83e6bece8bc +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODU1MiwiZXhwIjoxNzE3MTI5NDUyfQ.OAcMKEyrlzrtCOlz4HXu3mmDdEQ0s-oYBlbvlHWAJUY Content-Type: application/json { @@ -31,18 +31,18 @@ Content-Type: application/json ### # 게시글 삭제 -DELETE http://localhost:3000/articles/9c96039f-e56d-470e-847f-aa24b8da981c -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 +DELETE http://localhost:3000/articles/dc196ae3-0d72-4f4d-9057-a83e6bece8bc +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODU1MiwiZXhwIjoxNzE3MTI5NDUyfQ.OAcMKEyrlzrtCOlz4HXu3mmDdEQ0s-oYBlbvlHWAJUY ### # 게시글 좋아요 PATCH http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/like -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODU1MiwiZXhwIjoxNzE3MTI5NDUyfQ.OAcMKEyrlzrtCOlz4HXu3mmDdEQ0s-oYBlbvlHWAJUY ### # 게시글 좋아요 취소 PATCH http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da/unlike -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODU1MiwiZXhwIjoxNzE3MTI5NDUyfQ.OAcMKEyrlzrtCOlz4HXu3mmDdEQ0s-oYBlbvlHWAJUY @@ -53,13 +53,13 @@ GET http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments ### # 자유게시판 댓글 커서 조회 -GET http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments?cursor=4f9cd26c-09fa-441c-997f-2fdec0fb443e +GET http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments?cursor=2b3c4d5e-6f7g-8h9i-0j1k-2l3m4n5o6p7q ### # 자유게시판 댓글 등록 POST http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments Content-Type: application/json -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODU1MiwiZXhwIjoxNzE3MTI5NDUyfQ.OAcMKEyrlzrtCOlz4HXu3mmDdEQ0s-oYBlbvlHWAJUY { "content":"판다가 너무 귀여워요2" @@ -67,9 +67,9 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhd ### # 자유게시판 댓글 수정 -PATCH http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments/31599931-2aac-47fb-85ad-8de4c0a4a56d +PATCH http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments/1d896d0e-55e9-4075-ac77-4adde865f743 Content-Type: application/json -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODU1MiwiZXhwIjoxNzE3MTI5NDUyfQ.OAcMKEyrlzrtCOlz4HXu3mmDdEQ0s-oYBlbvlHWAJUY { "content":"판다가 너무 귀여워요 수정" @@ -77,5 +77,5 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhd ### # 자유게시판 댓글 삭제 -DELETE http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments/98b65e20-e12b-43fb-8b04-6525b019eb8b -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 \ No newline at end of file +DELETE http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments/1d896d0e-55e9-4075-ac77-4adde865f743 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODU1MiwiZXhwIjoxNzE3MTI5NDUyfQ.OAcMKEyrlzrtCOlz4HXu3mmDdEQ0s-oYBlbvlHWAJUY \ No newline at end of file diff --git a/http/auth.http b/http/auth.http index aeaf407..821ff0c 100644 --- a/http/auth.http +++ b/http/auth.http @@ -25,5 +25,5 @@ POST http://localhost:3000/auth/refresh-token Content-Type: application/json { - "refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjgsImlhdCI6MTcxNjc5Mzk0NywiZXhwIjoxNzE3Mzk4NzQ3fQ.bBxra1mgW2Pe4s9KcD_8Z5QmuFAIqZhjwKEupNpkXbs" + "refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODQ4MSwiZXhwIjoxNzE3NzMzMjgxfQ.d-h8rnnuG-lmptA_0ztr4XBDd45c32f73oWGGe_Rsak" } \ No newline at end of file diff --git a/http/products.http b/http/products.http index 39b37f6..a76a9ec 100644 --- a/http/products.http +++ b/http/products.http @@ -13,12 +13,12 @@ GET http://localhost:3000/products?keyword=판다 ### # 상품 상세 조회 -GET http://localhost:3000/products/d44e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 +GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc ### # 상품 등록 POST http://localhost:3000/products -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODc3NiwiZXhwIjoxNzE3MTI5Njc2fQ.1P-sxAljy-HP-1LQ3F53tJJLCry3--KdL6mJSZSy4bc Content-Type: application/json { @@ -32,7 +32,7 @@ Content-Type: application/json ### # 상품 수정 PATCH http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODc3NiwiZXhwIjoxNzE3MTI5Njc2fQ.1P-sxAljy-HP-1LQ3F53tJJLCry3--KdL6mJSZSy4bc Content-Type: application/json { @@ -45,17 +45,17 @@ Content-Type: application/json ### # 상품 삭제 DELETE http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODc3NiwiZXhwIjoxNzE3MTI5Njc2fQ.1P-sxAljy-HP-1LQ3F53tJJLCry3--KdL6mJSZSy4bc ### # 상품 좋아요 PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/like -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODc3NiwiZXhwIjoxNzE3MTI5Njc2fQ.1P-sxAljy-HP-1LQ3F53tJJLCry3--KdL6mJSZSy4bc ### # 상품 좋아요 취소 PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/unlike -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODc3NiwiZXhwIjoxNzE3MTI5Njc2fQ.1P-sxAljy-HP-1LQ3F53tJJLCry3--KdL6mJSZSy4bc ### # 상품 댓글 조회 @@ -63,12 +63,12 @@ GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments ### # 상품 댓글 커서 조회 -GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments?cursor=f81aac65-fb44-4973-8d6d-3789c6ba39d7 +GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments?cursor=2b3c4d5e-6f7g-8h9i-0j1k-2l3m4n5o6p7q ### # 상품 댓글 등록 POST http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODc3NiwiZXhwIjoxNzE3MTI5Njc2fQ.1P-sxAljy-HP-1LQ3F53tJJLCry3--KdL6mJSZSy4bc Content-Type: application/json { @@ -78,8 +78,8 @@ Content-Type: application/json ### # 상품 댓글 수정 -PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/536a7b1b-83c9-42c1-93b9-c4755e7fc8d6 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 +PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/3b2c5412-f7cd-454a-87d5-fee77aaab8d0 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODc3NiwiZXhwIjoxNzE3MTI5Njc2fQ.1P-sxAljy-HP-1LQ3F53tJJLCry3--KdL6mJSZSy4bc Content-Type: application/json { @@ -88,5 +88,5 @@ Content-Type: application/json ### # 상품 댓글 삭제 -DELETE http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/9d7d8a72-693e-44d3-bf72-889c9ebac0d9 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NDc2NywiZXhwIjoxNzE2ODc1NjY3fQ.chuRJN6EHR4x2r9-ocN1lKQKwYrSnZKYULaSgj5oU88 \ No newline at end of file +DELETE http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/comments/3b2c5412-f7cd-454a-87d5-fee77aaab8d0 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODc3NiwiZXhwIjoxNzE3MTI5Njc2fQ.1P-sxAljy-HP-1LQ3F53tJJLCry3--KdL6mJSZSy4bc \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index f9bc767..0fbfe52 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,8 +26,10 @@ "@types/cors": "^2.8.17", "@types/express": "^4.17.21", "@types/express-session": "^1.18.0", + "@types/is-email": "^1.0.0", "@types/jsonwebtoken": "^9.0.6", "@types/morgan": "^1.9.9", + "@types/multer": "^1.4.11", "@types/node": "^20.12.13", "@types/passport": "^1.0.16", "@types/passport-google-oauth20": "^2.0.16", @@ -668,6 +670,12 @@ "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "dev": true }, + "node_modules/@types/is-email": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/is-email/-/is-email-1.0.0.tgz", + "integrity": "sha512-b/76ooKpYY/b+oPrOuc/pmM5eag+ZlzctPsKcRCIKs+TFzh0FL58OeXtSPkbXt3uKNK84YCKHmjnoREtwve5Kg==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -697,6 +705,15 @@ "@types/node": "*" } }, + "node_modules/@types/multer": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.11.tgz", + "integrity": "sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/node": { "version": "20.12.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.13.tgz", diff --git a/package.json b/package.json index 7000a0a..62588df 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,10 @@ "@types/cors": "^2.8.17", "@types/express": "^4.17.21", "@types/express-session": "^1.18.0", + "@types/is-email": "^1.0.0", "@types/jsonwebtoken": "^9.0.6", "@types/morgan": "^1.9.9", + "@types/multer": "^1.4.11", "@types/node": "^20.12.13", "@types/passport": "^1.0.16", "@types/passport-google-oauth20": "^2.0.16", @@ -42,6 +44,6 @@ "dev": "nodemon" }, "prisma": { - "seed": "node prisma/seed.ts" + "seed": "tsx prisma/seed.ts" } } diff --git a/prisma/migrations/20240531031414_make_user_id_required/migration.sql b/prisma/migrations/20240531031414_make_user_id_required/migration.sql new file mode 100644 index 0000000..ca4905d --- /dev/null +++ b/prisma/migrations/20240531031414_make_user_id_required/migration.sql @@ -0,0 +1,24 @@ +/* + Warnings: + + - Made the column `userId` on table `Article` required. This step will fail if there are existing NULL values in that column. + - Made the column `userId` on table `Product` required. This step will fail if there are existing NULL values in that column. + +*/ +-- DropForeignKey +ALTER TABLE "Article" DROP CONSTRAINT "Article_userId_fkey"; + +-- DropForeignKey +ALTER TABLE "Product" DROP CONSTRAINT "Product_userId_fkey"; + +-- AlterTable +ALTER TABLE "Article" ALTER COLUMN "userId" SET NOT NULL; + +-- AlterTable +ALTER TABLE "Product" ALTER COLUMN "userId" SET NOT NULL; + +-- AddForeignKey +ALTER TABLE "Product" ADD CONSTRAINT "Product_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Article" ADD CONSTRAINT "Article_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 3915113..0ce8237 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,8 +1,3 @@ -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema - -// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? -// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init generator client { provider = "prisma-client-js" } @@ -25,7 +20,7 @@ model User { products Product[] articles Article[] favorites Favorite[] - Comment Comment[] + comment Comment[] } model Product { @@ -39,9 +34,9 @@ model Product { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt comments Comment[] - Image Image[] - User User? @relation(fields: [userId], references: [id]) - userId Int? + image Image[] + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + userId Int favorites Favorite[] } @@ -55,9 +50,9 @@ model Article { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt comments Comment[] - Image Image[] - User User? @relation(fields: [userId], references: [id]) - userId Int? + image Image[] + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + userId Int favorites Favorite[] } @@ -72,7 +67,7 @@ model Comment { article Article? @relation(fields: [articleId], references: [id], onDelete: SetNull) articleId String? userId Int - User User @relation(fields: [userId], references: [id], onDelete: Cascade) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([productId]) @@index([articleId]) diff --git a/src/controllers/articleController.ts b/src/controllers/articleController.ts index 494ee34..f04c401 100644 --- a/src/controllers/articleController.ts +++ b/src/controllers/articleController.ts @@ -1,8 +1,8 @@ +import { Prisma } from "@prisma/client"; import { NextFunction, Request, Response } from "express"; import { assert } from "superstruct"; import * as articleService from "../services/articleService"; import { CreateArticle, PatchArticle } from "../structs"; -import asyncHandler from "../utils/asyncHandler"; import AppError from "../utils/errors"; interface GetArticlesQuery { @@ -16,42 +16,36 @@ interface UserRequest extends Request { userId: number; } -interface ArticleRequest extends Request { - userId: number; - body: { - title: string; - content: string; - imageUrl?: string; - }; -} - // GET /articles -export const getArticles = asyncHandler(async (req: Request<{}, {}, {}, GetArticlesQuery>, res: Response) => { - const { offset = "0", limit = "10", orderBy = "recent", keyword = "" } = req.query as { [key: string]: string }; +export const getArticles = async (req: Request<{}, {}, {}, GetArticlesQuery>, res: Response) => { + const { offset = "0", limit = "10", orderBy = "recent", keyword = "" } = req.query; const offsetNumber = parseInt(offset, 10); const limitNumber = parseInt(limit, 10); const articles = await articleService.getArticles({ offset: offsetNumber, limit: limitNumber, orderBy, keyword }); const bestArticles = await articleService.getBestArticles(); res.send({ articles, bestArticles }); -}); +}; // POST /articles -export const createArticle = asyncHandler(async (req: ArticleRequest, res: Response) => { +export const createArticle = async (req: UserRequest, res: Response) => { assert(req.body, CreateArticle); const { userId } = req; - const article = await articleService.createArticle({ ...req.body, userId }); + + const articleData: Omit = req.body; + + const article = await articleService.createArticle(userId, articleData); res.status(201).send(article); -}); +}; // GET /articles/:id -export const getArticleById = asyncHandler(async (req: Request<{ id: string }>, res: Response) => { +export const getArticleById = async (req: Request<{ id: string }>, res: Response): Promise => { const { id } = req.params; const article = await articleService.getArticleById(id); res.send(article); -}); +}; // PATCH /articles/:id -export const updateArticle = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { +export const updateArticle = async (req: UserRequest & Request<{ id: string }>, res: Response): Promise => { assert(req.body, PatchArticle); const { id: articleId } = req.params; const { userId } = req; @@ -60,57 +54,57 @@ export const updateArticle = asyncHandler(async (req: UserRequest & Request<{ id res.send(updatedArticle); } catch (error) { if (error instanceof AppError) { - return res.status(error.statusCode).json({ message: error.message }); + res.status(error.statusCode).json({ message: error.message }); + return; } + throw error; } -}); +}; + // DELETE /articles/:id -export const deleteArticle = asyncHandler( - async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { - const { id: articleId } = req.params; - const { userId } = req; - try { - await articleService.deleteArticle(articleId, userId); - res.sendStatus(204); - } catch (error) { - if (error instanceof AppError) { - return res.status(error.statusCode).json({ message: error.message }); - } - next(error); +export const deleteArticle = async (req: UserRequest & Request<{ id: string }>, res: Response): Promise => { + const { id: articleId } = req.params; + const { userId } = req; + try { + await articleService.deleteArticle(articleId, userId); + res.sendStatus(204); + } catch (error) { + if (error instanceof AppError) { + res.status(error.statusCode).json({ message: error.message }); + return; } + throw error; } -); +}; // POST /articles/:id/like -export const likeArticle = asyncHandler( - async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { - const { id: articleId } = req.params; - const { userId } = req; - try { - const updatedArticle = await articleService.likeArticle(articleId, userId); - res.send(updatedArticle); - } catch (error) { - if (error instanceof AppError) { - return res.status(error.statusCode).json({ message: error.message }); - } - next(error); +export const likeArticle = async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { + const { id: articleId } = req.params; + const { userId } = req; + try { + const updatedArticle = await articleService.likeArticle(articleId, userId); + res.send(updatedArticle); + } catch (error) { + if (error instanceof AppError) { + res.status(error.statusCode).json({ message: error.message }); + return; } + next(error); } -); +}; // POST /articles/:id/unlike -export const unlikeArticle = asyncHandler( - async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { - const { id: articleId } = req.params; - const { userId } = req; - try { - const updatedArticle = await articleService.unlikeArticle(articleId, userId); - res.send(updatedArticle); - } catch (error) { - if (error instanceof AppError) { - return res.status(error.statusCode).json({ message: error.message }); - } - next(error); +export const unlikeArticle = async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { + const { id: articleId } = req.params; + const { userId } = req; + try { + const updatedArticle = await articleService.unlikeArticle(articleId, userId); + res.send(updatedArticle); + } catch (error) { + if (error instanceof AppError) { + res.status(error.statusCode).json({ message: error.message }); + return; } + next(error); } -); +}; diff --git a/src/controllers/authController.ts b/src/controllers/authController.ts index 428ebbf..07a64e6 100644 --- a/src/controllers/authController.ts +++ b/src/controllers/authController.ts @@ -16,7 +16,8 @@ export const signUp = async (req: Request, res: Response) => { const existingUser = await findUserByEmail(email); if (existingUser) { - return res.status(400).json({ message: "이미 가입된 이메일입니다." }); + res.status(400).json({ message: "이미 가입된 이메일입니다." }); + return; } await createUser(email, password, name, nickname); @@ -30,13 +31,15 @@ export const signIn = async (req: Request, res: Response) => { const user = await findUserByEmail(email); if (!user || !user.password) { - return res.status(401).json({ message: "이메일과 비밀번호를 확인해주세요." }); + res.status(401).json({ message: "이메일과 비밀번호를 확인해주세요." }); + return; } const isPasswordValid = await validatePassword(password, user.password); if (!isPasswordValid) { - return res.status(401).json({ message: "이메일과 비밀번호를 확인해주세요." }); + res.status(401).json({ message: "이메일과 비밀번호를 확인해주세요." }); + return; } const accessToken = generateAccessToken(user); @@ -49,7 +52,8 @@ export const refreshToken = async (req: Request, res: Response) => { const { refreshToken } = req.body; if (!refreshToken) { - return res.status(401).json({ message: "토큰은 필수값입니다." }); + res.status(401).json({ message: "토큰은 필수값입니다." }); + return; } try { @@ -58,20 +62,23 @@ export const refreshToken = async (req: Request, res: Response) => { const user = await findUserById(decoded.userId); if (!user) { - return res.status(401).json({ message: "유효하지 않은 토큰입니다." }); + res.status(401).json({ message: "유효하지 않은 토큰입니다." }); + return; } const accessToken = generateAccessToken(user); res.json({ accessToken, refreshToken: newRefreshToken }); } catch (error) { - return res.status(401).json({ message: "유효하지 않은 토큰입니다." }); + res.status(401).json({ message: "유효하지 않은 토큰입니다." }); + return; } }; export const googleCallback = (req: Request, res: Response, next: NextFunction) => { if (!req.user) { - return next(new Error("사용자 정보를 찾을 수 없습니다.")); + next(new Error("사용자 정보를 찾을 수 없습니다.")); + return; } const { accessToken, refreshToken } = req.user; res.json({ accessToken, refreshToken }); diff --git a/src/controllers/commentController.ts b/src/controllers/commentController.ts index f73fc09..44180ee 100644 --- a/src/controllers/commentController.ts +++ b/src/controllers/commentController.ts @@ -1,53 +1,76 @@ +import { Request, Response } from "express"; import { assert } from "superstruct"; -import * as commentService from "../services/commentService.js"; -import { CreateComment, PatchComment } from "../structs.js"; -import asyncHandler from "../utils/asyncHandler.js"; +import * as commentService from "../services/commentService"; +import { CreateComment, PatchComment } from "../structs"; -export const getCommentsByProductId = asyncHandler(async (req, res) => { +interface UserRequest extends Request { + userId: number; +} + +// GET /products/:id/comments +export const getCommentsByProductId = async ( + req: Request<{ id: string }, {}, {}, { cursor?: string }>, + res: Response +) => { const { id: productId } = req.params; const { cursor } = req.query; const comments = await commentService.getCommentsByProductId(productId, cursor); res.send(comments); -}); +}; -export const getCommentsByArticleId = asyncHandler(async (req, res) => { +// GET /articles/:id/comments +export const getCommentsByArticleId = async ( + req: Request<{ id: string }, {}, {}, { cursor?: string }>, + res: Response +) => { const { id: articleId } = req.params; const { cursor } = req.query; const comments = await commentService.getCommentsByArticleId(articleId, cursor); res.send(comments); -}); +}; -export const createComment = asyncHandler(async (req, res) => { +// POST /comments +export const createComment = async (req: UserRequest, res: Response) => { assert(req.body, CreateComment); const { userId } = req; - const commentData = { ...req.body, - ...req.params, userId, }; const comment = await commentService.createComment(commentData); res.status(201).send(comment); -}); +}; -export const updateComment = asyncHandler(async (req, res) => { +// PATCH /comments/:commentId +export const updateComment = async (req: UserRequest & Request<{ commentId: string }>, res: Response) => { assert(req.body, PatchComment); const { userId } = req; const { content } = req.body; const { commentId } = req.params; + if (!commentId) { + res.status(400).json({ message: "존재하지 않는 댓글입니다." }); + return; + } + + if (!content) { + res.status(400).json({ message: "댓글 내용은 필수값입니다." }); + return; + } + try { const updatedComment = await commentService.updateComment(commentId, userId, content); res.send(updatedComment); } catch (error) { - res.status(403).json({ message: error.message }); + res.status(403).json({ message: (error as Error).message }); } -}); +}; -export const deleteComment = asyncHandler(async (req, res) => { +// DELETE /comments/:commentId +export const deleteComment = async (req: UserRequest & Request<{ commentId: string }>, res: Response) => { const { commentId } = req.params; const { userId } = req; @@ -55,6 +78,6 @@ export const deleteComment = asyncHandler(async (req, res) => { await commentService.deleteComment(commentId, userId); res.sendStatus(204); } catch (error) { - res.status(403).json({ message: error.message }); + res.status(403).json({ message: (error as Error).message }); } -}); +}; diff --git a/src/controllers/imageController.ts b/src/controllers/imageController.ts index 76a3bd5..6eac983 100644 --- a/src/controllers/imageController.ts +++ b/src/controllers/imageController.ts @@ -1,13 +1,13 @@ -import * as imageService from "../services/imageService.js"; -import asyncHandler from "../utils/asyncHandler.js"; +import { Request, Response } from "express"; +import * as imageService from "../services/imageService"; -export const uploadImage = asyncHandler(async (req, res) => { +export const uploadImage = async (req: Request, res: Response) => { const file = req.file; try { const imageUrl = await imageService.uploadImage(file); res.status(200).json({ url: imageUrl }); } catch (error) { - res.status(400).send(error.message); + res.status(400).send((error as Error).message); } -}); +}; diff --git a/src/controllers/productController.ts b/src/controllers/productController.ts index 9467511..7e48691 100644 --- a/src/controllers/productController.ts +++ b/src/controllers/productController.ts @@ -1,28 +1,45 @@ +import { NextFunction, Request, Response } from "express"; import { assert } from "superstruct"; -import * as productService from "../services/productService.js"; -import { CreateProduct, PatchProduct } from "../structs.js"; -import asyncHandler from "../utils/asyncHandler.js"; +import * as productService from "../services/productService"; +import { CreateProduct, PatchProduct } from "../structs"; -export const getProducts = asyncHandler(async (req, res) => { - const { offset = 0, limit = 10, orderBy = "recent", keyword = "" } = req.query; - const products = await productService.getProducts({ offset, limit, orderBy, keyword }); +interface UserRequest extends Request { + userId: number; +} + +// GET /products +export const getProducts = async ( + req: Request<{}, {}, {}, { offset?: string; limit?: string; orderBy?: string; keyword?: string }>, + res: Response +) => { + const { offset = "0", limit = "10", orderBy = "recent", keyword = "" } = req.query; + const offsetNumber = parseInt(offset, 10); + const limitNumber = parseInt(limit, 10); + const products = await productService.getProducts({ offset: offsetNumber, limit: limitNumber, orderBy, keyword }); res.send(products); -}); +}; -export const createProduct = asyncHandler(async (req, res) => { +// POST /products +export const createProduct = async (req: UserRequest, res: Response) => { assert(req.body, CreateProduct); const { userId } = req; - const product = await productService.createProduct({ ...req.body, userId }); + const productData = { + ...req.body, + user: { connect: { id: userId } }, + }; + const product = await productService.createProduct(productData); res.status(201).send(product); -}); +}; -export const getProductById = asyncHandler(async (req, res) => { +// GET /products/:id +export const getProductById = async (req: Request<{ id: string }>, res: Response) => { const { id } = req.params; const product = await productService.getProductById(id); res.send(product); -}); +}; -export const updateProduct = asyncHandler(async (req, res) => { +// PATCH /products/:id +export const updateProduct = async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { assert(req.body, PatchProduct); const { id: productId } = req.params; @@ -32,11 +49,12 @@ export const updateProduct = asyncHandler(async (req, res) => { const updatedProduct = await productService.updateProduct(productId, userId, req.body); res.send(updatedProduct); } catch (error) { - res.status(403).json({ message: error.message }); + res.status(403).json({ message: (error as Error).message }); } -}); +}; -export const deleteProduct = asyncHandler(async (req, res) => { +// DELETE /products/:id +export const deleteProduct = async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { const { id: productId } = req.params; const { userId } = req; @@ -44,11 +62,12 @@ export const deleteProduct = asyncHandler(async (req, res) => { await productService.deleteProduct(productId, userId); res.sendStatus(204); } catch (error) { - res.status(403).json({ message: error.message }); + res.status(403).json({ message: (error as Error).message }); } -}); +}; -export const likeProduct = asyncHandler(async (req, res) => { +// POST /products/:id/like +export const likeProduct = async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { const { id: productId } = req.params; const { userId } = req; @@ -56,11 +75,12 @@ export const likeProduct = asyncHandler(async (req, res) => { const updatedProduct = await productService.likeProduct(productId, userId); res.send(updatedProduct); } catch (error) { - res.status(400).json({ message: error.message }); + res.status(400).json({ message: (error as Error).message }); } -}); +}; -export const unlikeProduct = asyncHandler(async (req, res) => { +// POST /products/:id/unlike +export const unlikeProduct = async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { const { id: productId } = req.params; const { userId } = req; @@ -68,6 +88,6 @@ export const unlikeProduct = asyncHandler(async (req, res) => { const updatedProduct = await productService.unlikeProduct(productId, userId); res.send(updatedProduct); } catch (error) { - res.status(400).json({ message: error.message }); + res.status(400).json({ message: (error as Error).message }); } -}); +}; diff --git a/src/middlewares/authenticate.ts b/src/middlewares/authenticate.ts index cb54af3..aaaf14d 100644 --- a/src/middlewares/authenticate.ts +++ b/src/middlewares/authenticate.ts @@ -1,21 +1,27 @@ import dotenv from "dotenv"; +import { NextFunction, Request, RequestHandler, Response } from "express"; import jwt from "jsonwebtoken"; dotenv.config(); -const JWT_SECRET = process.env.JWT_SECRET; +const JWT_SECRET = process.env.JWT_SECRET || "your_secret_key"; -const authenticate = (req, res, next) => { +export interface UserRequest extends Request { + userId: number; +} + +const authenticate: RequestHandler = (req: Request, res: Response, next: NextFunction): void => { const authHeader = req.headers.authorization; if (!authHeader) { - return res.status(401).json({ message: "인증 토큰이 제공되지 않았습니다." }); + res.status(401).json({ message: "인증 토큰이 제공되지 않았습니다." }); + return; } const token = authHeader.split(" ")[1]; try { - const decoded = jwt.verify(token, JWT_SECRET); - req.userId = decoded.userId; + const decoded = jwt.verify(token, JWT_SECRET) as { userId: number }; + (req as UserRequest).userId = decoded.userId; next(); } catch (error) { res.status(401).json({ message: "올바르지 않은 토큰입니다." }); diff --git a/src/middlewares/errorHandler.ts b/src/middlewares/errorHandler.ts index c01422f..3f2344c 100644 --- a/src/middlewares/errorHandler.ts +++ b/src/middlewares/errorHandler.ts @@ -1,8 +1,9 @@ -import AppError from "../utils/errors.js"; +import { NextFunction, Request, Response } from "express"; +import AppError from "../utils/errors"; -const errorHandler = (err, req, res, next) => { +const errorHandler = (err: Error, req: Request, res: Response, next: NextFunction) => { console.error("Error handler triggered:", err.stack); - console.log("Response object:", res); + if (err instanceof AppError) { res.status(err.statusCode).json({ status: err.status, diff --git a/src/routes/articleRoutes.ts b/src/routes/articleRoutes.ts index c2d9e4d..09005a2 100644 --- a/src/routes/articleRoutes.ts +++ b/src/routes/articleRoutes.ts @@ -1,9 +1,9 @@ -import express from "express"; -import * as articleController from "../controllers/articleController.js"; -import * as commentController from "../controllers/commentController.js"; -import authenticate from "../middlewares/authenticate.js"; +import express, { Request } from "express"; +import * as articleController from "../controllers/articleController"; +import * as commentController from "../controllers/commentController"; +import authenticate, { UserRequest } from "../middlewares/authenticate"; +import asyncHandler from "../utils/asyncHandler"; const router = express.Router(); - /** * @swagger * tags: @@ -205,7 +205,10 @@ const router = express.Router(); * message: "유효하지 않은 토큰입니다." * */ -router.route("/").get(articleController.getArticles).post(authenticate, articleController.createArticle); +router + .route("/") + .get(asyncHandler(articleController.getArticles)) + .post(authenticate, asyncHandler(articleController.createArticle)); /** * @swagger * /articles/{id}: @@ -438,9 +441,9 @@ router.route("/").get(articleController.getArticles).post(authenticate, articleC */ router .route("/:id") - .get(articleController.getArticleById) - .patch(authenticate, articleController.updateArticle) - .delete(authenticate, articleController.deleteArticle); + .get(asyncHandler>(articleController.getArticleById)) + .patch(authenticate, asyncHandler>(articleController.updateArticle)) + .delete(authenticate, asyncHandler>(articleController.deleteArticle)); /** * @swagger @@ -525,7 +528,7 @@ router * type: string * example: "이미 좋아요 처리된 게시글입니다." */ -router.route("/:id/like").patch(authenticate, articleController.likeArticle); +router.route("/:id/like").patch(authenticate, asyncHandler(articleController.likeArticle)); /** * @swagger @@ -610,7 +613,7 @@ router.route("/:id/like").patch(authenticate, articleController.likeArticle); * type: string * example: "아직 좋아요 처리되지 않은 게시글입니다." */ -router.route("/:id/unlike").patch(authenticate, articleController.unlikeArticle); +router.route("/:id/unlike").patch(authenticate, asyncHandler(articleController.unlikeArticle)); /** * @swagger @@ -762,8 +765,8 @@ router.route("/:id/unlike").patch(authenticate, articleController.unlikeArticle) router .route("/:articleId/comments") - .get(commentController.getCommentsByProductId) - .post(authenticate, commentController.createComment); + .get(asyncHandler(commentController.getCommentsByProductId)) + .post(authenticate, asyncHandler(commentController.createComment)); /** * @swagger @@ -920,7 +923,7 @@ router */ router .route("/:articleId/comments/:commentId") - .patch(authenticate, commentController.updateComment) - .delete(authenticate, commentController.deleteComment); + .patch(authenticate, asyncHandler(commentController.updateComment)) + .delete(authenticate, asyncHandler(commentController.deleteComment)); export default router; diff --git a/src/routes/authRoutes.ts b/src/routes/authRoutes.ts index 0a598a6..9ebf280 100644 --- a/src/routes/authRoutes.ts +++ b/src/routes/authRoutes.ts @@ -216,7 +216,7 @@ router.get("/google/callback", passport.authenticate("google", { failureRedirect * description: 로그아웃 후 리디렉션 */ router.get("/logout", (req, res) => { - req.logout(); + req.logout(() => console.log("로그아웃 되었습니다.")); res.redirect("/"); }); diff --git a/src/routes/productRoutes.ts b/src/routes/productRoutes.ts index 0ea88cd..99be896 100644 --- a/src/routes/productRoutes.ts +++ b/src/routes/productRoutes.ts @@ -1,7 +1,8 @@ import express from "express"; -import * as commentController from "../controllers/commentController.js"; -import * as productController from "../controllers/productController.js"; -import authenticate from "../middlewares/authenticate.js"; +import * as commentController from "../controllers/commentController"; +import * as productController from "../controllers/productController"; +import authenticate from "../middlewares/authenticate"; +import asyncHandler from "../utils/asyncHandler"; const router = express.Router(); /** @@ -157,7 +158,10 @@ const router = express.Router(); * value: * message: "유효하지 않은 토큰입니다." */ -router.route("/").get(productController.getProducts).post(authenticate, productController.createProduct); +router + .route("/") + .get(asyncHandler(productController.getProducts)) + .post(authenticate, asyncHandler(productController.createProduct)); /** * @swagger @@ -383,9 +387,9 @@ router.route("/").get(productController.getProducts).post(authenticate, productC */ router .route("/:id") - .get(productController.getProductById) - .patch(authenticate, productController.updateProduct) - .delete(authenticate, productController.deleteProduct); + .get(asyncHandler(productController.getProductById)) + .patch(authenticate, asyncHandler(productController.updateProduct)) + .delete(authenticate, asyncHandler(productController.deleteProduct)); /** * @swagger @@ -466,7 +470,7 @@ router * type: string * example: "이미 좋아요 처리된 상품입니다." */ -router.route("/:id/like").patch(authenticate, productController.likeProduct); +router.route("/:id/like").patch(authenticate, asyncHandler(productController.likeProduct)); /** * @swagger @@ -547,7 +551,7 @@ router.route("/:id/like").patch(authenticate, productController.likeProduct); * type: string * example: "아직 좋아요 처리되지 않은 상품입니다." */ -router.route("/:id/unlike").patch(authenticate, productController.unlikeProduct); +router.route("/:id/unlike").patch(authenticate, asyncHandler(productController.unlikeProduct)); /** * @swagger @@ -693,7 +697,7 @@ router.route("/:id/unlike").patch(authenticate, productController.unlikeProduct) router .route("/:productId/comments") .get(commentController.getCommentsByProductId) - .post(authenticate, commentController.createComment); + .post(authenticate, asyncHandler(commentController.createComment)); /** * @swagger @@ -851,7 +855,7 @@ router router .route("/:productId/comments/:commentId") - .patch(authenticate, commentController.updateComment) - .delete(authenticate, commentController.deleteComment); + .patch(authenticate, asyncHandler(commentController.updateComment)) + .delete(authenticate, asyncHandler(commentController.deleteComment)); export default router; diff --git a/src/services/articleService.ts b/src/services/articleService.ts index 9afffb4..5058acb 100644 --- a/src/services/articleService.ts +++ b/src/services/articleService.ts @@ -3,22 +3,17 @@ import AppError from "../utils/errors"; const prisma = new PrismaClient(); -interface getArticlesParams { +export const getArticles = async ({ + offset, + limit, + orderBy, + keyword, +}: { offset: number; limit: number; orderBy: string; keyword: string; -} - -interface Article { - title: string; - content: string; - imageUrl?: string; - userId: number; - writer?: string; -} - -export const getArticles = async ({ offset, limit, orderBy, keyword }: getArticlesParams) => { +}) => { const order: Prisma.ArticleOrderByWithRelationInput = orderBy === "like" ? { likeCount: "desc" } : { createdAt: "desc" }; @@ -66,9 +61,14 @@ export const getBestArticles = async () => { return bestArticles; }; -export const createArticle = async (articleData: Article) => { +export const createArticle = async (userId: number, articleData: Omit) => { return await prisma.article.create({ - data: articleData, + data: { + ...articleData, + user: { + connect: { id: userId }, + }, + }, }); }; @@ -87,7 +87,7 @@ export const getArticleById = async (id: string) => { }); }; -export const updateArticle = async (articleId: string, userId: number, articleData: Partial
) => { +export const updateArticle = async (articleId: string, userId: number, articleData: Prisma.ArticleUpdateInput) => { const article = await prisma.article.findUniqueOrThrow({ where: { id: articleId }, }); @@ -98,10 +98,7 @@ export const updateArticle = async (articleId: string, userId: number, articleDa return await prisma.article.update({ where: { id: articleId }, - data: { - ...articleData, - userId, - }, + data: articleData, }); }; @@ -133,7 +130,7 @@ export const likeArticle = async (articleId: string, userId: number) => { throw new AppError("이미 좋아요 처리된 게시글입니다.", 409); } - const [createdFavorite, updatedArticle] = await prisma.$transaction([ + const [, updatedArticle] = await prisma.$transaction([ prisma.favorite.create({ data: { userId, @@ -169,7 +166,7 @@ export const unlikeArticle = async (articleId: string, userId: number) => { throw new AppError("아직 좋아요 처리되지 않은 게시글입니다.", 409); } - const [deletedFavorite, updatedArticle] = await prisma.$transaction([ + const [, updatedArticle] = await prisma.$transaction([ prisma.favorite.delete({ where: { userId_articleId: { diff --git a/src/services/authService.ts b/src/services/authService.ts index 6caac6c..c55fbd3 100644 --- a/src/services/authService.ts +++ b/src/services/authService.ts @@ -1,18 +1,25 @@ -import { PrismaClient } from "@prisma/client"; +import { Prisma, PrismaClient } from "@prisma/client"; import bcrypt from "bcrypt"; const prisma = new PrismaClient(); export const createUser = async (email: string, password: string, name: string, nickname: string) => { const hashedPassword = await bcrypt.hash(password, 10); - return prisma.user.create({ - data: { - email, - password: hashedPassword, - name, - nickname, - }, - }); + try { + return await prisma.user.create({ + data: { + email, + password: hashedPassword, + name, + nickname, + }, + }); + } catch (error) { + if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002") { + throw new Error("이미 존재하는 이메일입니다."); + } + throw error; // 다른 에러는 그대로 던집니다. + } }; export const findUserByEmail = async (email: string) => { diff --git a/src/services/commentService.ts b/src/services/commentService.ts index 68df378..de70277 100644 --- a/src/services/commentService.ts +++ b/src/services/commentService.ts @@ -1,10 +1,10 @@ -import { PrismaClient } from "@prisma/client"; -import AppError from "../utils/errors.js"; +import { Comment, Prisma, PrismaClient } from "@prisma/client"; +import AppError from "../utils/errors"; const prisma = new PrismaClient(); -export const getCommentsByProductId = async (productId, cursor) => { - let queryOptions = { +export const getCommentsByProductId = async (productId: string, cursor?: string): Promise => { + const queryOptions: Prisma.CommentFindManyArgs = { take: 10, orderBy: { createdAt: "desc", @@ -18,23 +18,15 @@ export const getCommentsByProductId = async (productId, cursor) => { createdAt: true, writer: true, }, + cursor: cursor ? { id: cursor } : undefined, + skip: cursor ? 1 : undefined, }; - if (cursor) { - queryOptions = { - ...queryOptions, - cursor: { - id: cursor, - }, - skip: 1, - }; - } - return await prisma.comment.findMany(queryOptions); }; -export const getCommentsByArticleId = async (articleId, cursor) => { - let queryOptions = { +export const getCommentsByArticleId = async (articleId: string, cursor?: string): Promise => { + const queryOptions: Prisma.CommentFindManyArgs = { take: 10, orderBy: { createdAt: "desc", @@ -48,28 +40,26 @@ export const getCommentsByArticleId = async (articleId, cursor) => { createdAt: true, writer: true, }, + cursor: cursor ? { id: cursor } : undefined, + skip: cursor ? 1 : undefined, }; - if (cursor) { - queryOptions = { - ...queryOptions, - cursor: { - id: cursor, - }, - skip: 1, - }; - } - return await prisma.comment.findMany(queryOptions); }; -export const createComment = async (commentData) => { +export const createComment = async (commentData: { + content: string; + imageUrl?: string; + userId: number; + productId?: string; + articleId?: string; +}): Promise => { return await prisma.comment.create({ data: commentData, }); }; -export const updateComment = async (commentId, userId, content) => { +export const updateComment = async (commentId: string, userId: number, content: string): Promise => { const comment = await prisma.comment.findUnique({ where: { id: commentId }, }); @@ -88,7 +78,7 @@ export const updateComment = async (commentId, userId, content) => { }); }; -export const deleteComment = async (commentId, userId) => { +export const deleteComment = async (commentId: string, userId: number): Promise => { const comment = await prisma.comment.findUnique({ where: { id: commentId }, }); @@ -100,6 +90,7 @@ export const deleteComment = async (commentId, userId) => { if (comment.userId !== userId) { throw new AppError("이 댓글을 삭제할 권한이 없습니다.", 403); } + await prisma.comment.delete({ where: { id: commentId }, }); diff --git a/src/services/imageService.ts b/src/services/imageService.ts index 0950480..0e9f359 100644 --- a/src/services/imageService.ts +++ b/src/services/imageService.ts @@ -3,7 +3,7 @@ import { PrismaClient } from "@prisma/client"; const prisma = new PrismaClient(); const SERVER_URL = "http://localhost:3000"; -export const uploadImage = async (file) => { +export const uploadImage = async (file: Express.Multer.File | undefined): Promise => { if (!file) { throw new Error("이미지 파일을 선택해주세요."); } @@ -11,7 +11,7 @@ export const uploadImage = async (file) => { const imagePath = file.path; const imageUrl = `${SERVER_URL}/${imagePath.replace(/\\/g, "/")}`; - const image = await prisma.image.create({ + await prisma.image.create({ data: { imagePath: imagePath, }, diff --git a/src/services/productService.ts b/src/services/productService.ts index e8a3b7a..f40a8b2 100644 --- a/src/services/productService.ts +++ b/src/services/productService.ts @@ -1,13 +1,26 @@ -import { PrismaClient } from "@prisma/client"; -import AppError from "../utils/errors.js"; +import { Prisma, PrismaClient, Product } from "@prisma/client"; +import AppError from "../utils/errors"; + const prisma = new PrismaClient(); -export const getProducts = async ({ offset, limit, orderBy, keyword }) => { - const order = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; +export const getProducts = async ({ + offset, + limit, + orderBy, + keyword, +}: { + offset: number; + limit: number; + orderBy: string; + keyword: string; +}): Promise => { + const order: Prisma.ProductOrderByWithRelationInput = + orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; + return await prisma.product.findMany({ orderBy: order, - skip: parseInt(offset), - take: parseInt(limit), + skip: offset, + take: limit, where: { OR: [ { @@ -27,13 +40,13 @@ export const getProducts = async ({ offset, limit, orderBy, keyword }) => { }); }; -export const createProduct = async (productData) => { +export const createProduct = async (productData: Prisma.ProductCreateInput): Promise => { return await prisma.product.create({ data: productData, }); }; -export const getProductById = async (id) => { +export const getProductById = async (id: string): Promise => { const product = await prisma.product.findUnique({ where: { id }, }); @@ -44,7 +57,11 @@ export const getProductById = async (id) => { return product; }; -export const updateProduct = async (productId, userId, productData) => { +export const updateProduct = async ( + productId: string, + userId: number, + productData: Prisma.ProductUpdateInput +): Promise => { const product = await prisma.product.findUnique({ where: { id: productId }, }); @@ -63,7 +80,7 @@ export const updateProduct = async (productId, userId, productData) => { }); }; -export const deleteProduct = async (productId, userId) => { +export const deleteProduct = async (productId: string, userId: number): Promise => { const product = await prisma.product.findUnique({ where: { id: productId }, }); @@ -81,7 +98,7 @@ export const deleteProduct = async (productId, userId) => { }); }; -export const likeProduct = async (productId, userId) => { +export const likeProduct = async (productId: string, userId: number): Promise => { const favorite = await prisma.favorite.findUnique({ where: { userId_productId: { @@ -92,10 +109,10 @@ export const likeProduct = async (productId, userId) => { }); if (favorite) { - throw AppError("이미 좋아요 처리된 상품입니다.", 409); + throw new AppError("이미 좋아요 처리된 상품입니다.", 409); } - const [createdFavorite, updatedProduct] = await prisma.$transaction([ + const [, updatedProduct] = await prisma.$transaction([ prisma.favorite.create({ data: { userId, @@ -117,7 +134,7 @@ export const likeProduct = async (productId, userId) => { return updatedProduct; }; -export const unlikeProduct = async (productId, userId) => { +export const unlikeProduct = async (productId: string, userId: number): Promise => { const favorite = await prisma.favorite.findUnique({ where: { userId_productId: { @@ -128,10 +145,10 @@ export const unlikeProduct = async (productId, userId) => { }); if (!favorite) { - throw AppError("아직 좋아요 처리되지 않은 상품입니다.", 409); + throw new AppError("아직 좋아요 처리되지 않은 상품입니다.", 409); } - const [deletedFavorite, updatedProduct] = await prisma.$transaction([ + const [, updatedProduct] = await prisma.$transaction([ prisma.favorite.delete({ where: { userId_productId: { diff --git a/src/structs.ts b/src/structs.ts index a92e0c9..7b40173 100644 --- a/src/structs.ts +++ b/src/structs.ts @@ -29,7 +29,7 @@ export const CreateComment = s.object({ export const PatchComment = s.partial(CreateComment); export const CreateUser = s.object({ - email: s.define("Email", isEmail), + email: s.define("Email", (value: unknown) => typeof value === "string" && isEmail(value)), password: s.size(s.string(), 1, 32), name: s.size(s.string(), 1, 16), nickname: s.size(s.string(), 1, 16), diff --git a/src/utils/asyncHandler.ts b/src/utils/asyncHandler.ts index 15c70c4..6387fac 100644 --- a/src/utils/asyncHandler.ts +++ b/src/utils/asyncHandler.ts @@ -1,11 +1,15 @@ import { Prisma } from "@prisma/client"; +import { NextFunction, Request, RequestHandler, Response } from "express"; +import { StructError } from "superstruct"; -const asyncHandler = (handler) => { - return async (req, res) => { +type AsyncHandler = (req: T, res: Response, next: NextFunction) => Promise; + +const asyncHandler = (handler: AsyncHandler): RequestHandler => { + return async (req: Request, res: Response, next: NextFunction): Promise => { try { - await handler(req, res); + return await handler(req as T, res, next); } catch (e) { - if (e.name === "StructError") { + if (e instanceof StructError) { const errors = e.failures().map((failure) => ({ path: failure.path.join("."), message: failure.message, diff --git a/src/utils/tokens.ts b/src/utils/tokens.ts index 4697c00..05b50ee 100644 --- a/src/utils/tokens.ts +++ b/src/utils/tokens.ts @@ -1,5 +1,5 @@ import dotenv from "dotenv"; -import jwt from "jsonwebtoken"; +import jwt, { JwtPayload } from "jsonwebtoken"; dotenv.config(); @@ -7,17 +7,25 @@ const JWT_SECRET = process.env.JWT_SECRET || "kingPanda"; const JWT_ACCESS_EXPIRES_IN = process.env.JWT_ACCESS_EXPIRES_IN || "15m"; const JWT_REFRESH_EXPIRES_IN = process.env.JWT_REFRESH_EXPIRES_IN || "7d"; -export const generateAccessToken = (user) => { +interface User { + id: number; +} + +interface DecodedToken extends JwtPayload { + userId: number; +} + +export const generateAccessToken = (user: User): string => { return jwt.sign({ userId: user.id }, JWT_SECRET, { expiresIn: JWT_ACCESS_EXPIRES_IN }); }; -export const generateRefreshToken = (user) => { +export const generateRefreshToken = (user: User): string => { return jwt.sign({ userId: user.id }, JWT_SECRET, { expiresIn: JWT_REFRESH_EXPIRES_IN }); }; -export const regenerateRefreshToken = (refreshToken) => { +export const regenerateRefreshToken = (refreshToken: string): string => { try { - const decoded = jwt.verify(refreshToken, JWT_SECRET); + const decoded = jwt.verify(refreshToken, JWT_SECRET) as DecodedToken; return jwt.sign({ userId: decoded.userId }, JWT_SECRET, { expiresIn: JWT_REFRESH_EXPIRES_IN }); } catch (error) { throw new Error("Invalid refresh token"); diff --git a/yarn.lock b/yarn.lock index 7079449..7693cba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4,7 +4,7 @@ "@apidevtools/json-schema-ref-parser@^9.0.6": version "9.1.2" - resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz#8ff5386b365d4c9faa7c8b566ff16a46a577d9b8" + resolved "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz" integrity sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg== dependencies: "@jsdevtools/ono" "^7.1.3" @@ -14,17 +14,17 @@ "@apidevtools/openapi-schemas@^2.0.4": version "2.1.0" - resolved "https://registry.yarnpkg.com/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz#9fa08017fb59d80538812f03fc7cac5992caaa17" + resolved "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz" integrity sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ== "@apidevtools/swagger-methods@^3.0.2": version "3.0.2" - resolved "https://registry.yarnpkg.com/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz#b789a362e055b0340d04712eafe7027ddc1ac267" + resolved "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz" integrity sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg== "@apidevtools/swagger-parser@10.0.3": version "10.0.3" - resolved "https://registry.yarnpkg.com/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz#32057ae99487872c4dd96b314a1ab4b95d89eaf5" + resolved "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz" integrity sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g== dependencies: "@apidevtools/json-schema-ref-parser" "^9.0.6" @@ -36,139 +36,29 @@ "@cspotcode/source-map-support@^0.8.0": version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@esbuild/aix-ppc64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537" - integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g== - -"@esbuild/android-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9" - integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg== - -"@esbuild/android-arm@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995" - integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w== - -"@esbuild/android-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98" - integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg== - "@esbuild/darwin-arm64@0.20.2": version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb" + resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz" integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA== -"@esbuild/darwin-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0" - integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA== - -"@esbuild/freebsd-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911" - integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw== - -"@esbuild/freebsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c" - integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw== - -"@esbuild/linux-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5" - integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A== - -"@esbuild/linux-arm@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c" - integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg== - -"@esbuild/linux-ia32@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa" - integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig== - -"@esbuild/linux-loong64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5" - integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ== - -"@esbuild/linux-mips64el@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa" - integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA== - -"@esbuild/linux-ppc64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20" - integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg== - -"@esbuild/linux-riscv64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300" - integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg== - -"@esbuild/linux-s390x@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685" - integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ== - -"@esbuild/linux-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff" - integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw== - -"@esbuild/netbsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6" - integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ== - -"@esbuild/openbsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf" - integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ== - -"@esbuild/sunos-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f" - integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w== - -"@esbuild/win32-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90" - integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ== - -"@esbuild/win32-ia32@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23" - integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ== - -"@esbuild/win32-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc" - integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ== - "@jridgewell/resolve-uri@^3.0.3": version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== dependencies: "@jridgewell/resolve-uri" "^3.0.3" @@ -176,12 +66,12 @@ "@jsdevtools/ono@^7.1.3": version "7.1.3" - resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" + resolved "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz" integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== "@mapbox/node-pre-gyp@^1.0.11": version "1.0.11" - resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa" + resolved "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz" integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ== dependencies: detect-libc "^2.0.0" @@ -196,22 +86,22 @@ "@prisma/client@^5.4.2": version "5.14.0" - resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.14.0.tgz#dadca5bb1137ddcebb454bbdaf89423823d3363f" + resolved "https://registry.npmjs.org/@prisma/client/-/client-5.14.0.tgz" integrity sha512-akMSuyvLKeoU4LeyBAUdThP/uhVP3GuLygFE3MlYzaCb3/J8SfsYBE5PkaFuLuVpLyA6sFoW+16z/aPhNAESqg== "@prisma/debug@5.14.0": version "5.14.0" - resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.14.0.tgz#1227c705893c38284f7c63d72441480ebaa12605" + resolved "https://registry.npmjs.org/@prisma/debug/-/debug-5.14.0.tgz" integrity sha512-iq56qBZuFfX3fCxoxT8gBX33lQzomBU0qIUaEj1RebsKVz1ob/BVH1XSBwwwvRVtZEV1b7Fxx2eVu34Ge/mg3w== "@prisma/engines-version@5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48": version "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48.tgz#019c3c75a5c3276e580685fe48cdbfd181176858" + resolved "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48.tgz" integrity sha512-ip6pNkRo1UxWv+6toxNcYvItNYaqQjXdFNGJ+Nuk2eYtRoEdoF13wxo7/jsClJFFenMPVNVqXQDV0oveXnR1cA== "@prisma/engines@5.14.0": version "5.14.0" - resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.14.0.tgz#2ee91dd2220a726c27c906fbea788bbb3efdac6e" + resolved "https://registry.npmjs.org/@prisma/engines/-/engines-5.14.0.tgz" integrity sha512-lgxkKZ6IEygVcw6IZZUlPIfLQ9hjSYAtHjZ5r64sCLDgVzsPFCi2XBBJgzPMkOQ5RHzUD4E/dVdpn9+ez8tk1A== dependencies: "@prisma/debug" "5.14.0" @@ -221,7 +111,7 @@ "@prisma/fetch-engine@5.14.0": version "5.14.0" - resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-5.14.0.tgz#45297c118d4ec3fea55129886edd5a429da1f6da" + resolved "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.14.0.tgz" integrity sha512-VrheA9y9DMURK5vu8OJoOgQpxOhas3qF0IBHJ8G/0X44k82kc8E0w98HCn2nhnbOOMwbWsJWXfLC2/F8n5u0gQ== dependencies: "@prisma/debug" "5.14.0" @@ -230,41 +120,41 @@ "@prisma/get-platform@5.14.0": version "5.14.0" - resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-5.14.0.tgz#69112d3dde61905f59a65ed818f153e153ca40f0" + resolved "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.14.0.tgz" integrity sha512-/yAyBvcEjRv41ynZrhdrPtHgk47xLRRq/o5eWGcUpBJ1YrUZTYB8EoPiopnP7iQrMATK8stXQdPOoVlrzuTQZw== dependencies: "@prisma/debug" "5.14.0" "@tsconfig/node10@^1.0.7": version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz" integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== "@tsconfig/node12@^1.0.7": version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz" integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== "@tsconfig/node14@^1.0.0": version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz" integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== "@tsconfig/node16@^1.0.2": version "1.0.4" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== "@types/bcrypt@^5.0.2": version "5.0.2" - resolved "https://registry.yarnpkg.com/@types/bcrypt/-/bcrypt-5.0.2.tgz#22fddc11945ea4fbc3655b3e8b8847cc9f811477" + resolved "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz" integrity sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ== dependencies: "@types/node" "*" "@types/body-parser@*": version "1.19.5" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" + resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz" integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== dependencies: "@types/connect" "*" @@ -272,22 +162,22 @@ "@types/connect@*": version "3.4.38" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + resolved "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz" integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== dependencies: "@types/node" "*" "@types/cors@^2.8.17": version "2.8.17" - resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b" + resolved "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz" integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA== dependencies: "@types/node" "*" "@types/express-serve-static-core@^4.17.33": - version "4.19.3" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.3.tgz#e469a13e4186c9e1c0418fb17be8bc8ff1b19a7a" - integrity sha512-KOzM7MhcBFlmnlr/fzISFF5vGWVSvN6fTd4T+ExOt08bA/dA5kpSzY52nMsI1KDFmUREpJelPYyuslLRSjjgCg== + version "4.19.2" + resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.2.tgz" + integrity sha512-dPSEQElyVJ97BuGduAqQjpBocZWAs0GR94z+ptL7JXQJeJdHw2WBG3EWdFrK36b8Q6j8P4cXOMhgUoi0IIfIsg== dependencies: "@types/node" "*" "@types/qs" "*" @@ -296,14 +186,14 @@ "@types/express-session@^1.18.0": version "1.18.0" - resolved "https://registry.yarnpkg.com/@types/express-session/-/express-session-1.18.0.tgz#7c6f25c3604b28d6bc08a2e3929997bbc7672fa2" + resolved "https://registry.npmjs.org/@types/express-session/-/express-session-1.18.0.tgz" integrity sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA== dependencies: "@types/express" "*" "@types/express@*", "@types/express@^4.17.21": version "4.17.21" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + resolved "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz" integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== dependencies: "@types/body-parser" "*" @@ -313,50 +203,62 @@ "@types/http-errors@*": version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" + resolved "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz" integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== +"@types/is-email@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@types/is-email/-/is-email-1.0.0.tgz" + integrity sha512-b/76ooKpYY/b+oPrOuc/pmM5eag+ZlzctPsKcRCIKs+TFzh0FL58OeXtSPkbXt3uKNK84YCKHmjnoREtwve5Kg== + "@types/json-schema@^7.0.6": version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/jsonwebtoken@^9.0.6": version "9.0.6" - resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz#d1af3544d99ad992fb6681bbe60676e06b032bd3" + resolved "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz" integrity sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw== dependencies: "@types/node" "*" "@types/mime@^1": version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + resolved "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz" integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== "@types/morgan@^1.9.9": version "1.9.9" - resolved "https://registry.yarnpkg.com/@types/morgan/-/morgan-1.9.9.tgz#d60dec3979e16c203a000159daa07d3fb7270d7f" + resolved "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.9.tgz" integrity sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ== dependencies: "@types/node" "*" +"@types/multer@^1.4.11": + version "1.4.11" + resolved "https://registry.npmjs.org/@types/multer/-/multer-1.4.11.tgz" + integrity sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w== + dependencies: + "@types/express" "*" + "@types/node@*", "@types/node@^20.12.13": version "20.12.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.13.tgz#90ed3b8a4e52dd3c5dc5a42dde5b85b74ad8ed88" + resolved "https://registry.npmjs.org/@types/node/-/node-20.12.13.tgz" integrity sha512-gBGeanV41c1L171rR7wjbMiEpEI/l5XFQdLLfhr/REwpgDy/4U8y89+i8kRiLzDyZdOkXh+cRaTetUnCYutoXA== dependencies: undici-types "~5.26.4" "@types/oauth@*": version "0.9.5" - resolved "https://registry.yarnpkg.com/@types/oauth/-/oauth-0.9.5.tgz#acc4209bfa1c8d7d3aaf2c9ad0b32216a29616c1" + resolved "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.5.tgz" integrity sha512-+oQ3C2Zx6ambINOcdIARF5Z3Tu3x//HipE889/fqo3sgpQZbe9c6ExdQFtN6qlhpR7p83lTZfPJt0tCAW29dog== dependencies: "@types/node" "*" "@types/passport-google-oauth20@^2.0.16": version "2.0.16" - resolved "https://registry.yarnpkg.com/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.16.tgz#9e39c1203d56496d89392538e6109626e253bc28" + resolved "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.16.tgz" integrity sha512-ayXK2CJ7uVieqhYOc6k/pIr5pcQxOLB6kBev+QUGS7oEZeTgIs1odDobXRqgfBPvXzl0wXCQHftV5220czZCPA== dependencies: "@types/express" "*" @@ -365,7 +267,7 @@ "@types/passport-oauth2@*": version "1.4.17" - resolved "https://registry.yarnpkg.com/@types/passport-oauth2/-/passport-oauth2-1.4.17.tgz#d5d54339d44f6883d03e69dc0cc0e2114067abb4" + resolved "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.4.17.tgz" integrity sha512-ODiAHvso6JcWJ6ZkHHroVp05EHGhqQN533PtFNBkg8Fy5mERDqsr030AX81M0D69ZcaMvhF92SRckEk2B0HYYg== dependencies: "@types/express" "*" @@ -374,24 +276,24 @@ "@types/passport@*", "@types/passport@^1.0.16": version "1.0.16" - resolved "https://registry.yarnpkg.com/@types/passport/-/passport-1.0.16.tgz#5a2918b180a16924c4d75c31254c31cdca5ce6cf" + resolved "https://registry.npmjs.org/@types/passport/-/passport-1.0.16.tgz" integrity sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A== dependencies: "@types/express" "*" "@types/qs@*": version "6.9.15" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" + resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz" integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== "@types/range-parser@*": version "1.2.7" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz" integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== "@types/send@*": version "0.17.4" - resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + resolved "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz" integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== dependencies: "@types/mime" "^1" @@ -399,7 +301,7 @@ "@types/serve-static@*": version "1.15.7" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" + resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz" integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== dependencies: "@types/http-errors" "*" @@ -408,12 +310,12 @@ "@types/swagger-jsdoc@^6.0.4": version "6.0.4" - resolved "https://registry.yarnpkg.com/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz#bb4f60f3a5f103818e022f2e29ff8935113fb83d" + resolved "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz" integrity sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ== "@types/swagger-ui-express@^4.1.6": version "4.1.6" - resolved "https://registry.yarnpkg.com/@types/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz#d0929e3fabac1a96a8a9c6c7ee8d42362c5cdf48" + resolved "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz" integrity sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg== dependencies: "@types/express" "*" @@ -421,12 +323,12 @@ abbrev@1: version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== accepts@~1.3.8: version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: mime-types "~2.1.34" @@ -434,29 +336,29 @@ accepts@~1.3.8: acorn-walk@^8.1.1: version "8.3.2" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz" integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== acorn@^8.4.1: version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== agent-base@6: version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: debug "4" ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== anymatch@~3.1.2: version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" @@ -464,17 +366,17 @@ anymatch@~3.1.2: append-field@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56" + resolved "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz" integrity sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw== "aproba@^1.0.3 || ^2.0.0": version "2.0.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + resolved "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== are-we-there-yet@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" + resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz" integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== dependencies: delegates "^1.0.0" @@ -482,39 +384,39 @@ are-we-there-yet@^2.0.0: arg@^4.1.0: version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== argparse@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== array-flatten@1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== base64url@3.x.x: version "3.0.1" - resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" + resolved "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz" integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== basic-auth@~2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" + resolved "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz" integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== dependencies: safe-buffer "5.1.2" bcrypt@^5.1.1: version "5.1.1" - resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-5.1.1.tgz#0f732c6dcb4e12e5b70a25e326a72965879ba6e2" + resolved "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz" integrity sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww== dependencies: "@mapbox/node-pre-gyp" "^1.0.11" @@ -522,12 +424,12 @@ bcrypt@^5.1.1: binary-extensions@^2.0.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== body-parser@1.20.2: version "1.20.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" + resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz" integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== dependencies: bytes "3.1.2" @@ -545,7 +447,7 @@ body-parser@1.20.2: brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" @@ -553,36 +455,36 @@ brace-expansion@^1.1.7: braces@~3.0.2: version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: fill-range "^7.1.1" buffer-equal-constant-time@1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz" integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== buffer-from@^1.0.0: version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== busboy@^1.0.0: version "1.6.0" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + resolved "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz" integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== dependencies: streamsearch "^1.1.0" bytes@3.1.2: version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== call-bind@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz" integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== dependencies: es-define-property "^1.0.0" @@ -593,12 +495,12 @@ call-bind@^1.0.7: call-me-maybe@^1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" + resolved "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz" integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== chokidar@^3.5.2: version "3.6.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== dependencies: anymatch "~3.1.2" @@ -613,32 +515,32 @@ chokidar@^3.5.2: chownr@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== color-support@^1.1.2: version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== +commander@^9.4.1: + version "9.5.0" + resolved "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== + commander@6.2.0: version "6.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75" + resolved "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz" integrity sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q== -commander@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" - integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== - concat-map@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== concat-stream@^1.5.2: version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== dependencies: buffer-from "^1.0.0" @@ -648,44 +550,44 @@ concat-stream@^1.5.2: console-control-strings@^1.0.0, console-control-strings@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz" integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== content-disposition@0.5.4: version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== dependencies: safe-buffer "5.2.1" content-type@~1.0.4, content-type@~1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== cookie-signature@1.0.6: version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== cookie-signature@1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.7.tgz#ab5dd7ab757c54e60f37ef6550f481c426d10454" + resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz" integrity sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA== cookie@0.6.0: version "0.6.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz" integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== core-util-is@~1.0.0: version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== cors@^2.8.5: version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + resolved "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz" integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== dependencies: object-assign "^4" @@ -693,26 +595,33 @@ cors@^2.8.5: create-require@^1.1.0: version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +debug@^4: + version "4.3.4" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + debug@2.6.9: version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@4, debug@^4: +debug@4: version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" define-data-property@^1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz" integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== dependencies: es-define-property "^1.0.0" @@ -721,78 +630,78 @@ define-data-property@^1.1.4: delegates@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== -depd@2.0.0, depd@~2.0.0: +depd@~2.0.0, depd@2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== destroy@1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detect-libc@^2.0.0: version "2.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" + resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz" integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== diff@^4.0.1: version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== doctrine@3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== dependencies: esutils "^2.0.2" dotenv@^16.3.1: version "16.4.5" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" + resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz" integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== ecdsa-sig-formatter@1.0.11: version "1.0.11" - resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + resolved "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz" integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== dependencies: safe-buffer "^5.0.1" ee-first@1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== encodeurl@~1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== es-define-property@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz" integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== dependencies: get-intrinsic "^1.2.4" es-errors@^1.3.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== esbuild@~0.20.2: version "0.20.2" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.2.tgz#9d6b2386561766ee6b5a55196c6d766d28c87ea1" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz" integrity sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g== optionalDependencies: "@esbuild/aix-ppc64" "0.20.2" @@ -821,22 +730,22 @@ esbuild@~0.20.2: escape-html@~1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== etag@~1.8.1: version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== express-session@^1.18.0: version "1.18.0" - resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.18.0.tgz#a6ae39d9091f2efba5f20fc5c65a3ce7c9ce16a3" + resolved "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz" integrity sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ== dependencies: cookie "0.6.0" @@ -848,9 +757,9 @@ express-session@^1.18.0: safe-buffer "5.2.1" uid-safe "~2.1.5" -express@^4.18.2: +express@^4.18.2, "express@>=4.0.0 || >=5.0.0-beta": version "4.19.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" + resolved "https://registry.npmjs.org/express/-/express-4.19.2.tgz" integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== dependencies: accepts "~1.3.8" @@ -887,14 +796,14 @@ express@^4.18.2: fill-range@^7.1.1: version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" finalhandler@1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz" integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== dependencies: debug "2.6.9" @@ -907,39 +816,39 @@ finalhandler@1.2.0: forwarded@0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== fresh@0.5.2: version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== fs-minipass@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz" integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== dependencies: minipass "^3.0.0" fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== function-bind@^1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== gauge@^3.0.0: version "3.0.2" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + resolved "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz" integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== dependencies: aproba "^1.0.3 || ^2.0.0" @@ -954,7 +863,7 @@ gauge@^3.0.0: get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz" integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== dependencies: es-errors "^1.3.0" @@ -965,86 +874,86 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: get-tsconfig@^4.7.5: version "4.7.5" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.5.tgz#5e012498579e9a6947511ed0cd403272c7acbbaf" + resolved "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz" integrity sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw== dependencies: resolve-pkg-maps "^1.0.0" glob-parent@~5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" -glob@7.1.6: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== +glob@7.1.6: + version "7.1.6" + resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.1.1" + minimatch "^3.0.4" once "^1.3.0" path-is-absolute "^1.0.0" gopd@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz" integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== dependencies: get-intrinsic "^1.1.3" has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-property-descriptors@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz" integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== dependencies: es-define-property "^1.0.0" has-proto@^1.0.1: version "1.0.3" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz" integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== has-symbols@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has-unicode@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== hasown@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: function-bind "^1.1.2" http-errors@2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== dependencies: depd "2.0.0" @@ -1055,7 +964,7 @@ http-errors@2.0.0: https-proxy-agent@^5.0.0: version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" @@ -1063,88 +972,88 @@ https-proxy-agent@^5.0.0: iconv-lite@0.4.24: version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" ignore-by-default@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + resolved "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz" integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.3: +inherits@^2.0.3, inherits@~2.0.3, inherits@2, inherits@2.0.4: version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== ipaddr.js@1.9.1: version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== is-binary-path@~2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: binary-extensions "^2.0.0" is-email@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-email/-/is-email-1.0.2.tgz#51a618e2ddc895988ceb550df9f587b3607560e5" + resolved "https://registry.npmjs.org/is-email/-/is-email-1.0.2.tgz" integrity sha512-UojUgD2EhDTBQ2SGKwrK9edce5phRzgLsP+V5+Uu2Swi+uvjVXgH3zduM3HhT9iaC/9Kq19/TYUbP0jPoi6ioA== is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-number@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-uuid@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-uuid/-/is-uuid-1.0.2.tgz#ad1898ddf154947c25c8e54966f48604e9caecc4" + resolved "https://registry.npmjs.org/is-uuid/-/is-uuid-1.0.2.tgz" integrity sha512-tCByphFcJgf2qmiMo5hMCgNAquNSagOetVetDvBXswGkNfoyEMvGH1yDlF8cbZbKnbVBr4Y5/rlpMz9umxyBkQ== isarray@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== js-yaml@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" jsonwebtoken@^9.0.2: version "9.0.2" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" + resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz" integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== dependencies: jws "^3.2.2" @@ -1160,7 +1069,7 @@ jsonwebtoken@^9.0.2: jwa@^1.4.1: version "1.4.1" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz" integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== dependencies: buffer-equal-constant-time "1.0.1" @@ -1169,7 +1078,7 @@ jwa@^1.4.1: jws@^3.2.2: version "3.2.2" - resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + resolved "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz" integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== dependencies: jwa "^1.4.1" @@ -1177,125 +1086,125 @@ jws@^3.2.2: lodash.get@^4.4.2: version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + resolved "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz" integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== lodash.includes@^4.3.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + resolved "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz" integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== lodash.isboolean@^3.0.3: version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + resolved "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz" integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== lodash.isequal@^4.5.0: version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz" integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== lodash.isinteger@^4.0.4: version "4.0.4" - resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + resolved "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz" integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== lodash.isnumber@^3.0.3: version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + resolved "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz" integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== lodash.isplainobject@^4.0.6: version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + resolved "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz" integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== lodash.isstring@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + resolved "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz" integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== lodash.mergewith@^4.6.2: version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" + resolved "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz" integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== lodash.once@^4.0.0: version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + resolved "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz" integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== make-dir@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" make-error@^1.1.1: version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== media-typer@0.3.0: version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== merge-descriptors@1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== methods@~1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== mime-db@1.52.0: version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" mime@1.6.0: version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" minimist@^1.2.6: version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== minipass@^3.0.0: version "3.3.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + resolved "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz" integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== dependencies: yallist "^4.0.0" minipass@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + resolved "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== minizlib@^2.1.1: version "2.1.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== dependencies: minipass "^3.0.0" @@ -1303,31 +1212,31 @@ minizlib@^2.1.1: mkdirp@^0.5.4: version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: minimist "^1.2.6" mkdirp@^1.0.3: version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== moment-timezone@^0.5.45: version "0.5.45" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.45.tgz#cb685acd56bac10e69d93c536366eb65aa6bcf5c" + resolved "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz" integrity sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ== dependencies: moment "^2.29.4" moment@^2.29.4: version "2.30.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + resolved "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz" integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== morgan@^1.10.0: version "1.10.0" - resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" + resolved "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz" integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== dependencies: basic-auth "~2.0.1" @@ -1336,24 +1245,29 @@ morgan@^1.10.0: on-finished "~2.3.0" on-headers "~1.0.2" +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + ms@2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== ms@2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1: +ms@2.1.3: version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== multer@^1.4.5-lts.1: version "1.4.5-lts.1" - resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.5-lts.1.tgz#803e24ad1984f58edffbc79f56e305aec5cfd1ac" + resolved "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz" integrity sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ== dependencies: append-field "^1.0.0" @@ -1366,24 +1280,24 @@ multer@^1.4.5-lts.1: negotiator@0.6.3: version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== node-addon-api@^5.0.0: version "5.1.0" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz" integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== node-fetch@^2.6.7: version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" nodemon@^3.1.2: version "3.1.2" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.2.tgz#e4041ef00b930c5bdc1ab68d897a88eb7b17c8c2" + resolved "https://registry.npmjs.org/nodemon/-/nodemon-3.1.2.tgz" integrity sha512-/Ib/kloefDy+N0iRTxIUzyGcdW9lzlnca2Jsa5w73bs3npXjg+WInmiX6VY13mIb6SykkthYX/U5t0ukryGqBw== dependencies: chokidar "^3.5.2" @@ -1399,19 +1313,19 @@ nodemon@^3.1.2: nopt@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + resolved "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz" integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== dependencies: abbrev "1" normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== npmlog@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" + resolved "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz" integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== dependencies: are-we-there-yet "^2.0.0" @@ -1421,60 +1335,65 @@ npmlog@^5.0.1: oauth@0.10.x: version "0.10.0" - resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.10.0.tgz#3551c4c9b95c53ea437e1e21e46b649482339c58" + resolved "https://registry.npmjs.org/oauth/-/oauth-0.10.0.tgz" integrity sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q== object-assign@^4, object-assign@^4.1.1: version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-inspect@^1.13.1: version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz" integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - on-finished@~2.3.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== dependencies: ee-first "1.1.1" +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + on-headers@~1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + resolved "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz" integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== once@^1.3.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" +openapi-types@>=7: + version "12.1.3" + resolved "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz" + integrity sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw== + parseurl@~1.3.3: version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== passport-google-oauth20@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz#0d241b2d21ebd3dc7f2b60669ec4d587e3a674ef" + resolved "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz" integrity sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ== dependencies: passport-oauth2 "1.x.x" passport-oauth2@1.x.x: version "1.8.0" - resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.8.0.tgz#55725771d160f09bbb191828d5e3d559eee079c8" + resolved "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.8.0.tgz" integrity sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA== dependencies: base64url "3.x.x" @@ -1485,12 +1404,12 @@ passport-oauth2@1.x.x: passport-strategy@1.x.x: version "1.0.0" - resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" + resolved "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== passport@^0.7.0: version "0.7.0" - resolved "https://registry.yarnpkg.com/passport/-/passport-0.7.0.tgz#3688415a59a48cf8068417a8a8092d4492ca3a05" + resolved "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz" integrity sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ== dependencies: passport-strategy "1.x.x" @@ -1499,39 +1418,39 @@ passport@^0.7.0: path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-to-regexp@0.1.7: version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== pause@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" + resolved "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz" integrity sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg== picomatch@^2.0.4, picomatch@^2.2.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -prisma@^5.4.2: +prisma@*, prisma@^5.4.2: version "5.14.0" - resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.14.0.tgz#ffc4696a43b044b636c3303b7aa98c13c2ade4dd" + resolved "https://registry.npmjs.org/prisma/-/prisma-5.14.0.tgz" integrity sha512-gCNZco7y5XtjrnQYeDJTiVZmT/ncqCr5RY1/Cf8X2wgLRmyh9ayPAGBNziI4qEE4S6SxCH5omQLVo9lmURaJ/Q== dependencies: "@prisma/engines" "5.14.0" process-nextick-args@~2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== proxy-addr@~2.0.7: version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== dependencies: forwarded "0.2.0" @@ -1539,29 +1458,29 @@ proxy-addr@~2.0.7: pstree.remy@^1.1.8: version "1.1.8" - resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + resolved "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz" integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== qs@6.11.0: version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + resolved "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz" integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== dependencies: side-channel "^1.0.4" random-bytes@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" + resolved "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz" integrity sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ== range-parser@~1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== raw-body@2.5.2: version "2.5.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz" integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: bytes "3.1.2" @@ -1571,7 +1490,7 @@ raw-body@2.5.2: readable-stream@^2.2.2: version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" @@ -1584,7 +1503,7 @@ readable-stream@^2.2.2: readable-stream@^3.6.0: version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" @@ -1593,51 +1512,61 @@ readable-stream@^3.6.0: readdirp@~3.6.0: version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== dependencies: picomatch "^2.2.1" resolve-pkg-maps@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + resolved "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== rimraf@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@^5.0.1, safe-buffer@5.2.1: + version "5.2.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0: version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== "safer-buffer@>= 2.1.2 < 3": version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== semver@^6.0.0: version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.3.5, semver@^7.5.3, semver@^7.5.4: version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + resolved "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz" integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== send@0.18.0: version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + resolved "https://registry.npmjs.org/send/-/send-0.18.0.tgz" integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" @@ -1656,7 +1585,7 @@ send@0.18.0: serve-static@1.15.0: version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz" integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== dependencies: encodeurl "~1.0.2" @@ -1666,12 +1595,12 @@ serve-static@1.15.0: set-blocking@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== set-function-length@^1.2.1: version "1.2.2" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz" integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== dependencies: define-data-property "^1.1.4" @@ -1683,12 +1612,12 @@ set-function-length@^1.2.1: setprototypeof@1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== side-channel@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz" integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== dependencies: call-bind "^1.0.7" @@ -1698,71 +1627,64 @@ side-channel@^1.0.4: signal-exit@^3.0.0: version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== simple-update-notifier@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" + resolved "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz" integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== dependencies: semver "^7.5.3" statuses@2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== streamsearch@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== +string_decoder@^1.1.1, string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.2.3: version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" superstruct@^1.0.3: version "1.0.4" - resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" + resolved "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz" integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== supports-color@^5.5.0: version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" swagger-jsdoc@^6.2.8: version "6.2.8" - resolved "https://registry.yarnpkg.com/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz#6d33d9fb07ff4a7c1564379c52c08989ec7d0256" + resolved "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz" integrity sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ== dependencies: commander "6.2.0" @@ -1774,26 +1696,26 @@ swagger-jsdoc@^6.2.8: swagger-parser@^10.0.3: version "10.0.3" - resolved "https://registry.yarnpkg.com/swagger-parser/-/swagger-parser-10.0.3.tgz#04cb01c18c3ac192b41161c77f81e79309135d03" + resolved "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz" integrity sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg== dependencies: "@apidevtools/swagger-parser" "10.0.3" swagger-ui-dist@>=5.0.0: version "5.17.14" - resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz#e2c222e5bf9e15ccf80ec4bc08b4aaac09792fd6" + resolved "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz" integrity sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw== swagger-ui-express@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz#7a00a18dd909574cb0d628574a299b9ba53d4d49" + resolved "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz" integrity sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA== dependencies: swagger-ui-dist ">=5.0.0" tar@^6.1.11: version "6.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + resolved "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz" integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== dependencies: chownr "^2.0.0" @@ -1805,29 +1727,29 @@ tar@^6.1.11: to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" toidentifier@1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== touch@^3.1.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.1.tgz#097a23d7b161476435e5c1344a95c0f75b4a5694" + resolved "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz" integrity sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA== tr46@~0.0.3: version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== ts-node@^10.9.2: version "10.9.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz" integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== dependencies: "@cspotcode/source-map-support" "^0.8.0" @@ -1846,7 +1768,7 @@ ts-node@^10.9.2: tsx@^4.11.0: version "4.11.0" - resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.11.0.tgz#fdd8ce7ccaa0a84aed64c11e2fc5da314e1d8d14" + resolved "https://registry.npmjs.org/tsx/-/tsx-4.11.0.tgz" integrity sha512-vzGGELOgAupsNVssAmZjbUDfdm/pWP4R+Kg8TVdsonxbXk0bEpE1qh0yV6/QxUVXaVlNemgcPajGdJJ82n3stg== dependencies: esbuild "~0.20.2" @@ -1856,7 +1778,7 @@ tsx@^4.11.0: type-is@^1.6.4, type-is@~1.6.18: version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== dependencies: media-typer "0.3.0" @@ -1864,74 +1786,74 @@ type-is@^1.6.4, type-is@~1.6.18: typedarray@^0.0.6: version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typescript@^5.4.5: +typescript@^5.4.5, typescript@>=2.7: version "5.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz" integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== uid-safe@~2.1.5: version "2.1.5" - resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a" + resolved "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz" integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA== dependencies: random-bytes "~1.0.0" uid2@0.0.x: version "0.0.4" - resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.4.tgz#033f3b1d5d32505f5ce5f888b9f3b667123c0a44" + resolved "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz" integrity sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA== undefsafe@^2.0.5: version "2.0.5" - resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" + resolved "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz" integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== undici-types@~5.26.4: version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== -unpipe@1.0.0, unpipe@~1.0.0: +unpipe@~1.0.0, unpipe@1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -utils-merge@1.0.1, utils-merge@1.x.x, utils-merge@^1.0.1: +utils-merge@^1.0.1, utils-merge@1.0.1, utils-merge@1.x.x: version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== v8-compile-cache-lib@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== validator@^13.7.0: version "13.12.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-13.12.0.tgz#7d78e76ba85504da3fee4fd1922b385914d4b35f" + resolved "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz" integrity sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg== vary@^1, vary@~1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== webidl-conversions@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== whatwg-url@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" @@ -1939,43 +1861,43 @@ whatwg-url@^5.0.0: wide-align@^1.1.2: version "1.1.5" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz" integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== dependencies: string-width "^1.0.2 || 2 || 3 || 4" wrappy@1: version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== xtend@^4.0.0: version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== yallist@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yaml@2.0.0-1: version "2.0.0-1" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.0.0-1.tgz#8c3029b3ee2028306d5bcf396980623115ff8d18" + resolved "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz" integrity sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ== yn@3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== z-schema@^5.0.1: - version "5.0.6" - resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-5.0.6.tgz#46d6a687b15e4a4369e18d6cb1c7b8618fc256c5" - integrity sha512-+XR1GhnWklYdfr8YaZv/iu+vY+ux7V5DS5zH1DQf6bO5ufrt/5cgNhVO5qyhsjFXvsqQb/f08DWE9b6uPscyAg== + version "5.0.5" + resolved "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz" + integrity sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q== dependencies: lodash.get "^4.4.2" lodash.isequal "^4.5.0" validator "^13.7.0" optionalDependencies: - commander "^10.0.0" + commander "^9.4.1" From 117b703d8878f980810ba24b63fa8e3bbfbb0a63 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Sun, 2 Jun 2024 09:39:35 +0900 Subject: [PATCH 40/60] =?UTF-8?q?[#M11]=20fix=20:=20swagger=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=20=EA=B2=BD=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/swagger/swaggerOptions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/swagger/swaggerOptions.ts b/src/swagger/swaggerOptions.ts index 028a9da..8aa9195 100644 --- a/src/swagger/swaggerOptions.ts +++ b/src/swagger/swaggerOptions.ts @@ -36,7 +36,7 @@ const swaggerOptions = { }, ], }, - apis: ["./routes/*.js"], + apis: ["./src/routes/*.ts"], }; export default swaggerOptions; From a1c2df4be36092ed7b70451ad6e0fb7e4663b637 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Sun, 2 Jun 2024 11:30:04 +0900 Subject: [PATCH 41/60] =?UTF-8?q?[#M11]=20writer=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20=EC=A0=80=EC=9E=A5=ED=95=98=EA=B3=A0=20=EB=B6=88?= =?UTF-8?q?=EB=9F=AC=EC=98=A4=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migration.sql | 16 +++++++++++++ prisma/mock.ts | 5 ++++ prisma/schema.prisma | 5 ++-- src/services/articleService.ts | 24 ++++++++++++++----- src/services/commentService.ts | 17 +++++++++++-- src/services/productService.ts | 23 +++++++++++++++--- 6 files changed, 77 insertions(+), 13 deletions(-) create mode 100644 prisma/migrations/20240602022233_add_writer_to_product/migration.sql diff --git a/prisma/migrations/20240602022233_add_writer_to_product/migration.sql b/prisma/migrations/20240602022233_add_writer_to_product/migration.sql new file mode 100644 index 0000000..7a2f07a --- /dev/null +++ b/prisma/migrations/20240602022233_add_writer_to_product/migration.sql @@ -0,0 +1,16 @@ +/* + Warnings: + + - Made the column `writer` on table `Article` required. This step will fail if there are existing NULL values in that column. + - Made the column `writer` on table `Comment` required. This step will fail if there are existing NULL values in that column. + - Added the required column `writer` to the `Product` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "Article" ALTER COLUMN "writer" SET NOT NULL; + +-- AlterTable +ALTER TABLE "Comment" ALTER COLUMN "writer" SET NOT NULL; + +-- AlterTable +ALTER TABLE "Product" ADD COLUMN "writer" TEXT NOT NULL; diff --git a/prisma/mock.ts b/prisma/mock.ts index 255b921..db1cb39 100644 --- a/prisma/mock.ts +++ b/prisma/mock.ts @@ -7,6 +7,7 @@ export const PRODUCTS = [ price: 700000, description: "판다인형 판다", name: "판다인형", + writer: "김판다", userId: 1, }, { @@ -19,6 +20,7 @@ export const PRODUCTS = [ price: 7000, description: "판다인형 안판다", name: "불곰사세요", + writer: "박불곰", userId: 2, }, ]; @@ -31,6 +33,7 @@ export const ARTICLES = [ imageUrl: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", likeCount: 7, userId: 1, + writer: "김판다", }, { id: "7c8b9d2e-5d45-4c9f-9b4b-7626f3c9c9a9", @@ -39,6 +42,7 @@ export const ARTICLES = [ imageUrl: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", likeCount: 2, userId: 1, + writer: "김판다", }, { id: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", @@ -47,6 +51,7 @@ export const ARTICLES = [ imageUrl: "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg", likeCount: 3, userId: 2, + writer: "김판다", }, ]; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 0ce8237..da1d50b 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -26,6 +26,7 @@ model User { model Product { id String @id @default(uuid()) name String + writer String description String price Int tags String[] @@ -43,10 +44,10 @@ model Product { model Article { id String @id @default(uuid()) title String + writer String content String imageUrl String? @default("") likeCount Int @default(0) - writer String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt comments Comment[] @@ -59,7 +60,7 @@ model Article { model Comment { id String @id @default(uuid()) content String - writer String? + writer String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt product Product? @relation(fields: [productId], references: [id], onDelete: SetNull) diff --git a/src/services/articleService.ts b/src/services/articleService.ts index 5058acb..e2bcb5b 100644 --- a/src/services/articleService.ts +++ b/src/services/articleService.ts @@ -62,13 +62,25 @@ export const getBestArticles = async () => { }; export const createArticle = async (userId: number, articleData: Omit) => { - return await prisma.article.create({ - data: { - ...articleData, - user: { - connect: { id: userId }, - }, + const user = await prisma.user.findUnique({ + where: { id: userId }, + select: { name: true }, + }); + + if (!user) { + throw new Error("User not found"); + } + + const articleDataWithWriterName = { + ...articleData, + writer: user.name!, + user: { + connect: { id: userId }, }, + }; + + return await prisma.article.create({ + data: articleDataWithWriterName, }); }; diff --git a/src/services/commentService.ts b/src/services/commentService.ts index de70277..e20787e 100644 --- a/src/services/commentService.ts +++ b/src/services/commentService.ts @@ -54,11 +54,24 @@ export const createComment = async (commentData: { productId?: string; articleId?: string; }): Promise => { + const user = await prisma.user.findUnique({ + where: { id: commentData.userId }, + select: { name: true }, + }); + + if (!user) { + throw new Error("User not found"); + } + + const commentDataWithWriterName = { + ...commentData, + writer: user.name!, + }; + return await prisma.comment.create({ - data: commentData, + data: commentDataWithWriterName, }); }; - export const updateComment = async (commentId: string, userId: number, content: string): Promise => { const comment = await prisma.comment.findUnique({ where: { id: commentId }, diff --git a/src/services/productService.ts b/src/services/productService.ts index f40a8b2..e6ae50a 100644 --- a/src/services/productService.ts +++ b/src/services/productService.ts @@ -40,9 +40,26 @@ export const getProducts = async ({ }); }; -export const createProduct = async (productData: Prisma.ProductCreateInput): Promise => { - return await prisma.product.create({ - data: productData, +export const createArticle = async (userId: number, articleData: Omit) => { + const user = await prisma.user.findUnique({ + where: { id: userId }, + select: { name: true }, + }); + + if (!user) { + throw new Error("User not found"); + } + + const articleDataWithWriterName = { + ...articleData, + writer: user.name!, + user: { + connect: { id: userId }, + }, + }; + + return await prisma.article.create({ + data: articleDataWithWriterName, }); }; From 49d46fc051cd0a7e65a0f2c7e72583f677026fa3 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Sun, 2 Jun 2024 13:30:04 +0900 Subject: [PATCH 42/60] =?UTF-8?q?[#M11]=20fix=20:=20=EC=A4=91=EA=B3=A0?= =?UTF-8?q?=EB=A7=88=EC=BC=93=EA=B3=BC=20=EC=9E=90=EC=9C=A0=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=ED=8C=90=EC=97=90=EC=84=9C=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EB=93=B1=EB=A1=9D,=20=EC=88=98=EC=A0=95=EC=9D=B4?= =?UTF-8?q?=20=EC=A0=9C=EB=8C=80=EB=A1=9C=20=EB=90=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- http/articles.http | 9 +- http/products.http | 9 +- .../migration.sql | 12 ++ prisma/mock.ts | 42 +++++- prisma/schema.prisma | 10 +- prisma/seed.ts | 9 +- src/controllers/articleController.ts | 21 +-- src/controllers/productController.ts | 17 ++- src/services/articleService.ts | 72 +++++++++-- src/services/productService.ts | 120 +++++++++++++++--- src/structs.ts | 2 +- test.html | 2 +- 12 files changed, 254 insertions(+), 71 deletions(-) create mode 100644 prisma/migrations/20240602035455_delete_image_url/migration.sql diff --git a/http/articles.http b/http/articles.http index 58cd57c..b65d943 100644 --- a/http/articles.http +++ b/http/articles.http @@ -9,7 +9,7 @@ GET http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da ### # 게시글 등록 POST http://localhost:3000/articles -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODU1MiwiZXhwIjoxNzE3MTI5NDUyfQ.OAcMKEyrlzrtCOlz4HXu3mmDdEQ0s-oYBlbvlHWAJUY +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzMwNDc2OCwiZXhwIjoxNzE3MzA1NjY4fQ.0Neh8i3gQWCU0o0y01-Co8jsW8kiXKl3dW7H6wK94pY Content-Type: application/json { @@ -20,13 +20,14 @@ Content-Type: application/json ### # 게시글 수정 -PATCH http://localhost:3000/articles/dc196ae3-0d72-4f4d-9057-a83e6bece8bc -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODU1MiwiZXhwIjoxNzE3MTI5NDUyfQ.OAcMKEyrlzrtCOlz4HXu3mmDdEQ0s-oYBlbvlHWAJUY +PATCH http://localhost:3000/articles/802a7c2b-d3c5-48d7-8caf-13c6cc803d78 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzMwNDc2OCwiZXhwIjoxNzE3MzA1NjY4fQ.0Neh8i3gQWCU0o0y01-Co8jsW8kiXKl3dW7H6wK94pY Content-Type: application/json { "title":"판다 대박이네요", - "content":"대나무를 잘 먹네요 ㄷㄷ" + "content":"대나무를 잘 먹네요 ㄷㄷ", + "imageUrl":"https://cdn.011st.com/11dims/resize/600x600/quality/75/11src/product/5575072075/B.jpg?51000000" } ### diff --git a/http/products.http b/http/products.http index a76a9ec..dfa1ea1 100644 --- a/http/products.http +++ b/http/products.http @@ -18,7 +18,7 @@ GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc ### # 상품 등록 POST http://localhost:3000/products -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODc3NiwiZXhwIjoxNzE3MTI5Njc2fQ.1P-sxAljy-HP-1LQ3F53tJJLCry3--KdL6mJSZSy4bc +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzMwNTM2MCwiZXhwIjoxNzE3MzA2MjYwfQ.oxUkWqPB86HyizeCuzU-KcWvnOGRiA1_8CNPh9HuO0A Content-Type: application/json { @@ -26,20 +26,21 @@ Content-Type: application/json "description": "세종시청에서 교환원합니다.", "price": 20000, "tags": ["판다", "불곰"], - "images": ["https://www.wishbucket.io/_next/image?url=https%3A%2F%2Fd2gfz7wkiigkmv.cloudfront.net%2Fpickin%2F2%2F1%2F2%2FHereyhSJRMOmUw7I5uWAxg&w=640&q=75","https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg"] + "imageUrl": "://www.wishbucket.io/_next/image?url=https%3A%2F%2Fd2gfz7wkiigkmv.cloudfront.net%2Fpickin%2F2%2F1%2F2%2FHereyhSJRMOmUw7I5uWAxg&w=640&q=75" } ### # 상품 수정 PATCH http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODc3NiwiZXhwIjoxNzE3MTI5Njc2fQ.1P-sxAljy-HP-1LQ3F53tJJLCry3--KdL6mJSZSy4bc +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzMwNTM2MCwiZXhwIjoxNzE3MzA2MjYwfQ.oxUkWqPB86HyizeCuzU-KcWvnOGRiA1_8CNPh9HuO0A Content-Type: application/json { "name":"판다 안팔려서 안판다", "description":"안판다고 했지만 사실은 판다", "price":7000, - "tags":["판다","안판다"] + "tags":["판다","안판다"], + "imageUrl": "https://www.wishbucket.io/_next/image?url=https%3A%2F%2Fd2gfz7wkiigkmv.cloudfront.net%2Fpickin%2F2%2F1%2F2%2FHereyhSJRMOmUw7I5uWAxg&w=640&q=75" } ### diff --git a/prisma/migrations/20240602035455_delete_image_url/migration.sql b/prisma/migrations/20240602035455_delete_image_url/migration.sql new file mode 100644 index 0000000..f6df9e8 --- /dev/null +++ b/prisma/migrations/20240602035455_delete_image_url/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - You are about to drop the column `imageUrl` on the `Article` table. All the data in the column will be lost. + - You are about to drop the column `images` on the `Product` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "Article" DROP COLUMN "imageUrl"; + +-- AlterTable +ALTER TABLE "Product" DROP COLUMN "images"; diff --git a/prisma/mock.ts b/prisma/mock.ts index db1cb39..482fe2b 100644 --- a/prisma/mock.ts +++ b/prisma/mock.ts @@ -2,7 +2,6 @@ export const PRODUCTS = [ { id: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", favoriteCount: 7, - images: ["https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg"], tags: ["판다인형", "인형", "판다"], price: 700000, description: "판다인형 판다", @@ -13,9 +12,6 @@ export const PRODUCTS = [ { id: "d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9", favoriteCount: 2, - images: [ - "https://view01.wemep.co.kr/wmp-product/4/879/2515748794/pm_ebifv5nrjsyf.jpg?1683280710&f=webp&w=460&h=460", - ], tags: ["판다인형", "인형", "판다", "불곰"], price: 7000, description: "판다인형 안판다", @@ -30,7 +26,6 @@ export const ARTICLES = [ id: "2c027764-d7ef-4a94-8399-f15ffbf8f4da", title: "판다인형 구매 후기", content: "판다인형 구매 후기입니다.", - imageUrl: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", likeCount: 7, userId: 1, writer: "김판다", @@ -39,7 +34,6 @@ export const ARTICLES = [ id: "7c8b9d2e-5d45-4c9f-9b4b-7626f3c9c9a9", title: "판다인형 판매 후기", content: "판다인형 판매 후기입니다.", - imageUrl: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", likeCount: 2, userId: 1, writer: "김판다", @@ -48,7 +42,6 @@ export const ARTICLES = [ id: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", title: "불곰인형 구하는 곳 아시는분", content: "불곰인형 구하는 곳 아시는분 계신가요?", - imageUrl: "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg", likeCount: 3, userId: 2, writer: "김판다", @@ -201,3 +194,38 @@ export const FAVORITE = [ productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", }, ]; + +export const IMAGE = [ + { + id: "1a2b3c4d-5e6f-7g8h-9i0j-1k2l3m4n5o6p", + imagePath: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", + articleId: "2c027764-d7ef-4a94-8399-f15ffbf8f4da", + }, + { + id: "2b3c4d5e-6f7g-8h9i-0j1k-2l3m4n5o6p7q", + imagePath: + "https://view01.wemep.co.kr/wmp-product/4/879/2515748794/pm_ebifv5nrjsyf.jpg?1683280710&f=webp&w=460&h=460", + articleId: "7c8b9d2e-5d45-4c9f-9b4b-7626f3c9c9a9", + }, + { + id: "3c4d5e6f-7g8h-9i0j-1k2l-3m4n5o6p7q8r", + imagePath: "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg", + articleId: "287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3", + }, + { + id: "4d5e6f7g-8h9i-0j1k-2l3m4n5o6p7q8r9s", + imagePath: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, + { + id: "5e6f7g8h-9i0j-1k2l-3m4n5o6p7q8r9s0t", + imagePath: + "https://view01.wemep.co.kr/wmp-product/4/879/2515748794/pm_ebifv5nrjsyf.jpg?1683280710&f=webp&w=460&h=460", + productId: "d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9", + }, + { + id: "6f7g8h9i-0j1k-2l3m4n5o6p7q8r9s0t1u", + imagePath: "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg", + productId: "377ce06c-23c8-46de-b86f-2cfd43d41cbc", + }, +]; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index da1d50b..69b7735 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -30,12 +30,11 @@ model Product { description String price Int tags String[] - images String[] favoriteCount Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt comments Comment[] - image Image[] + images Image[] @relation("ProductImages") user User @relation(fields: [userId], references: [id], onDelete: Cascade) userId Int favorites Favorite[] @@ -46,12 +45,11 @@ model Article { title String writer String content String - imageUrl String? @default("") likeCount Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt comments Comment[] - image Image[] + images Image[] @relation("ArticleImages") user User @relation(fields: [userId], references: [id], onDelete: Cascade) userId Int favorites Favorite[] @@ -77,11 +75,11 @@ model Comment { model Image { id String @id @default(uuid()) imagePath String - product Product? @relation(fields: [productId], references: [id], onDelete: SetNull) + product Product? @relation(fields: [productId], references: [id], onDelete: SetNull, name: "ProductImages") productId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt - article Article? @relation(fields: [articleId], references: [id], onDelete: SetNull) + article Article? @relation(fields: [articleId], references: [id], onDelete: SetNull, name: "ArticleImages") articleId String? @@index([productId]) diff --git a/prisma/seed.ts b/prisma/seed.ts index 7e067cf..812aafa 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,5 +1,5 @@ import { PrismaClient } from "@prisma/client"; -import { ARTICLES, COMMENTS, FAVORITE, PRODUCTS, USERS } from "./mock.js"; +import { ARTICLES, COMMENTS, FAVORITE, IMAGE, PRODUCTS, USERS } from "./mock.js"; const prisma = new PrismaClient(); async function main() { @@ -23,6 +23,13 @@ async function main() { skipDuplicates: true, }); + await prisma.image.deleteMany(); + + await prisma.image.createMany({ + data: IMAGE, + skipDuplicates: true, + }); + await prisma.favorite.deleteMany(); await prisma.favorite.createMany({ diff --git a/src/controllers/articleController.ts b/src/controllers/articleController.ts index f04c401..65f4c84 100644 --- a/src/controllers/articleController.ts +++ b/src/controllers/articleController.ts @@ -1,4 +1,3 @@ -import { Prisma } from "@prisma/client"; import { NextFunction, Request, Response } from "express"; import { assert } from "superstruct"; import * as articleService from "../services/articleService"; @@ -30,10 +29,9 @@ export const getArticles = async (req: Request<{}, {}, {}, GetArticlesQuery>, re export const createArticle = async (req: UserRequest, res: Response) => { assert(req.body, CreateArticle); const { userId } = req; + const { imageUrl, ...articleData } = req.body; - const articleData: Omit = req.body; - - const article = await articleService.createArticle(userId, articleData); + const article = await articleService.createArticle(userId!, articleData, imageUrl || ""); res.status(201).send(article); }; @@ -47,18 +45,11 @@ export const getArticleById = async (req: Request<{ id: string }>, res: Response // PATCH /articles/:id export const updateArticle = async (req: UserRequest & Request<{ id: string }>, res: Response): Promise => { assert(req.body, PatchArticle); - const { id: articleId } = req.params; const { userId } = req; - try { - const updatedArticle = await articleService.updateArticle(articleId, userId, req.body); - res.send(updatedArticle); - } catch (error) { - if (error instanceof AppError) { - res.status(error.statusCode).json({ message: error.message }); - return; - } - throw error; - } + const { id } = req.params; + const { imageUrl, ...articleData } = req.body; + const updatedArticle = await articleService.updateArticle(id, userId!, articleData, imageUrl || ""); + res.send(updatedArticle); }; // DELETE /articles/:id diff --git a/src/controllers/productController.ts b/src/controllers/productController.ts index 7e48691..58cff79 100644 --- a/src/controllers/productController.ts +++ b/src/controllers/productController.ts @@ -16,18 +16,17 @@ export const getProducts = async ( const offsetNumber = parseInt(offset, 10); const limitNumber = parseInt(limit, 10); const products = await productService.getProducts({ offset: offsetNumber, limit: limitNumber, orderBy, keyword }); - res.send(products); + const bestProducts = await productService.getBestProducts(); + res.send({ products, bestProducts }); }; // POST /products export const createProduct = async (req: UserRequest, res: Response) => { assert(req.body, CreateProduct); const { userId } = req; - const productData = { - ...req.body, - user: { connect: { id: userId } }, - }; - const product = await productService.createProduct(productData); + const { imageUrl, ...productData } = req.body; + + const product = await productService.createProduct(userId!, productData, imageUrl || ""); res.status(201).send(product); }; @@ -42,11 +41,11 @@ export const getProductById = async (req: Request<{ id: string }>, res: Response export const updateProduct = async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { assert(req.body, PatchProduct); - const { id: productId } = req.params; const { userId } = req; - + const { id } = req.params; + const { imageUrl, ...productData } = req.body; try { - const updatedProduct = await productService.updateProduct(productId, userId, req.body); + const updatedProduct = await productService.updateProduct(id, userId, productData, imageUrl || ""); res.send(updatedProduct); } catch (error) { res.status(403).json({ message: (error as Error).message }); diff --git a/src/services/articleService.ts b/src/services/articleService.ts index e2bcb5b..2e8b7e3 100644 --- a/src/services/articleService.ts +++ b/src/services/articleService.ts @@ -22,9 +22,13 @@ export const getArticles = async ({ id: true, title: true, content: true, - imageUrl: true, createdAt: true, writer: true, + images: { + select: { + imagePath: true, + }, + }, }, orderBy: order, skip: offset, @@ -52,6 +56,18 @@ export const getArticles = async ({ export const getBestArticles = async () => { const bestArticles = await prisma.article.findMany({ + select: { + id: true, + title: true, + content: true, + createdAt: true, + writer: true, + images: { + select: { + imagePath: true, + }, + }, + }, orderBy: { likeCount: "desc", }, @@ -61,26 +77,36 @@ export const getBestArticles = async () => { return bestArticles; }; -export const createArticle = async (userId: number, articleData: Omit) => { +export const createArticle = async ( + userId: number, + articleData: Omit, + imageUrl: string +) => { const user = await prisma.user.findUnique({ where: { id: userId }, select: { name: true }, }); if (!user) { - throw new Error("User not found"); + throw new Error("유저 정보를 찾을 수 없습니다."); } - const articleDataWithWriterName = { + const articleDataWithWriterName: Prisma.ArticleCreateInput = { ...articleData, writer: user.name!, user: { connect: { id: userId }, }, + images: { + create: [{ imagePath: imageUrl }], + }, }; return await prisma.article.create({ data: articleDataWithWriterName, + include: { + images: true, + }, }); }; @@ -91,26 +117,56 @@ export const getArticleById = async (id: string) => { id: true, title: true, content: true, - imageUrl: true, createdAt: true, likeCount: true, writer: true, + images: { + select: { + imagePath: true, + }, + }, }, }); }; -export const updateArticle = async (articleId: string, userId: number, articleData: Prisma.ArticleUpdateInput) => { +export const updateArticle = async ( + id: string, + userId: number, + articleData: Prisma.ArticleUpdateInput, + imageUrl: string +) => { const article = await prisma.article.findUniqueOrThrow({ - where: { id: articleId }, + where: { id }, + include: { images: true }, }); if (article.userId !== userId) { throw new AppError("게시글을 수정할 권한이 없습니다.", 403); } + if (imageUrl) { + const existingImage = article.images[0]; + if (existingImage) { + await prisma.image.update({ + where: { id: existingImage.id }, + data: { imagePath: imageUrl }, + }); + } else { + await prisma.image.create({ + data: { + imagePath: imageUrl, + article: { connect: { id } }, + }, + }); + } + } + return await prisma.article.update({ - where: { id: articleId }, + where: { id }, data: articleData, + include: { + images: true, + }, }); }; diff --git a/src/services/productService.ts b/src/services/productService.ts index e6ae50a..6ec3157 100644 --- a/src/services/productService.ts +++ b/src/services/productService.ts @@ -21,6 +21,23 @@ export const getProducts = async ({ orderBy: order, skip: offset, take: limit, + select: { + id: true, + name: true, + description: true, + price: true, + favoriteCount: true, + createdAt: true, + updatedAt: true, + writer: true, + tags: true, + userId: true, + images: { + select: { + imagePath: true, + }, + }, + }, where: { OR: [ { @@ -40,32 +57,87 @@ export const getProducts = async ({ }); }; -export const createArticle = async (userId: number, articleData: Omit) => { +export const getBestProducts = async () => { + const bestProducts = await prisma.product.findMany({ + select: { + id: true, + name: true, + description: true, + price: true, + favoriteCount: true, + createdAt: true, + updatedAt: true, + writer: true, + tags: true, + userId: true, + images: { + select: { + imagePath: true, + }, + }, + }, + orderBy: { + favoriteCount: "desc", + }, + take: 4, + }); + + return bestProducts; +}; + +export const createProduct = async ( + userId: number, + productData: Omit, + imageUrl: string +) => { const user = await prisma.user.findUnique({ where: { id: userId }, select: { name: true }, }); if (!user) { - throw new Error("User not found"); + throw new Error("유저 정보를 찾을 수 없습니다."); } - const articleDataWithWriterName = { - ...articleData, + const productDataWithWriterName = { + ...productData, writer: user.name!, user: { connect: { id: userId }, }, + images: { + create: [{ imagePath: imageUrl }], + }, }; - return await prisma.article.create({ - data: articleDataWithWriterName, + return await prisma.product.create({ + data: productDataWithWriterName, + include: { + images: true, + }, }); }; export const getProductById = async (id: string): Promise => { const product = await prisma.product.findUnique({ where: { id }, + select: { + id: true, + name: true, + description: true, + price: true, + favoriteCount: true, + createdAt: true, + writer: true, + images: { + select: { + imagePath: true, + }, + }, + tags: true, + updatedAt: true, + userId: true, + }, }); if (!product) { @@ -75,25 +147,43 @@ export const getProductById = async (id: string): Promise => { }; export const updateProduct = async ( - productId: string, + id: string, userId: number, - productData: Prisma.ProductUpdateInput + productData: Prisma.ProductUpdateInput, + imageUrl: string ): Promise => { - const product = await prisma.product.findUnique({ - where: { id: productId }, + const product = await prisma.product.findUniqueOrThrow({ + where: { id }, + include: { images: true }, }); - if (!product) { - throw new AppError("존재하지 않는 상품입니다.", 404); - } - if (product.userId !== userId) { throw new AppError("상품을 수정할 권한이 없습니다.", 403); } + if (imageUrl) { + const existingImage = product.images[0]; + if (existingImage) { + await prisma.image.update({ + where: { id: existingImage.id }, + data: { imagePath: imageUrl }, + }); + } else { + await prisma.image.create({ + data: { + imagePath: imageUrl, + product: { connect: { id } }, + }, + }); + } + } + return await prisma.product.update({ - where: { id: productId }, + where: { id }, data: productData, + include: { + images: true, + }, }); }; diff --git a/src/structs.ts b/src/structs.ts index 7b40173..7a9bac4 100644 --- a/src/structs.ts +++ b/src/structs.ts @@ -3,11 +3,11 @@ import * as s from "superstruct"; const PositivePrice = s.refine(s.number(), "PositivePrice", (value) => value > 0 && value < 1000000000); export const CreateProduct = s.object({ - images: s.array(s.string()), tags: s.array(s.size(s.string(), 1, 32)), price: PositivePrice, description: s.string(), name: s.size(s.string(), 1, 60), + imageUrl: s.optional(s.string()), }); export const PatchProduct = s.partial(CreateProduct); diff --git a/test.html b/test.html index 4e32f08..ddb7fb2 100644 --- a/test.html +++ b/test.html @@ -19,7 +19,7 @@ const form = event.target; const formData = new FormData(form); - const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NTQ4MCwiZXhwIjoxNzE2ODc2MzgwfQ.c07c8gt-7uMUXVssa1cf5CtZFCFaWXHczV1m_rAtSJo'; // 여기에 실제 JWT 토큰을 넣습니다. + const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NTQ4MCwiZXhwIjoxNzE2ODc2MzgwfQ.c07c8gt-7uMUXVssa1cf5CtZFCFaWXHczV1m_rAtSJo'; try { const response = await fetch('http://localhost:3000/images/upload', { From 170bc41a387d260a117fba46f83366232c6237a8 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Mon, 3 Jun 2024 09:57:26 +0900 Subject: [PATCH 43/60] =?UTF-8?q?[#M12]=20feat=20:=20jest=20=EC=84=A4?= =?UTF-8?q?=EC=B9=98=20=EB=B0=8F=20=EC=A4=91=EA=B3=A0=EB=A7=88=EC=BC=93=20?= =?UTF-8?q?=EC=83=81=ED=92=88=20=EB=93=B1=EB=A1=9D=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- babel.config.cjs | 3 + http/products.http | 2 +- jest.config.cjs | 9 + package-lock.json | 7305 ++++++++++++++++++++++++++------ package.json | 11 +- src/client.ts | 4 + src/context.ts | 16 + src/services/authService.ts | 2 +- src/services/productService.ts | 5 +- src/singleton.ts | 15 + src/test/product.test.ts | 78 + tsconfig.json | 1 + yarn.lock | 2870 ++++++++++++- 13 files changed, 8950 insertions(+), 1371 deletions(-) create mode 100644 babel.config.cjs create mode 100644 jest.config.cjs create mode 100644 src/client.ts create mode 100644 src/context.ts create mode 100644 src/singleton.ts create mode 100644 src/test/product.test.ts diff --git a/babel.config.cjs b/babel.config.cjs new file mode 100644 index 0000000..2afcfd2 --- /dev/null +++ b/babel.config.cjs @@ -0,0 +1,3 @@ +module.exports = { + presets: [["@babel/preset-env", { targets: { node: "current" } }], "@babel/preset-typescript"], +}; diff --git a/http/products.http b/http/products.http index dfa1ea1..ac4a7d6 100644 --- a/http/products.http +++ b/http/products.http @@ -18,7 +18,7 @@ GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc ### # 상품 등록 POST http://localhost:3000/products -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzMwNTM2MCwiZXhwIjoxNzE3MzA2MjYwfQ.oxUkWqPB86HyizeCuzU-KcWvnOGRiA1_8CNPh9HuO0A +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzM2ODk4OCwiZXhwIjoxNzE3MzY5ODg4fQ.KJMk2M5J_3fkHsYGljXhx30vBVUZI4rMYAOiROf6gLo Content-Type: application/json { diff --git a/jest.config.cjs b/jest.config.cjs new file mode 100644 index 0000000..1f9d819 --- /dev/null +++ b/jest.config.cjs @@ -0,0 +1,9 @@ +module.exports = { + transform: { + "^.+\\.[tj]sx?$": "babel-jest", + }, + clearMocks: true, + preset: "ts-jest", + testEnvironment: "node", + setupFilesAfterEnv: ["./src/singleton.ts"], +}; diff --git a/package-lock.json b/package-lock.json index 0fbfe52..689780e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "express": "^4.18.2", "is-email": "^1.0.2", "is-uuid": "^1.0.2", + "jest-mock-extended": "^3.0.7", "jsonwebtoken": "^9.0.2", "moment-timezone": "^0.5.45", "multer": "^1.4.5-lts.1", @@ -22,6 +23,9 @@ "swagger-ui-express": "^5.0.0" }, "devDependencies": { + "@babel/preset-env": "^7.24.6", + "@babel/preset-typescript": "^7.24.6", + "@jest/globals": "^29.7.0", "@types/bcrypt": "^5.0.2", "@types/cors": "^2.8.17", "@types/express": "^4.17.21", @@ -35,15 +39,40 @@ "@types/passport-google-oauth20": "^2.0.16", "@types/swagger-jsdoc": "^6.0.4", "@types/swagger-ui-express": "^4.1.6", + "babel-jest": "^29.7.0", "cors": "^2.8.5", "express-session": "^1.18.0", + "jest": "^29.7.0", "morgan": "^1.10.0", + "node-mocks-http": "^1.14.1", "nodemon": "^3.1.2", + "ts-jest": "^29.1.4", "ts-node": "^10.9.2", "tsx": "^4.11.0", "typescript": "^5.4.5" } }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@ampproject/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@apidevtools/json-schema-ref-parser": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", @@ -84,1809 +113,5528 @@ "openapi-types": ">=7" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, + "node_modules/@babel/code-frame": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz", + "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@babel/highlight": "^7.24.6", + "picocolors": "^1.0.0" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], + "node_modules/@babel/compat-data": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.6.tgz", + "integrity": "sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==", "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" + "node_modules/@babel/core": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.6.tgz", + "integrity": "sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.6", + "@babel/generator": "^7.24.6", + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helpers": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/template": "^7.24.6", + "@babel/traverse": "^7.24.6", + "@babel/types": "^7.24.6", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, "engines": { - "node": ">=12" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", - "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@babel/generator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.6.tgz", + "integrity": "sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==", + "dependencies": { + "@babel/types": "^7.24.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz", + "integrity": "sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@babel/types": "^7.24.6" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", - "cpu": [ - "x64" - ], + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.6.tgz", + "integrity": "sha512-+wnfqc5uHiMYtvRX7qu80Toef8BXeh4HHR1SPeonGb1SKPniNEd4a/nlaJJMv/OIEYvIVavvo0yR7u10Gqz0Iw==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@babel/types": "^7.24.6" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/helper-compilation-targets": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz", + "integrity": "sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==", + "dependencies": { + "@babel/compat-data": "^7.24.6", + "@babel/helper-validator-option": "^7.24.6", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.6.tgz", + "integrity": "sha512-djsosdPJVZE6Vsw3kk7IPRWethP94WHGOhQTc67SNXE0ZzMhHgALw8iGmYS0TD1bbMM0VDROy43od7/hN6WYcA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-member-expression-to-functions": "^7.24.6", + "@babel/helper-optimise-call-expression": "^7.24.6", + "@babel/helper-replace-supers": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "semver": "^6.3.1" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", - "cpu": [ - "loong64" - ], + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", - "cpu": [ - "mips64el" - ], + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.6.tgz", + "integrity": "sha512-C875lFBIWWwyv6MHZUG9HmRrlTDgOsLWZfYR0nW69gaKJNe0/Mpxx5r0EID2ZdHQkdUmQo2t0uNckTL08/1BgA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", - "cpu": [ - "riscv64" - ], + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", - "cpu": [ - "s390x" - ], + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "ms": "2.1.2" + }, "engines": { - "node": ">=12" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz", + "integrity": "sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==", "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], + "node_modules/@babel/helper-function-name": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz", + "integrity": "sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==", + "dependencies": { + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], + "node_modules/@babel/helper-hoist-variables": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz", + "integrity": "sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==", + "dependencies": { + "@babel/types": "^7.24.6" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", - "cpu": [ - "x64" - ], + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.6.tgz", + "integrity": "sha512-OTsCufZTxDUsv2/eDXanw/mUZHWOxSbEmC3pP8cgjcy5rgeVPWWMStnv274DV60JtHxTk0adT0QrCzC4M9NWGg==", "dev": true, - "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "@babel/types": "^7.24.6" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@babel/helper-module-imports": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz", + "integrity": "sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==", + "dependencies": { + "@babel/types": "^7.24.6" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@babel/helper-module-transforms": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz", + "integrity": "sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-module-imports": "^7.24.6", + "@babel/helper-simple-access": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.6.tgz", + "integrity": "sha512-3SFDJRbx7KuPRl8XDUr8O7GAEB8iGyWPjLKJh/ywP/Iy9WOmEfMrsWbaZpvBu2HSYn4KQygIsz0O7m8y10ncMA==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/types": "^7.24.6" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.6.tgz", + "integrity": "sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg==", "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.6.tgz", + "integrity": "sha512-1Qursq9ArRZPAMOZf/nuzVW8HgJLkTB9y9LfP4lW2MVp4e9WkLJDovfKBxoDcCk6VuzIxyqWHyBoaCtSRP10yg==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-wrap-function": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@jsdevtools/ono": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" - }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "node_modules/@babel/helper-replace-supers": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.6.tgz", + "integrity": "sha512-mRhfPwDqDpba8o1F8ESxsEkJMQkUF8ZIWrAc0FtWhxnjfextxMWxr22RtFizxxSYLjVHDeMgVsRq8BBZR2ikJQ==", + "dev": true, "dependencies": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-member-expression-to-functions": "^7.24.6", + "@babel/helper-optimise-call-expression": "^7.24.6" }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@prisma/client": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.14.0.tgz", - "integrity": "sha512-akMSuyvLKeoU4LeyBAUdThP/uhVP3GuLygFE3MlYzaCb3/J8SfsYBE5PkaFuLuVpLyA6sFoW+16z/aPhNAESqg==", - "hasInstallScript": true, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" }, "peerDependencies": { - "prisma": "*" + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz", + "integrity": "sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==", + "dependencies": { + "@babel/types": "^7.24.6" }, - "peerDependenciesMeta": { - "prisma": { - "optional": true - } + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@prisma/debug": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.14.0.tgz", - "integrity": "sha512-iq56qBZuFfX3fCxoxT8gBX33lQzomBU0qIUaEj1RebsKVz1ob/BVH1XSBwwwvRVtZEV1b7Fxx2eVu34Ge/mg3w==" + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.6.tgz", + "integrity": "sha512-jhbbkK3IUKc4T43WadP96a27oYti9gEf1LdyGSP2rHGH77kwLwfhO7TgwnWvxxQVmke0ImmCSS47vcuxEMGD3Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@prisma/engines": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.14.0.tgz", - "integrity": "sha512-lgxkKZ6IEygVcw6IZZUlPIfLQ9hjSYAtHjZ5r64sCLDgVzsPFCi2XBBJgzPMkOQ5RHzUD4E/dVdpn9+ez8tk1A==", - "hasInstallScript": true, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", + "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", "dependencies": { - "@prisma/debug": "5.14.0", - "@prisma/engines-version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", - "@prisma/fetch-engine": "5.14.0", - "@prisma/get-platform": "5.14.0" + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@prisma/engines-version": { - "version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48.tgz", - "integrity": "sha512-ip6pNkRo1UxWv+6toxNcYvItNYaqQjXdFNGJ+Nuk2eYtRoEdoF13wxo7/jsClJFFenMPVNVqXQDV0oveXnR1cA==" + "node_modules/@babel/helper-string-parser": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz", + "integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==", + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@prisma/fetch-engine": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.14.0.tgz", - "integrity": "sha512-VrheA9y9DMURK5vu8OJoOgQpxOhas3qF0IBHJ8G/0X44k82kc8E0w98HCn2nhnbOOMwbWsJWXfLC2/F8n5u0gQ==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz", + "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz", + "integrity": "sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.6.tgz", + "integrity": "sha512-f1JLrlw/jbiNfxvdrfBgio/gRBk3yTAEJWirpAkiJG2Hb22E7cEYKHWo0dFPTv/niPovzIdPdEDetrv6tC6gPQ==", + "dev": true, "dependencies": { - "@prisma/debug": "5.14.0", - "@prisma/engines-version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", - "@prisma/get-platform": "5.14.0" + "@babel/helper-function-name": "^7.24.6", + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@prisma/get-platform": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.14.0.tgz", - "integrity": "sha512-/yAyBvcEjRv41ynZrhdrPtHgk47xLRRq/o5eWGcUpBJ1YrUZTYB8EoPiopnP7iQrMATK8stXQdPOoVlrzuTQZw==", + "node_modules/@babel/helpers": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.6.tgz", + "integrity": "sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==", "dependencies": { - "@prisma/debug": "5.14.0" + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true - }, - "node_modules/@types/bcrypt": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", - "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==", - "dev": true, + "node_modules/@babel/highlight": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz", + "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==", "dependencies": { - "@types/node": "*" + "@babel/helper-validator-identifier": "^7.24.6", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { - "@types/connect": "*", - "@types/node": "*" + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { - "@types/node": "*" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/@types/cors": { - "version": "2.8.17", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", - "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", - "dev": true, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { - "@types/node": "*" + "color-name": "1.1.3" } }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" } }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.2.tgz", - "integrity": "sha512-dPSEQElyVJ97BuGduAqQjpBocZWAs0GR94z+ptL7JXQJeJdHw2WBG3EWdFrK36b8Q6j8P4cXOMhgUoi0IIfIsg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" + "node_modules/@babel/parser": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", + "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@types/express-session": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.18.0.tgz", - "integrity": "sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA==", + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.6.tgz", + "integrity": "sha512-bYndrJ6Ph6Ar+GaB5VAc0JPoP80bQCm4qon6JEzXfRl5QZyQ8Ur1K6k7htxWmPA5z+k7JQvaMUrtXlqclWYzKw==", "dev": true, "dependencies": { - "@types/express": "*" + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true - }, - "node_modules/@types/is-email": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/is-email/-/is-email-1.0.0.tgz", - "integrity": "sha512-b/76ooKpYY/b+oPrOuc/pmM5eag+ZlzctPsKcRCIKs+TFzh0FL58OeXtSPkbXt3uKNK84YCKHmjnoREtwve5Kg==", - "dev": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" - }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", - "integrity": "sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==", + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.6.tgz", + "integrity": "sha512-iVuhb6poq5ikqRq2XWU6OQ+R5o9wF+r/or9CeUyovgptz0UlnK4/seOQ1Istu/XybYjAhQv1FRSSfHHufIku5Q==", "dev": true, "dependencies": { - "@types/node": "*" + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true - }, - "node_modules/@types/morgan": { - "version": "1.9.9", - "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.9.tgz", - "integrity": "sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==", + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.6.tgz", + "integrity": "sha512-c8TER5xMDYzzFcGqOEp9l4hvB7dcbhcGjcLVwxWfe4P5DOafdwjsBJZKsmv+o3aXh7NhopvayQIovHrh2zSRUQ==", "dev": true, "dependencies": { - "@types/node": "*" + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", + "@babel/plugin-transform-optional-chaining": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" } }, - "node_modules/@types/multer": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.11.tgz", - "integrity": "sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==", + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.6.tgz", + "integrity": "sha512-z8zEjYmwBUHN/pCF3NuWBhHQjJCrd33qAi8MgANfMrAvn72k2cImT8VjK9LJFu4ysOLJqhfkYYb3MvwANRUNZQ==", "dev": true, "dependencies": { - "@types/express": "*" + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@types/node": { - "version": "20.12.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.13.tgz", - "integrity": "sha512-gBGeanV41c1L171rR7wjbMiEpEI/l5XFQdLLfhr/REwpgDy/4U8y89+i8kRiLzDyZdOkXh+cRaTetUnCYutoXA==", + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dependencies": { - "undici-types": "~5.26.4" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/oauth": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.5.tgz", - "integrity": "sha512-+oQ3C2Zx6ambINOcdIARF5Z3Tu3x//HipE889/fqo3sgpQZbe9c6ExdQFtN6qlhpR7p83lTZfPJt0tCAW29dog==", - "dev": true, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dependencies": { - "@types/node": "*" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/passport": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.16.tgz", - "integrity": "sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A==", - "dev": true, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dependencies": { - "@types/express": "*" + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/passport-google-oauth20": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.16.tgz", - "integrity": "sha512-ayXK2CJ7uVieqhYOc6k/pIr5pcQxOLB6kBev+QUGS7oEZeTgIs1odDobXRqgfBPvXzl0wXCQHftV5220czZCPA==", + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dev": true, "dependencies": { - "@types/express": "*", - "@types/passport": "*", - "@types/passport-oauth2": "*" + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/passport-oauth2": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.4.17.tgz", - "integrity": "sha512-ODiAHvso6JcWJ6ZkHHroVp05EHGhqQN533PtFNBkg8Fy5mERDqsr030AX81M0D69ZcaMvhF92SRckEk2B0HYYg==", + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, "dependencies": { - "@types/express": "*", - "@types/oauth": "*", - "@types/passport": "*" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true - }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", "dev": true, "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.6.tgz", + "integrity": "sha512-BE6o2BogJKJImTmGpkmOic4V0hlRRxVtzqxiSPa8TIFxyhi4EFjHm08nq1M4STK4RytuLMgnSz0/wfflvGFNOg==", "dev": true, "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/swagger-jsdoc": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz", - "integrity": "sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ==", - "dev": true - }, - "node_modules/@types/swagger-ui-express": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz", - "integrity": "sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==", + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.6.tgz", + "integrity": "sha512-D+CfsVZousPXIdudSII7RGy52+dYRtbyKAZcvtQKq/NpsivyMVduepzcLqG5pMBugtMdedxdC8Ramdpcne9ZWQ==", "dev": true, "dependencies": { - "@types/express": "*", - "@types/serve-static": "*" + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">= 0.6" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.6.tgz", + "integrity": "sha512-lWfvAIFNWMlCsU0DRUun2GpFwZdGTukLaHJqRh1JRb80NdAP5Sb1HDHB5X9P9OtgZHQl089UzQkpYlBq2VTPRw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" }, "engines": { - "node": ">=0.4.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", - "dev": true, - "engines": { - "node": ">=0.4.0" + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dependencies": { - "debug": "4" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">= 6.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/agent-base/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dependencies": { - "ms": "2.1.2" + "@babel/helper-plugin-utils": "^7.10.4" }, - "engines": { - "node": ">=6.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/agent-base/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" - }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" - }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "deprecated": "This package is no longer supported.", + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": ">=10" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.6.tgz", + "integrity": "sha512-TzCtxGgVTEJWWwcYwQhCIQ6WaKlo80/B+Onsk4RRCcYqpYGFcG9etPW94VToGte5AAcxRrhjPUFvUS3Y2qKi4A==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "@babel/helper-plugin-utils": "^7.24.6" }, "engines": { - "node": ">= 6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base64url": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", - "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.6.tgz", + "integrity": "sha512-jSSSDt4ZidNMggcLx8SaKsbGNEfIl0PHx/4mFEulorE7bpYLbN0d3pDW3eJ7Y5Z3yPhy3L3NaPCYyTUY7TuugQ==", "dev": true, "dependencies": { - "safe-buffer": "5.1.2" + "@babel/helper-plugin-utils": "^7.24.6" }, "engines": { - "node": ">= 0.8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/basic-auth/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/bcrypt": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", - "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", - "hasInstallScript": true, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.6.tgz", + "integrity": "sha512-VEP2o4iR2DqQU6KPgizTW2mnMx6BG5b5O9iQdrW9HesLkv8GIA8x2daXBQxw1MrsIkFQGA/iJ204CKoQ8UcnAA==", + "dev": true, "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.11", - "node-addon-api": "^5.0.0" + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-remap-async-to-generator": "^7.24.6", + "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { - "node": ">= 10.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.6.tgz", + "integrity": "sha512-NTBA2SioI3OsHeIn6sQmhvXleSl9T70YY/hostQLveWs0ic+qvbA3fa0kwAwQ0OA/XGaAerNZRQGJyRfhbJK4g==", "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-remap-async-to-generator": "^7.24.6" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.6.tgz", + "integrity": "sha512-XNW7jolYHW9CwORrZgA/97tL/k05qe/HL0z/qqJq1mdWhwwCM6D4BJBV7wAz9HgFziN5dTOG31znkVIzwxv+vw==", + "dev": true, "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" + "@babel/helper-plugin-utils": "^7.24.6" }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.6.tgz", + "integrity": "sha512-S/t1Xh4ehW7sGA7c1j/hiOBLnEYCp/c2sEG4ZkL8kI1xX9tW2pqJTCHKtdhe/jHKt8nG0pFCrDHUXd4DvjHS9w==", + "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.6.tgz", + "integrity": "sha512-j6dZ0Z2Z2slWLR3kt9aOmSIrBvnntWjMDN/TVcMPxhXMLmJVqX605CBRlcGI4b32GMbfifTEsdEjGjiE+j/c3A==", "dev": true, "dependencies": { - "fill-range": "^7.1.1" + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.6.tgz", + "integrity": "sha512-1QSRfoPI9RoLRa8Mnakc6v3e0gJxiZQTYrMfLn+mD0sz5+ndSzwymp2hDcYJTyT0MOn0yuWzj8phlIvO72gTHA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "node_modules/@babel/plugin-transform-classes": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.6.tgz", + "integrity": "sha512-+fN+NO2gh8JtRmDSOB6gaCVo36ha8kfCW1nMq2Gc0DABln0VcHN4PrALDvF5/diLzIRKptC7z/d7Lp64zk92Fg==", + "dev": true, "dependencies": { - "streamsearch": "^1.1.0" + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-replace-supers": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "globals": "^11.1.0" }, "engines": { - "node": ">=10.16.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.6.tgz", + "integrity": "sha512-cRzPobcfRP0ZtuIEkA8QzghoUpSB3X3qSH5W2+FzG+VjWbJXExtx0nbRqwumdBN1x/ot2SlTNQLfBCnPdzp6kg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/template": "^7.24.6" + }, "engines": { - "node": ">= 0.8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.6.tgz", + "integrity": "sha512-YLW6AE5LQpk5npNXL7i/O+U9CE4XsBCuRPgyjl1EICZYKmcitV+ayuuUGMJm2lC1WWjXYszeTnIxF/dq/GhIZQ==", + "dev": true, "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "@babel/helper-plugin-utils": "^7.24.6" }, "engines": { - "node": ">= 0.4" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.6.tgz", + "integrity": "sha512-rCXPnSEKvkm/EjzOtLoGvKseK+dS4kZwx1HexO3BtRtgL0fQ34awHn34aeSHuXtZY2F8a1X8xqBBPRtOxDVmcA==", "dev": true, "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" + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" }, "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">=6.9.0" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.6.tgz", + "integrity": "sha512-/8Odwp/aVkZwPFJMllSbawhDAO3UJi65foB00HYnK/uXvvCPm0TAXSByjz1mpRmp0q6oX2SIxpkUOpPFHk7FLA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, "engines": { - "node": ">=10" - } - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "bin": { - "color-support": "bin.js" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/commander": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", - "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.6.tgz", + "integrity": "sha512-vpq8SSLRTBLOHUZHSnBqVo0AKX3PBaoPs2vVzYVWslXDTDIpwAcCDtfhUcHSQQoYoUvcFPTdC8TZYXu9ZnLT/w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, "engines": { - "node": ">= 6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "engines": [ - "node >= 0.8" - ], + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.6.tgz", + "integrity": "sha512-EemYpHtmz0lHE7hxxxYEuTYOOBZ43WkDgZ4arQ4r+VX9QHuNZC+WH3wUWmRNvR8ECpTRne29aZV6XO22qpOtdA==", + "dev": true, "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.6.tgz", + "integrity": "sha512-inXaTM1SVrIxCkIJ5gqWiozHfFMStuGbGJAxZFBoHcRRdDP0ySLb3jH6JOwmfiinPwyMZqMBX+7NBDCO4z0NSA==", + "dev": true, "dependencies": { - "safe-buffer": "5.2.1" + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.6.tgz", + "integrity": "sha512-n3Sf72TnqK4nw/jziSqEl1qaWPbCRw2CziHH+jdRYvw4J6yeCzsj4jdw8hIntOEeDGTmHVe2w4MVL44PN0GMzg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6" + }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.6.tgz", + "integrity": "sha512-sOajCu6V0P1KPljWHKiDq6ymgqB+vfo3isUS4McqW1DZtvSVU2v/wuMhmRmkg3sFoq6GMaUUf8W4WtoSLkOV/Q==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.6.tgz", + "integrity": "sha512-Uvgd9p2gUnzYJxVdBLcU0KurF8aVhkmVyMKW4MIY1/BByvs3EBpv45q01o7pRTVmTvtQq5zDlytP3dcUgm7v9w==", "dev": true, "dependencies": { - "object-assign": "^4", - "vary": "^1" + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { - "node": ">= 0.10" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/@babel/plugin-transform-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.6.tgz", + "integrity": "sha512-f2wHfR2HF6yMj+y+/y07+SLqnOSwRp8KYLpQKOzS58XLVlULhXbiYcygfXQxJlMbhII9+yXDwOUFLf60/TL5tw==", + "dev": true, "dependencies": { - "ms": "2.0.0" + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.6.tgz", + "integrity": "sha512-EKaWvnezBCMkRIHxMJSIIylzhqK09YpiJtDbr2wsXTwnO0TxyjMUkaw4RlFIZMIS0iDj0KyIg7H7XCguHu/YDA==", + "dev": true, "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { - "node": ">= 0.4" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.6.tgz", + "integrity": "sha512-9g8iV146szUo5GWgXpRbq/GALTnY+WnNuRTuRHWWFfWGbP9ukRL0aO/jpu9dmOPikclkxnNsjY8/gsWl6bmZJQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, "engines": { - "node": ">= 0.8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.6.tgz", + "integrity": "sha512-eAGogjZgcwqAxhyFgqghvoHRr+EYRQPFjUXrTYKBRb5qPnAVxOOglaxc4/byHqjvq/bqO2F3/CGwTHsgKJYHhQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.6.tgz", + "integrity": "sha512-JEV8l3MHdmmdb7S7Cmx6rbNEjRCgTQMZxllveHO0mx6uiclB0NflCawlQQ6+o5ZrwjUBYPzHm2XoK4wqGVUFuw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-simple-access": "^7.24.6" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.6.tgz", + "integrity": "sha512-xg1Z0J5JVYxtpX954XqaaAT6NpAY6LtZXvYFCJmGFJWwtlz2EmJoR8LycFRGNE8dBKizGWkGQZGegtkV8y8s+w==", "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.24.6", + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6" + }, "engines": { - "node": ">=0.3.1" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.6.tgz", + "integrity": "sha512-esRCC/KsSEUvrSjv5rFYnjZI6qv4R1e/iHQrqwbZIoRJqk7xCvEUiN7L1XrmW5QSmQe3n1XD88wbgDTWLbVSyg==", + "dev": true, "dependencies": { - "esutils": "^2.0.2" + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.6.tgz", + "integrity": "sha512-6DneiCiu91wm3YiNIGDWZsl6GfTTbspuj/toTEqLh9d4cx50UIzSdg+T96p8DuT7aJOBRhFyaE9ZvTHkXrXr6Q==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" }, - "funding": { - "url": "https://dotenvx.com" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.6.tgz", + "integrity": "sha512-f8liz9JG2Va8A4J5ZBuaSdwfPqN6axfWRK+y66fjKYbwf9VBLuq4WxtinhJhvp1w6lamKUwLG0slK2RxqFgvHA==", + "dev": true, "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "@babel/helper-plugin-utils": "^7.24.6" + }, "engines": { - "node": ">= 0.8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.6.tgz", + "integrity": "sha512-+QlAiZBMsBK5NqrBWFXCYeXyiU1y7BQ/OYaiPAcQJMomn5Tyg+r5WuVtyEuvTbpV7L25ZSLfE+2E9ywj4FD48A==", + "dev": true, "dependencies": { - "get-intrinsic": "^1.2.4" + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { - "node": ">= 0.4" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.6.tgz", + "integrity": "sha512-6voawq8T25Jvvnc4/rXcWZQKKxUNZcKMS8ZNrjxQqoRFernJJKjE3s18Qo6VFaatG5aiX5JV1oPD7DbJhn0a4Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, "engines": { - "node": ">= 0.4" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.6.tgz", + "integrity": "sha512-OKmi5wiMoRW5Smttne7BwHM8s/fb5JFs+bVGNSeHWzwZkWXWValR1M30jyXo1s/RaqgwwhEC62u4rFH/FBcBPg==", "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.6" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.6.tgz", + "integrity": "sha512-N/C76ihFKlZgKfdkEYKtaRUtXZAgK7sOY4h2qrbVbVTXPrKGIi8aww5WGe/+Wmg8onn8sr2ut6FXlsbu/j6JHg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-replace-supers": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.6.tgz", + "integrity": "sha512-L5pZ+b3O1mSzJ71HmxSCmTVd03VOT2GXOigug6vDYJzE5awLI7P1g0wFcdmGuwSDSrQ0L2rDOe/hHws8J1rv3w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.6.tgz", + "integrity": "sha512-cHbqF6l1QP11OkYTYQ+hhVx1E017O5ZcSPXk9oODpqhcAD1htsWG2NpHrrhthEO2qZomLK0FXS+u7NfrkF5aOQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.6.tgz", + "integrity": "sha512-ST7guE8vLV+vI70wmAxuZpIKzVjvFX9Qs8bl5w6tN/6gOypPWUmMQL2p7LJz5E63vEGrDhAiYetniJFyBH1RkA==", + "dev": true, "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" + "@babel/helper-plugin-utils": "^7.24.6" }, "engines": { - "node": ">= 0.10.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/express-session": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz", - "integrity": "sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ==", + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.6.tgz", + "integrity": "sha512-T9LtDI0BgwXOzyXrvgLTT8DFjCC/XgWLjflczTLXyvxbnSR/gpv0hbmzlHE/kmh9nOvlygbamLKRo6Op4yB6aw==", "dev": true, "dependencies": { - "cookie": "0.6.0", - "cookie-signature": "1.0.7", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-headers": "~1.0.2", - "parseurl": "~1.3.3", - "safe-buffer": "5.2.1", - "uid-safe": "~2.1.5" + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" }, "engines": { - "node": ">= 0.8.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/express-session/node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "dev": true + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.6.tgz", + "integrity": "sha512-Qu/ypFxCY5NkAnEhCF86Mvg3NSabKsh/TPpBVswEdkGl7+FbsYHy1ziRqJpwGH4thBdQHh8zx+z7vMYmcJ7iaQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.6.tgz", + "integrity": "sha512-oARaglxhRsN18OYsnPTpb8TcKQWDYNsPNmTnx5++WOAsUJ0cSC/FZVlIJCKvPbU4yn/UXsS0551CFKJhN0CaMw==", "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "@babel/helper-plugin-utils": "^7.24.6" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.6.tgz", + "integrity": "sha512-SMDxO95I8WXRtXhTAc8t/NFQUT7VYbIWwJCJgEli9ml4MhqUMh4S6hxgH6SmAC3eAQNWCDJFxcFeEt9w2sDdXg==", + "dev": true, "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" + "@babel/helper-plugin-utils": "^7.24.6", + "regenerator-transform": "^0.15.2" }, "engines": { - "node": ">= 0.8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.6.tgz", + "integrity": "sha512-DcrgFXRRlK64dGE0ZFBPD5egM2uM8mgfrvTMOSB2yKzOtjpGegVYkzh3s1zZg1bBck3nkXiaOamJUqK3Syk+4A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.6.tgz", + "integrity": "sha512-xnEUvHSMr9eOWS5Al2YPfc32ten7CXdH7Zwyyk7IqITg4nX61oHj+GxpNvl+y5JHjfN3KXE2IV55wAWowBYMVw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.6.tgz", + "integrity": "sha512-h/2j7oIUDjS+ULsIrNZ6/TKG97FgmEk1PXryk/HQq6op4XUUUwif2f69fJrzK0wza2zjCS1xhXmouACaWV5uPA==", + "dev": true, "dependencies": { - "minipass": "^3.0.0" + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6" }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.6.tgz", + "integrity": "sha512-fN8OcTLfGmYv7FnDrsjodYBo1DhPL3Pze/9mIIE2MGCT1KgADYIOD7rEglpLHZj8PZlC/JFX5WcD+85FLAQusw==", + "dev": true, "dependencies": { - "yallist": "^4.0.0" + "@babel/helper-plugin-utils": "^7.24.6" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.6.tgz", + "integrity": "sha512-BJbEqJIcKwrqUP+KfUIkxz3q8VzXe2R8Wv8TaNgO1cx+nNavxn/2+H8kp9tgFSOL6wYPPEgFvU6IKS4qoGqhmg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.6.tgz", + "integrity": "sha512-IshCXQ+G9JIFJI7bUpxTE/oA2lgVLAIK8q1KdJNoPXOpvRaNjMySGuvLfBw/Xi2/1lLo953uE8hyYSDW3TSYig==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.6.tgz", + "integrity": "sha512-H0i+hDLmaYYSt6KU9cZE0gb3Cbssa/oxWis7PX4ofQzbvsfix9Lbh8SRk7LCPDlLWJHUiFeHU0qRRpF/4Zv7mQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-typescript": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "deprecated": "This package is no longer supported.", + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.6.tgz", + "integrity": "sha512-bKl3xxcPbkQQo5eX9LjjDpU2xYHeEeNQbOhj0iPvetSzA+Tu9q/o5lujF4Sek60CM6MgYvOS/DJuwGbiEYAnLw==", + "dev": true, "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.6.tgz", + "integrity": "sha512-8EIgImzVUxy15cZiPii9GvLZwsy7Vxc+8meSlR3cXFmBIl5W5Tn9LGBf7CDKkHj4uVfNXCJB8RsVfnmY61iedA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.6.tgz", + "integrity": "sha512-pssN6ExsvxaKU638qcWb81RrvvgZom3jDgU/r5xFZ7TONkZGFf4MhI2ltMb8OcQWhHyxgIavEU+hgqtbKOmsPA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.6.tgz", + "integrity": "sha512-quiMsb28oXWIDK0gXLALOJRXLgICLiulqdZGOaPPd0vRT7fQp74NtdADAVu+D8s00C+0Xs0MxVP0VKF/sZEUgw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.6.tgz", + "integrity": "sha512-CrxEAvN7VxfjOG8JNF2Y/eMqMJbZPZ185amwGUBp8D9USK90xQmv7dLdFSa+VbD7fdIqcy/Mfv7WtzG8+/qxKg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.24.6", + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-validator-option": "^7.24.6", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.6", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.6", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.6", + "@babel/plugin-syntax-import-attributes": "^7.24.6", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.6", + "@babel/plugin-transform-async-generator-functions": "^7.24.6", + "@babel/plugin-transform-async-to-generator": "^7.24.6", + "@babel/plugin-transform-block-scoped-functions": "^7.24.6", + "@babel/plugin-transform-block-scoping": "^7.24.6", + "@babel/plugin-transform-class-properties": "^7.24.6", + "@babel/plugin-transform-class-static-block": "^7.24.6", + "@babel/plugin-transform-classes": "^7.24.6", + "@babel/plugin-transform-computed-properties": "^7.24.6", + "@babel/plugin-transform-destructuring": "^7.24.6", + "@babel/plugin-transform-dotall-regex": "^7.24.6", + "@babel/plugin-transform-duplicate-keys": "^7.24.6", + "@babel/plugin-transform-dynamic-import": "^7.24.6", + "@babel/plugin-transform-exponentiation-operator": "^7.24.6", + "@babel/plugin-transform-export-namespace-from": "^7.24.6", + "@babel/plugin-transform-for-of": "^7.24.6", + "@babel/plugin-transform-function-name": "^7.24.6", + "@babel/plugin-transform-json-strings": "^7.24.6", + "@babel/plugin-transform-literals": "^7.24.6", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.6", + "@babel/plugin-transform-member-expression-literals": "^7.24.6", + "@babel/plugin-transform-modules-amd": "^7.24.6", + "@babel/plugin-transform-modules-commonjs": "^7.24.6", + "@babel/plugin-transform-modules-systemjs": "^7.24.6", + "@babel/plugin-transform-modules-umd": "^7.24.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.6", + "@babel/plugin-transform-new-target": "^7.24.6", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.6", + "@babel/plugin-transform-numeric-separator": "^7.24.6", + "@babel/plugin-transform-object-rest-spread": "^7.24.6", + "@babel/plugin-transform-object-super": "^7.24.6", + "@babel/plugin-transform-optional-catch-binding": "^7.24.6", + "@babel/plugin-transform-optional-chaining": "^7.24.6", + "@babel/plugin-transform-parameters": "^7.24.6", + "@babel/plugin-transform-private-methods": "^7.24.6", + "@babel/plugin-transform-private-property-in-object": "^7.24.6", + "@babel/plugin-transform-property-literals": "^7.24.6", + "@babel/plugin-transform-regenerator": "^7.24.6", + "@babel/plugin-transform-reserved-words": "^7.24.6", + "@babel/plugin-transform-shorthand-properties": "^7.24.6", + "@babel/plugin-transform-spread": "^7.24.6", + "@babel/plugin-transform-sticky-regex": "^7.24.6", + "@babel/plugin-transform-template-literals": "^7.24.6", + "@babel/plugin-transform-typeof-symbol": "^7.24.6", + "@babel/plugin-transform-unicode-escapes": "^7.24.6", + "@babel/plugin-transform-unicode-property-regex": "^7.24.6", + "@babel/plugin-transform-unicode-regex": "^7.24.6", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.6", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.6.tgz", + "integrity": "sha512-U10aHPDnokCFRXgyT/MaIRTivUu2K/mu0vJlwRS9LxJmJet+PFQNKpggPyFCUtC6zWSBPjvxjnpNkAn3Uw2m5w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-validator-option": "^7.24.6", + "@babel/plugin-syntax-jsx": "^7.24.6", + "@babel/plugin-transform-modules-commonjs": "^7.24.6", + "@babel/plugin-transform-typescript": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "node_modules/@babel/runtime": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.6.tgz", + "integrity": "sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.6.tgz", + "integrity": "sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==", + "dependencies": { + "@babel/code-frame": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.6.tgz", + "integrity": "sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==", + "dependencies": { + "@babel/code-frame": "^7.24.6", + "@babel/generator": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-hoist-variables": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/types": "^7.24.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@babel/types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz", + "integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==", + "dependencies": { + "@babel/helper-string-parser": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "devOptional": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "devOptional": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@prisma/client": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.14.0.tgz", + "integrity": "sha512-akMSuyvLKeoU4LeyBAUdThP/uhVP3GuLygFE3MlYzaCb3/J8SfsYBE5PkaFuLuVpLyA6sFoW+16z/aPhNAESqg==", + "hasInstallScript": true, + "engines": { + "node": ">=16.13" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/debug": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.14.0.tgz", + "integrity": "sha512-iq56qBZuFfX3fCxoxT8gBX33lQzomBU0qIUaEj1RebsKVz1ob/BVH1XSBwwwvRVtZEV1b7Fxx2eVu34Ge/mg3w==" + }, + "node_modules/@prisma/engines": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.14.0.tgz", + "integrity": "sha512-lgxkKZ6IEygVcw6IZZUlPIfLQ9hjSYAtHjZ5r64sCLDgVzsPFCi2XBBJgzPMkOQ5RHzUD4E/dVdpn9+ez8tk1A==", + "hasInstallScript": true, + "dependencies": { + "@prisma/debug": "5.14.0", + "@prisma/engines-version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", + "@prisma/fetch-engine": "5.14.0", + "@prisma/get-platform": "5.14.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48.tgz", + "integrity": "sha512-ip6pNkRo1UxWv+6toxNcYvItNYaqQjXdFNGJ+Nuk2eYtRoEdoF13wxo7/jsClJFFenMPVNVqXQDV0oveXnR1cA==" + }, + "node_modules/@prisma/fetch-engine": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.14.0.tgz", + "integrity": "sha512-VrheA9y9DMURK5vu8OJoOgQpxOhas3qF0IBHJ8G/0X44k82kc8E0w98HCn2nhnbOOMwbWsJWXfLC2/F8n5u0gQ==", + "dependencies": { + "@prisma/debug": "5.14.0", + "@prisma/engines-version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", + "@prisma/get-platform": "5.14.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.14.0.tgz", + "integrity": "sha512-/yAyBvcEjRv41ynZrhdrPtHgk47xLRRq/o5eWGcUpBJ1YrUZTYB8EoPiopnP7iQrMATK8stXQdPOoVlrzuTQZw==", + "dependencies": { + "@prisma/debug": "5.14.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "devOptional": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "devOptional": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "devOptional": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "devOptional": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/bcrypt": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", + "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.2.tgz", + "integrity": "sha512-dPSEQElyVJ97BuGduAqQjpBocZWAs0GR94z+ptL7JXQJeJdHw2WBG3EWdFrK36b8Q6j8P4cXOMhgUoi0IIfIsg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express-session": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.18.0.tgz", + "integrity": "sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/is-email": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/is-email/-/is-email-1.0.0.tgz", + "integrity": "sha512-b/76ooKpYY/b+oPrOuc/pmM5eag+ZlzctPsKcRCIKs+TFzh0FL58OeXtSPkbXt3uKNK84YCKHmjnoREtwve5Kg==", + "dev": true + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", + "integrity": "sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/morgan": { + "version": "1.9.9", + "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.9.tgz", + "integrity": "sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/multer": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.11.tgz", + "integrity": "sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/node": { + "version": "20.12.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.13.tgz", + "integrity": "sha512-gBGeanV41c1L171rR7wjbMiEpEI/l5XFQdLLfhr/REwpgDy/4U8y89+i8kRiLzDyZdOkXh+cRaTetUnCYutoXA==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/oauth": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.5.tgz", + "integrity": "sha512-+oQ3C2Zx6ambINOcdIARF5Z3Tu3x//HipE889/fqo3sgpQZbe9c6ExdQFtN6qlhpR7p83lTZfPJt0tCAW29dog==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/passport": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.16.tgz", + "integrity": "sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-google-oauth20": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.16.tgz", + "integrity": "sha512-ayXK2CJ7uVieqhYOc6k/pIr5pcQxOLB6kBev+QUGS7oEZeTgIs1odDobXRqgfBPvXzl0wXCQHftV5220czZCPA==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-oauth2": "*" + } + }, + "node_modules/@types/passport-oauth2": { + "version": "1.4.17", + "resolved": "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.4.17.tgz", + "integrity": "sha512-ODiAHvso6JcWJ6ZkHHroVp05EHGhqQN533PtFNBkg8Fy5mERDqsr030AX81M0D69ZcaMvhF92SRckEk2B0HYYg==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/oauth": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" + }, + "node_modules/@types/swagger-jsdoc": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz", + "integrity": "sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ==", + "dev": true + }, + "node_modules/@types/swagger-ui-express": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz", + "integrity": "sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "devOptional": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "devOptional": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "devOptional": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001625", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001625.tgz", + "integrity": "sha512-4KE9N2gcRH+HQhpeiRZXd+1niLB/XNLAhSy4z7fI8EzcbcPoAqjNInxVHTiTwWfTIV4w096XG8OtCOCQQKPv3w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/core-js-compat": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "devOptional": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "devOptional": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.787", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.787.tgz", + "integrity": "sha512-d0EFmtLPjctczO3LogReyM2pbBiiZbnsKnGF+cdZhsYzHm/A0GV7W94kqzLD8SN4O3f3iHlgLUChqghgyznvCQ==" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-session": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz", + "integrity": "sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ==", + "dev": true, + "dependencies": { + "cookie": "0.6.0", + "cookie-signature": "1.0.7", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-email": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-email/-/is-email-1.0.2.tgz", + "integrity": "sha512-UojUgD2EhDTBQ2SGKwrK9edce5phRzgLsP+V5+Uu2Swi+uvjVXgH3zduM3HhT9iaC/9Kq19/TYUbP0jPoi6ioA==" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-uuid": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-uuid/-/is-uuid-1.0.2.tgz", + "integrity": "sha512-tCByphFcJgf2qmiMo5hMCgNAquNSagOetVetDvBXswGkNfoyEMvGH1yDlF8cbZbKnbVBr4Y5/rlpMz9umxyBkQ==" + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/get-tsconfig": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", - "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", - "dev": true, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dependencies": { - "resolve-pkg-maps": "^1.0.0" + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "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" + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dependencies": { - "is-glob": "^4.0.1" + "detect-newline": "^3.0.0" }, "engines": { - "node": ">= 6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dependencies": { - "get-intrinsic": "^1.1.3" + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "engines": { - "node": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dependencies": { - "es-define-property": "^1.0.0" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dependencies": { - "function-bind": "^1.1.2" + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">= 0.8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dependencies": { - "agent-base": "6", - "debug": "4" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">= 6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/jest-mock-extended": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/jest-mock-extended/-/jest-mock-extended-3.0.7.tgz", + "integrity": "sha512-7lsKdLFcW9B9l5NzZ66S/yTQ9k8rFtnwYdCNuRU/81fqDWicNDVhitTSPnrGmNeNm0xyw0JHexEOShrIKRCIRQ==", "dependencies": { - "ms": "2.1.2" + "ts-essentials": "^10.0.0" }, + "peerDependencies": { + "jest": "^24.0.0 || ^25.0.0 || ^26.0.0 || ^27.0.0 || ^28.0.0 || ^29.0.0", + "typescript": "^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "engines": { - "node": ">=6.0" + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" }, "peerDependenciesMeta": { - "supports-color": { + "jest-resolve": { "optional": true } } }, - "node_modules/https-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, "engines": { - "node": ">= 0.10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dependencies": { - "binary-extensions": "^2.0.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-email": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-email/-/is-email-1.0.2.tgz", - "integrity": "sha512-UojUgD2EhDTBQ2SGKwrK9edce5phRzgLsP+V5+Uu2Swi+uvjVXgH3zduM3HhT9iaC/9Kq19/TYUbP0jPoi6ioA==" + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dependencies": { - "is-extglob": "^2.1.1" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "engines": { - "node": ">=0.12.0" + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/is-uuid": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-uuid/-/is-uuid-1.0.2.tgz", - "integrity": "sha512-tCByphFcJgf2qmiMo5hMCgNAquNSagOetVetDvBXswGkNfoyEMvGH1yDlF8cbZbKnbVBr4Y5/rlpMz9umxyBkQ==" - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "4.1.0", @@ -1899,6 +5647,33 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/jsonwebtoken": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", @@ -1944,6 +5719,44 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, "node_modules/lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", @@ -1984,6 +5797,12 @@ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, "node_modules/lodash.mergewith": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", @@ -1994,6 +5813,19 @@ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lru-cache/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -2020,7 +5852,15 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "devOptional": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dependencies": { + "tmpl": "1.0.5" + } }, "node_modules/media-typer": { "version": "0.3.0", @@ -2035,6 +5875,11 @@ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -2043,6 +5888,18 @@ "node": ">= 0.6" } }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -2073,6 +5930,14 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2203,6 +6068,11 @@ "node": ">= 6.0.0" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -2235,6 +6105,48 @@ } } }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + }, + "node_modules/node-mocks-http": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.14.1.tgz", + "integrity": "sha512-mfXuCGonz0A7uG1FEjnypjm34xegeN5+HI6xeGhYKecfgaZhjsmYoLE9LEFmT+53G1n8IuagPZmVnEL/xNsFaA==", + "dev": true, + "dependencies": { + "@types/express": "^4.17.21", + "@types/node": "^20.10.6", + "accepts": "^1.3.7", + "content-disposition": "^0.5.3", + "depd": "^1.1.0", + "fresh": "^0.5.2", + "merge-descriptors": "^1.0.1", + "methods": "^1.1.2", + "mime": "^1.3.4", + "parseurl": "^1.3.3", + "range-parser": "^1.2.0", + "type-is": "^1.6.18" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/node-mocks-http/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, "node_modules/nodemon": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.2.tgz", @@ -2304,11 +6216,21 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", @@ -2370,12 +6292,90 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/openapi-types": { "version": "12.1.3", "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", "peer": true }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -2439,6 +6439,14 @@ "node": ">= 0.4.0" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -2447,6 +6455,19 @@ "node": ">=0.10.0" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -2457,11 +6478,15 @@ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -2469,6 +6494,49 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/prisma": { "version": "5.14.0", "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.14.0.tgz", @@ -2489,6 +6557,18 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -2507,6 +6587,21 @@ "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", "dev": true }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, "node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -2552,6 +6647,11 @@ "node": ">= 0.8" } }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, "node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -2566,21 +6666,135 @@ "util-deprecate": "~1.0.1" } }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dependencies": { - "picomatch": "^2.2.1" + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=8.10.0" + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "engines": { + "node": ">=8" } }, "node_modules/resolve-pkg-maps": { @@ -2592,6 +6806,14 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "engines": { + "node": ">=10" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -2710,6 +6932,25 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -2744,6 +6985,52 @@ "node": ">=10" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -2773,6 +7060,18 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -2797,6 +7096,33 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/superstruct": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", @@ -2809,7 +7135,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -2817,6 +7142,17 @@ "node": ">=4" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/swagger-jsdoc": { "version": "6.2.8", "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", @@ -2913,11 +7249,36 @@ "node": ">=10" } }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -2947,11 +7308,71 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "node_modules/ts-essentials": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-10.0.0.tgz", + "integrity": "sha512-77FHNJEyysF9+1s4G6eejuA1lxw7uMchT3ZPy3CIbh7GIunffpshtM8pTe5G6N5dpOzNevqRHew859ceLWVBfw==", + "peerDependencies": { + "typescript": ">=4.5.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ts-jest": { + "version": "29.1.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.4.tgz", + "integrity": "sha512-YiHwDhSvCiItoAgsKtoLFCuakDzDsJ1DLDnSouTaTmdOcOwIkSzbLXduaQ6M5DRVhuZC/NYaaZ/mtHbWMv/S6Q==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, + "devOptional": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -3009,6 +7430,25 @@ "fsevents": "~2.3.3" } }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -3030,7 +7470,6 @@ "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3065,8 +7504,47 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } }, "node_modules/unpipe": { "version": "1.0.0", @@ -3076,6 +7554,35 @@ "node": ">= 0.8" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -3093,7 +7600,29 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "devOptional": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } }, "node_modules/validator": { "version": "13.12.0", @@ -3111,6 +7640,14 @@ "node": ">= 0.8" } }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dependencies": { + "makeerror": "1.0.12" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -3125,6 +7662,20 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -3133,11 +7684,39 @@ "string-width": "^1.0.2 || 2 || 3 || 4" } }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -3146,6 +7725,14 @@ "node": ">=0.4" } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -3159,15 +7746,51 @@ "node": ">= 6" } }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6" } }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/z-schema": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", diff --git a/package.json b/package.json index 62588df..86adb09 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "express": "^4.18.2", "is-email": "^1.0.2", "is-uuid": "^1.0.2", + "jest-mock-extended": "^3.0.7", "jsonwebtoken": "^9.0.2", "moment-timezone": "^0.5.45", "multer": "^1.4.5-lts.1", @@ -17,6 +18,9 @@ "swagger-ui-express": "^5.0.0" }, "devDependencies": { + "@babel/preset-env": "^7.24.6", + "@babel/preset-typescript": "^7.24.6", + "@jest/globals": "^29.7.0", "@types/bcrypt": "^5.0.2", "@types/cors": "^2.8.17", "@types/express": "^4.17.21", @@ -30,10 +34,14 @@ "@types/passport-google-oauth20": "^2.0.16", "@types/swagger-jsdoc": "^6.0.4", "@types/swagger-ui-express": "^4.1.6", + "babel-jest": "^29.7.0", "cors": "^2.8.5", "express-session": "^1.18.0", + "jest": "^29.7.0", "morgan": "^1.10.0", + "node-mocks-http": "^1.14.1", "nodemon": "^3.1.2", + "ts-jest": "^29.1.4", "ts-node": "^10.9.2", "tsx": "^4.11.0", "typescript": "^5.4.5" @@ -41,7 +49,8 @@ "type": "module", "scripts": { "start": "tsx --loader ts-node/esm src/app.ts", - "dev": "nodemon" + "dev": "nodemon", + "test": "jest" }, "prisma": { "seed": "tsx prisma/seed.ts" diff --git a/src/client.ts b/src/client.ts new file mode 100644 index 0000000..63f8bbd --- /dev/null +++ b/src/client.ts @@ -0,0 +1,4 @@ +import { PrismaClient } from "@prisma/client"; + +const prisma = new PrismaClient(); +export default prisma; diff --git a/src/context.ts b/src/context.ts new file mode 100644 index 0000000..7b9530b --- /dev/null +++ b/src/context.ts @@ -0,0 +1,16 @@ +import { PrismaClient } from "@prisma/client"; +import { DeepMockProxy, mockDeep } from "jest-mock-extended"; + +export type Context = { + prisma: PrismaClient; +}; + +export type MockContext = { + prisma: DeepMockProxy; +}; + +export const createMockContext = (): MockContext => { + return { + prisma: mockDeep(), + }; +}; diff --git a/src/services/authService.ts b/src/services/authService.ts index c55fbd3..22dac30 100644 --- a/src/services/authService.ts +++ b/src/services/authService.ts @@ -18,7 +18,7 @@ export const createUser = async (email: string, password: string, name: string, if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002") { throw new Error("이미 존재하는 이메일입니다."); } - throw error; // 다른 에러는 그대로 던집니다. + throw error; } }; diff --git a/src/services/productService.ts b/src/services/productService.ts index 6ec3157..5664de3 100644 --- a/src/services/productService.ts +++ b/src/services/productService.ts @@ -1,8 +1,7 @@ -import { Prisma, PrismaClient, Product } from "@prisma/client"; +import { Prisma, Product } from "@prisma/client"; +import prisma from "../client"; import AppError from "../utils/errors"; -const prisma = new PrismaClient(); - export const getProducts = async ({ offset, limit, diff --git a/src/singleton.ts b/src/singleton.ts new file mode 100644 index 0000000..f4a8790 --- /dev/null +++ b/src/singleton.ts @@ -0,0 +1,15 @@ +import { beforeEach, jest } from "@jest/globals"; +import { PrismaClient } from "@prisma/client"; +import { DeepMockProxy, mockDeep, mockReset } from "jest-mock-extended"; +import prisma from "./client"; + +jest.mock("./client", () => ({ + __esModule: true, + default: mockDeep(), +})); + +beforeEach(() => { + mockReset(prismaMock); +}); + +export const prismaMock = prisma as unknown as DeepMockProxy; diff --git a/src/test/product.test.ts b/src/test/product.test.ts new file mode 100644 index 0000000..c10a7c8 --- /dev/null +++ b/src/test/product.test.ts @@ -0,0 +1,78 @@ +import { describe, expect, jest, test } from "@jest/globals"; +import prisma from "../client"; +import { createProduct } from "../services/productService"; + +jest.mock("../client", () => ({ + __esModule: true, + default: { + user: { + findUnique: jest.fn(), + }, + product: { + create: jest.fn(), + }, + }, +})); + +describe("중고마켓", () => { + test("새 상품을 등록한다", async () => { + const userId = 1; + const productData = { + name: "판다인형 테스트", + description: "테스트용 판다인형입니다.", + price: 20000, + }; + const imageUrl = "image1.jpg"; + + const mockUser = { + id: 1, + googleId: null, + email: "test@example.com", + name: "테스트", + nickname: "테스트의왕", + image: null, + password: null, + createdAt: new Date(), + updatedAt: new Date(), + }; + + const mockProduct = { + id: "test-product-id", + ...productData, + writer: mockUser.name, + userId: userId, + tags: [], + favoriteCount: 0, + createdAt: new Date(), + updatedAt: new Date(), + images: [{ imagePath: imageUrl }], + }; + + (prisma.user.findUnique as jest.MockedFunction).mockResolvedValue(mockUser); + (prisma.product.create as jest.MockedFunction).mockResolvedValue(mockProduct); + + const result = await createProduct(userId, productData, imageUrl); + + expect(result).toEqual(mockProduct); + + expect(prisma.user.findUnique).toHaveBeenCalledWith({ + where: { id: userId }, + select: { name: true }, + }); + expect(prisma.product.create).toHaveBeenCalledWith({ + data: { + ...productData, + writer: mockUser.name, + user: { + connect: { id: userId }, + }, + images: { + create: [{ imagePath: imageUrl }], + }, + }, + include: { + images: true, + }, + }); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index d278dee..8bdcf5e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,6 +15,7 @@ "ts-node": { "esm": true }, + "strictNullChecks": true, "include": ["src/**/*.ts"], "exclude": ["node_modules"] diff --git a/yarn.lock b/yarn.lock index 7693cba..be9055a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,14 @@ # yarn lockfile v1 +"@ampproject/remapping@^2.2.0": + version "2.3.0" + resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + "@apidevtools/json-schema-ref-parser@^9.0.6": version "9.1.2" resolved "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz" @@ -34,6 +42,993 @@ call-me-maybe "^1.0.1" z-schema "^5.0.1" +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz" + integrity sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA== + dependencies: + "@babel/highlight" "^7.24.6" + picocolors "^1.0.0" + +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.6.tgz" + integrity sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ== + +"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.11.6", "@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.13.0", "@babel/core@^7.23.9", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.8.0", "@babel/core@>=7.0.0-beta.0 <8": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.24.6.tgz" + integrity sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.24.6" + "@babel/generator" "^7.24.6" + "@babel/helper-compilation-targets" "^7.24.6" + "@babel/helper-module-transforms" "^7.24.6" + "@babel/helpers" "^7.24.6" + "@babel/parser" "^7.24.6" + "@babel/template" "^7.24.6" + "@babel/traverse" "^7.24.6" + "@babel/types" "^7.24.6" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.24.6", "@babel/generator@^7.7.2": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.24.6.tgz" + integrity sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg== + dependencies: + "@babel/types" "^7.24.6" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz" + integrity sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg== + dependencies: + "@babel/types" "^7.24.6" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.6.tgz" + integrity sha512-+wnfqc5uHiMYtvRX7qu80Toef8BXeh4HHR1SPeonGb1SKPniNEd4a/nlaJJMv/OIEYvIVavvo0yR7u10Gqz0Iw== + dependencies: + "@babel/types" "^7.24.6" + +"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz" + integrity sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg== + dependencies: + "@babel/compat-data" "^7.24.6" + "@babel/helper-validator-option" "^7.24.6" + browserslist "^4.22.2" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.6.tgz" + integrity sha512-djsosdPJVZE6Vsw3kk7IPRWethP94WHGOhQTc67SNXE0ZzMhHgALw8iGmYS0TD1bbMM0VDROy43od7/hN6WYcA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.6" + "@babel/helper-environment-visitor" "^7.24.6" + "@babel/helper-function-name" "^7.24.6" + "@babel/helper-member-expression-to-functions" "^7.24.6" + "@babel/helper-optimise-call-expression" "^7.24.6" + "@babel/helper-replace-supers" "^7.24.6" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" + "@babel/helper-split-export-declaration" "^7.24.6" + semver "^6.3.1" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.6.tgz" + integrity sha512-C875lFBIWWwyv6MHZUG9HmRrlTDgOsLWZfYR0nW69gaKJNe0/Mpxx5r0EID2ZdHQkdUmQo2t0uNckTL08/1BgA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.6" + regexpu-core "^5.3.1" + semver "^6.3.1" + +"@babel/helper-define-polyfill-provider@^0.6.1", "@babel/helper-define-polyfill-provider@^0.6.2": + version "0.6.2" + resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz" + integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== + dependencies: + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + +"@babel/helper-environment-visitor@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz" + integrity sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g== + +"@babel/helper-function-name@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz" + integrity sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w== + dependencies: + "@babel/template" "^7.24.6" + "@babel/types" "^7.24.6" + +"@babel/helper-hoist-variables@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz" + integrity sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA== + dependencies: + "@babel/types" "^7.24.6" + +"@babel/helper-member-expression-to-functions@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.6.tgz" + integrity sha512-OTsCufZTxDUsv2/eDXanw/mUZHWOxSbEmC3pP8cgjcy5rgeVPWWMStnv274DV60JtHxTk0adT0QrCzC4M9NWGg== + dependencies: + "@babel/types" "^7.24.6" + +"@babel/helper-module-imports@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz" + integrity sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g== + dependencies: + "@babel/types" "^7.24.6" + +"@babel/helper-module-transforms@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz" + integrity sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA== + dependencies: + "@babel/helper-environment-visitor" "^7.24.6" + "@babel/helper-module-imports" "^7.24.6" + "@babel/helper-simple-access" "^7.24.6" + "@babel/helper-split-export-declaration" "^7.24.6" + "@babel/helper-validator-identifier" "^7.24.6" + +"@babel/helper-optimise-call-expression@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.6.tgz" + integrity sha512-3SFDJRbx7KuPRl8XDUr8O7GAEB8iGyWPjLKJh/ywP/Iy9WOmEfMrsWbaZpvBu2HSYn4KQygIsz0O7m8y10ncMA== + dependencies: + "@babel/types" "^7.24.6" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.6", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.6.tgz" + integrity sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg== + +"@babel/helper-remap-async-to-generator@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.6.tgz" + integrity sha512-1Qursq9ArRZPAMOZf/nuzVW8HgJLkTB9y9LfP4lW2MVp4e9WkLJDovfKBxoDcCk6VuzIxyqWHyBoaCtSRP10yg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.6" + "@babel/helper-environment-visitor" "^7.24.6" + "@babel/helper-wrap-function" "^7.24.6" + +"@babel/helper-replace-supers@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.6.tgz" + integrity sha512-mRhfPwDqDpba8o1F8ESxsEkJMQkUF8ZIWrAc0FtWhxnjfextxMWxr22RtFizxxSYLjVHDeMgVsRq8BBZR2ikJQ== + dependencies: + "@babel/helper-environment-visitor" "^7.24.6" + "@babel/helper-member-expression-to-functions" "^7.24.6" + "@babel/helper-optimise-call-expression" "^7.24.6" + +"@babel/helper-simple-access@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz" + integrity sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g== + dependencies: + "@babel/types" "^7.24.6" + +"@babel/helper-skip-transparent-expression-wrappers@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.6.tgz" + integrity sha512-jhbbkK3IUKc4T43WadP96a27oYti9gEf1LdyGSP2rHGH77kwLwfhO7TgwnWvxxQVmke0ImmCSS47vcuxEMGD3Q== + dependencies: + "@babel/types" "^7.24.6" + +"@babel/helper-split-export-declaration@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz" + integrity sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw== + dependencies: + "@babel/types" "^7.24.6" + +"@babel/helper-string-parser@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz" + integrity sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q== + +"@babel/helper-validator-identifier@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz" + integrity sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw== + +"@babel/helper-validator-option@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz" + integrity sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ== + +"@babel/helper-wrap-function@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.6.tgz" + integrity sha512-f1JLrlw/jbiNfxvdrfBgio/gRBk3yTAEJWirpAkiJG2Hb22E7cEYKHWo0dFPTv/niPovzIdPdEDetrv6tC6gPQ== + dependencies: + "@babel/helper-function-name" "^7.24.6" + "@babel/template" "^7.24.6" + "@babel/types" "^7.24.6" + +"@babel/helpers@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.6.tgz" + integrity sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA== + dependencies: + "@babel/template" "^7.24.6" + "@babel/types" "^7.24.6" + +"@babel/highlight@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz" + integrity sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ== + dependencies: + "@babel/helper-validator-identifier" "^7.24.6" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz" + integrity sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q== + +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.6.tgz" + integrity sha512-bYndrJ6Ph6Ar+GaB5VAc0JPoP80bQCm4qon6JEzXfRl5QZyQ8Ur1K6k7htxWmPA5z+k7JQvaMUrtXlqclWYzKw== + dependencies: + "@babel/helper-environment-visitor" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.6.tgz" + integrity sha512-iVuhb6poq5ikqRq2XWU6OQ+R5o9wF+r/or9CeUyovgptz0UlnK4/seOQ1Istu/XybYjAhQv1FRSSfHHufIku5Q== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.6.tgz" + integrity sha512-c8TER5xMDYzzFcGqOEp9l4hvB7dcbhcGjcLVwxWfe4P5DOafdwjsBJZKsmv+o3aXh7NhopvayQIovHrh2zSRUQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" + "@babel/plugin-transform-optional-chaining" "^7.24.6" + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.6.tgz" + integrity sha512-z8zEjYmwBUHN/pCF3NuWBhHQjJCrd33qAi8MgANfMrAvn72k2cImT8VjK9LJFu4ysOLJqhfkYYb3MvwANRUNZQ== + dependencies: + "@babel/helper-environment-visitor" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-import-assertions@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.6.tgz" + integrity sha512-BE6o2BogJKJImTmGpkmOic4V0hlRRxVtzqxiSPa8TIFxyhi4EFjHm08nq1M4STK4RytuLMgnSz0/wfflvGFNOg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-syntax-import-attributes@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.6.tgz" + integrity sha512-D+CfsVZousPXIdudSII7RGy52+dYRtbyKAZcvtQKq/NpsivyMVduepzcLqG5pMBugtMdedxdC8Ramdpcne9ZWQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-syntax-import-meta@^7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.24.6", "@babel/plugin-syntax-jsx@^7.7.2": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.6.tgz" + integrity sha512-lWfvAIFNWMlCsU0DRUun2GpFwZdGTukLaHJqRh1JRb80NdAP5Sb1HDHB5X9P9OtgZHQl089UzQkpYlBq2VTPRw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.24.6", "@babel/plugin-syntax-typescript@^7.7.2": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.6.tgz" + integrity sha512-TzCtxGgVTEJWWwcYwQhCIQ6WaKlo80/B+Onsk4RRCcYqpYGFcG9etPW94VToGte5AAcxRrhjPUFvUS3Y2qKi4A== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-arrow-functions@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.6.tgz" + integrity sha512-jSSSDt4ZidNMggcLx8SaKsbGNEfIl0PHx/4mFEulorE7bpYLbN0d3pDW3eJ7Y5Z3yPhy3L3NaPCYyTUY7TuugQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-async-generator-functions@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.6.tgz" + integrity sha512-VEP2o4iR2DqQU6KPgizTW2mnMx6BG5b5O9iQdrW9HesLkv8GIA8x2daXBQxw1MrsIkFQGA/iJ204CKoQ8UcnAA== + dependencies: + "@babel/helper-environment-visitor" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-remap-async-to-generator" "^7.24.6" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-transform-async-to-generator@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.6.tgz" + integrity sha512-NTBA2SioI3OsHeIn6sQmhvXleSl9T70YY/hostQLveWs0ic+qvbA3fa0kwAwQ0OA/XGaAerNZRQGJyRfhbJK4g== + dependencies: + "@babel/helper-module-imports" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-remap-async-to-generator" "^7.24.6" + +"@babel/plugin-transform-block-scoped-functions@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.6.tgz" + integrity sha512-XNW7jolYHW9CwORrZgA/97tL/k05qe/HL0z/qqJq1mdWhwwCM6D4BJBV7wAz9HgFziN5dTOG31znkVIzwxv+vw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-block-scoping@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.6.tgz" + integrity sha512-S/t1Xh4ehW7sGA7c1j/hiOBLnEYCp/c2sEG4ZkL8kI1xX9tW2pqJTCHKtdhe/jHKt8nG0pFCrDHUXd4DvjHS9w== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-class-properties@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.6.tgz" + integrity sha512-j6dZ0Z2Z2slWLR3kt9aOmSIrBvnntWjMDN/TVcMPxhXMLmJVqX605CBRlcGI4b32GMbfifTEsdEjGjiE+j/c3A== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-class-static-block@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.6.tgz" + integrity sha512-1QSRfoPI9RoLRa8Mnakc6v3e0gJxiZQTYrMfLn+mD0sz5+ndSzwymp2hDcYJTyT0MOn0yuWzj8phlIvO72gTHA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-transform-classes@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.6.tgz" + integrity sha512-+fN+NO2gh8JtRmDSOB6gaCVo36ha8kfCW1nMq2Gc0DABln0VcHN4PrALDvF5/diLzIRKptC7z/d7Lp64zk92Fg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.6" + "@babel/helper-compilation-targets" "^7.24.6" + "@babel/helper-environment-visitor" "^7.24.6" + "@babel/helper-function-name" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-replace-supers" "^7.24.6" + "@babel/helper-split-export-declaration" "^7.24.6" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.6.tgz" + integrity sha512-cRzPobcfRP0ZtuIEkA8QzghoUpSB3X3qSH5W2+FzG+VjWbJXExtx0nbRqwumdBN1x/ot2SlTNQLfBCnPdzp6kg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/template" "^7.24.6" + +"@babel/plugin-transform-destructuring@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.6.tgz" + integrity sha512-YLW6AE5LQpk5npNXL7i/O+U9CE4XsBCuRPgyjl1EICZYKmcitV+ayuuUGMJm2lC1WWjXYszeTnIxF/dq/GhIZQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-dotall-regex@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.6.tgz" + integrity sha512-rCXPnSEKvkm/EjzOtLoGvKseK+dS4kZwx1HexO3BtRtgL0fQ34awHn34aeSHuXtZY2F8a1X8xqBBPRtOxDVmcA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-duplicate-keys@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.6.tgz" + integrity sha512-/8Odwp/aVkZwPFJMllSbawhDAO3UJi65foB00HYnK/uXvvCPm0TAXSByjz1mpRmp0q6oX2SIxpkUOpPFHk7FLA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-dynamic-import@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.6.tgz" + integrity sha512-vpq8SSLRTBLOHUZHSnBqVo0AKX3PBaoPs2vVzYVWslXDTDIpwAcCDtfhUcHSQQoYoUvcFPTdC8TZYXu9ZnLT/w== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-transform-exponentiation-operator@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.6.tgz" + integrity sha512-EemYpHtmz0lHE7hxxxYEuTYOOBZ43WkDgZ4arQ4r+VX9QHuNZC+WH3wUWmRNvR8ECpTRne29aZV6XO22qpOtdA== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-export-namespace-from@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.6.tgz" + integrity sha512-inXaTM1SVrIxCkIJ5gqWiozHfFMStuGbGJAxZFBoHcRRdDP0ySLb3jH6JOwmfiinPwyMZqMBX+7NBDCO4z0NSA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-transform-for-of@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.6.tgz" + integrity sha512-n3Sf72TnqK4nw/jziSqEl1qaWPbCRw2CziHH+jdRYvw4J6yeCzsj4jdw8hIntOEeDGTmHVe2w4MVL44PN0GMzg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" + +"@babel/plugin-transform-function-name@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.6.tgz" + integrity sha512-sOajCu6V0P1KPljWHKiDq6ymgqB+vfo3isUS4McqW1DZtvSVU2v/wuMhmRmkg3sFoq6GMaUUf8W4WtoSLkOV/Q== + dependencies: + "@babel/helper-compilation-targets" "^7.24.6" + "@babel/helper-function-name" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-json-strings@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.6.tgz" + integrity sha512-Uvgd9p2gUnzYJxVdBLcU0KurF8aVhkmVyMKW4MIY1/BByvs3EBpv45q01o7pRTVmTvtQq5zDlytP3dcUgm7v9w== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-transform-literals@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.6.tgz" + integrity sha512-f2wHfR2HF6yMj+y+/y07+SLqnOSwRp8KYLpQKOzS58XLVlULhXbiYcygfXQxJlMbhII9+yXDwOUFLf60/TL5tw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-logical-assignment-operators@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.6.tgz" + integrity sha512-EKaWvnezBCMkRIHxMJSIIylzhqK09YpiJtDbr2wsXTwnO0TxyjMUkaw4RlFIZMIS0iDj0KyIg7H7XCguHu/YDA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-transform-member-expression-literals@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.6.tgz" + integrity sha512-9g8iV146szUo5GWgXpRbq/GALTnY+WnNuRTuRHWWFfWGbP9ukRL0aO/jpu9dmOPikclkxnNsjY8/gsWl6bmZJQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-modules-amd@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.6.tgz" + integrity sha512-eAGogjZgcwqAxhyFgqghvoHRr+EYRQPFjUXrTYKBRb5qPnAVxOOglaxc4/byHqjvq/bqO2F3/CGwTHsgKJYHhQ== + dependencies: + "@babel/helper-module-transforms" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-modules-commonjs@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.6.tgz" + integrity sha512-JEV8l3MHdmmdb7S7Cmx6rbNEjRCgTQMZxllveHO0mx6uiclB0NflCawlQQ6+o5ZrwjUBYPzHm2XoK4wqGVUFuw== + dependencies: + "@babel/helper-module-transforms" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-simple-access" "^7.24.6" + +"@babel/plugin-transform-modules-systemjs@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.6.tgz" + integrity sha512-xg1Z0J5JVYxtpX954XqaaAT6NpAY6LtZXvYFCJmGFJWwtlz2EmJoR8LycFRGNE8dBKizGWkGQZGegtkV8y8s+w== + dependencies: + "@babel/helper-hoist-variables" "^7.24.6" + "@babel/helper-module-transforms" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-validator-identifier" "^7.24.6" + +"@babel/plugin-transform-modules-umd@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.6.tgz" + integrity sha512-esRCC/KsSEUvrSjv5rFYnjZI6qv4R1e/iHQrqwbZIoRJqk7xCvEUiN7L1XrmW5QSmQe3n1XD88wbgDTWLbVSyg== + dependencies: + "@babel/helper-module-transforms" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.6.tgz" + integrity sha512-6DneiCiu91wm3YiNIGDWZsl6GfTTbspuj/toTEqLh9d4cx50UIzSdg+T96p8DuT7aJOBRhFyaE9ZvTHkXrXr6Q== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-new-target@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.6.tgz" + integrity sha512-f8liz9JG2Va8A4J5ZBuaSdwfPqN6axfWRK+y66fjKYbwf9VBLuq4WxtinhJhvp1w6lamKUwLG0slK2RxqFgvHA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.6.tgz" + integrity sha512-+QlAiZBMsBK5NqrBWFXCYeXyiU1y7BQ/OYaiPAcQJMomn5Tyg+r5WuVtyEuvTbpV7L25ZSLfE+2E9ywj4FD48A== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-transform-numeric-separator@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.6.tgz" + integrity sha512-6voawq8T25Jvvnc4/rXcWZQKKxUNZcKMS8ZNrjxQqoRFernJJKjE3s18Qo6VFaatG5aiX5JV1oPD7DbJhn0a4Q== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-transform-object-rest-spread@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.6.tgz" + integrity sha512-OKmi5wiMoRW5Smttne7BwHM8s/fb5JFs+bVGNSeHWzwZkWXWValR1M30jyXo1s/RaqgwwhEC62u4rFH/FBcBPg== + dependencies: + "@babel/helper-compilation-targets" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.24.6" + +"@babel/plugin-transform-object-super@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.6.tgz" + integrity sha512-N/C76ihFKlZgKfdkEYKtaRUtXZAgK7sOY4h2qrbVbVTXPrKGIi8aww5WGe/+Wmg8onn8sr2ut6FXlsbu/j6JHg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-replace-supers" "^7.24.6" + +"@babel/plugin-transform-optional-catch-binding@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.6.tgz" + integrity sha512-L5pZ+b3O1mSzJ71HmxSCmTVd03VOT2GXOigug6vDYJzE5awLI7P1g0wFcdmGuwSDSrQ0L2rDOe/hHws8J1rv3w== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-transform-optional-chaining@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.6.tgz" + integrity sha512-cHbqF6l1QP11OkYTYQ+hhVx1E017O5ZcSPXk9oODpqhcAD1htsWG2NpHrrhthEO2qZomLK0FXS+u7NfrkF5aOQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-transform-parameters@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.6.tgz" + integrity sha512-ST7guE8vLV+vI70wmAxuZpIKzVjvFX9Qs8bl5w6tN/6gOypPWUmMQL2p7LJz5E63vEGrDhAiYetniJFyBH1RkA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-private-methods@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.6.tgz" + integrity sha512-T9LtDI0BgwXOzyXrvgLTT8DFjCC/XgWLjflczTLXyvxbnSR/gpv0hbmzlHE/kmh9nOvlygbamLKRo6Op4yB6aw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-private-property-in-object@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.6.tgz" + integrity sha512-Qu/ypFxCY5NkAnEhCF86Mvg3NSabKsh/TPpBVswEdkGl7+FbsYHy1ziRqJpwGH4thBdQHh8zx+z7vMYmcJ7iaQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.6" + "@babel/helper-create-class-features-plugin" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-transform-property-literals@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.6.tgz" + integrity sha512-oARaglxhRsN18OYsnPTpb8TcKQWDYNsPNmTnx5++WOAsUJ0cSC/FZVlIJCKvPbU4yn/UXsS0551CFKJhN0CaMw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-regenerator@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.6.tgz" + integrity sha512-SMDxO95I8WXRtXhTAc8t/NFQUT7VYbIWwJCJgEli9ml4MhqUMh4S6hxgH6SmAC3eAQNWCDJFxcFeEt9w2sDdXg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + regenerator-transform "^0.15.2" + +"@babel/plugin-transform-reserved-words@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.6.tgz" + integrity sha512-DcrgFXRRlK64dGE0ZFBPD5egM2uM8mgfrvTMOSB2yKzOtjpGegVYkzh3s1zZg1bBck3nkXiaOamJUqK3Syk+4A== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-shorthand-properties@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.6.tgz" + integrity sha512-xnEUvHSMr9eOWS5Al2YPfc32ten7CXdH7Zwyyk7IqITg4nX61oHj+GxpNvl+y5JHjfN3KXE2IV55wAWowBYMVw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-spread@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.6.tgz" + integrity sha512-h/2j7oIUDjS+ULsIrNZ6/TKG97FgmEk1PXryk/HQq6op4XUUUwif2f69fJrzK0wza2zjCS1xhXmouACaWV5uPA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" + +"@babel/plugin-transform-sticky-regex@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.6.tgz" + integrity sha512-fN8OcTLfGmYv7FnDrsjodYBo1DhPL3Pze/9mIIE2MGCT1KgADYIOD7rEglpLHZj8PZlC/JFX5WcD+85FLAQusw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-template-literals@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.6.tgz" + integrity sha512-BJbEqJIcKwrqUP+KfUIkxz3q8VzXe2R8Wv8TaNgO1cx+nNavxn/2+H8kp9tgFSOL6wYPPEgFvU6IKS4qoGqhmg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-typeof-symbol@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.6.tgz" + integrity sha512-IshCXQ+G9JIFJI7bUpxTE/oA2lgVLAIK8q1KdJNoPXOpvRaNjMySGuvLfBw/Xi2/1lLo953uE8hyYSDW3TSYig== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-typescript@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.6.tgz" + integrity sha512-H0i+hDLmaYYSt6KU9cZE0gb3Cbssa/oxWis7PX4ofQzbvsfix9Lbh8SRk7LCPDlLWJHUiFeHU0qRRpF/4Zv7mQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.6" + "@babel/helper-create-class-features-plugin" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/plugin-syntax-typescript" "^7.24.6" + +"@babel/plugin-transform-unicode-escapes@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.6.tgz" + integrity sha512-bKl3xxcPbkQQo5eX9LjjDpU2xYHeEeNQbOhj0iPvetSzA+Tu9q/o5lujF4Sek60CM6MgYvOS/DJuwGbiEYAnLw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-unicode-property-regex@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.6.tgz" + integrity sha512-8EIgImzVUxy15cZiPii9GvLZwsy7Vxc+8meSlR3cXFmBIl5W5Tn9LGBf7CDKkHj4uVfNXCJB8RsVfnmY61iedA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-unicode-regex@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.6.tgz" + integrity sha512-pssN6ExsvxaKU638qcWb81RrvvgZom3jDgU/r5xFZ7TONkZGFf4MhI2ltMb8OcQWhHyxgIavEU+hgqtbKOmsPA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/plugin-transform-unicode-sets-regex@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.6.tgz" + integrity sha512-quiMsb28oXWIDK0gXLALOJRXLgICLiulqdZGOaPPd0vRT7fQp74NtdADAVu+D8s00C+0Xs0MxVP0VKF/sZEUgw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + +"@babel/preset-env@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.6.tgz" + integrity sha512-CrxEAvN7VxfjOG8JNF2Y/eMqMJbZPZ185amwGUBp8D9USK90xQmv7dLdFSa+VbD7fdIqcy/Mfv7WtzG8+/qxKg== + dependencies: + "@babel/compat-data" "^7.24.6" + "@babel/helper-compilation-targets" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-validator-option" "^7.24.6" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.6" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.6" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.6" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.6" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.24.6" + "@babel/plugin-syntax-import-attributes" "^7.24.6" + "@babel/plugin-syntax-import-meta" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.24.6" + "@babel/plugin-transform-async-generator-functions" "^7.24.6" + "@babel/plugin-transform-async-to-generator" "^7.24.6" + "@babel/plugin-transform-block-scoped-functions" "^7.24.6" + "@babel/plugin-transform-block-scoping" "^7.24.6" + "@babel/plugin-transform-class-properties" "^7.24.6" + "@babel/plugin-transform-class-static-block" "^7.24.6" + "@babel/plugin-transform-classes" "^7.24.6" + "@babel/plugin-transform-computed-properties" "^7.24.6" + "@babel/plugin-transform-destructuring" "^7.24.6" + "@babel/plugin-transform-dotall-regex" "^7.24.6" + "@babel/plugin-transform-duplicate-keys" "^7.24.6" + "@babel/plugin-transform-dynamic-import" "^7.24.6" + "@babel/plugin-transform-exponentiation-operator" "^7.24.6" + "@babel/plugin-transform-export-namespace-from" "^7.24.6" + "@babel/plugin-transform-for-of" "^7.24.6" + "@babel/plugin-transform-function-name" "^7.24.6" + "@babel/plugin-transform-json-strings" "^7.24.6" + "@babel/plugin-transform-literals" "^7.24.6" + "@babel/plugin-transform-logical-assignment-operators" "^7.24.6" + "@babel/plugin-transform-member-expression-literals" "^7.24.6" + "@babel/plugin-transform-modules-amd" "^7.24.6" + "@babel/plugin-transform-modules-commonjs" "^7.24.6" + "@babel/plugin-transform-modules-systemjs" "^7.24.6" + "@babel/plugin-transform-modules-umd" "^7.24.6" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.24.6" + "@babel/plugin-transform-new-target" "^7.24.6" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.6" + "@babel/plugin-transform-numeric-separator" "^7.24.6" + "@babel/plugin-transform-object-rest-spread" "^7.24.6" + "@babel/plugin-transform-object-super" "^7.24.6" + "@babel/plugin-transform-optional-catch-binding" "^7.24.6" + "@babel/plugin-transform-optional-chaining" "^7.24.6" + "@babel/plugin-transform-parameters" "^7.24.6" + "@babel/plugin-transform-private-methods" "^7.24.6" + "@babel/plugin-transform-private-property-in-object" "^7.24.6" + "@babel/plugin-transform-property-literals" "^7.24.6" + "@babel/plugin-transform-regenerator" "^7.24.6" + "@babel/plugin-transform-reserved-words" "^7.24.6" + "@babel/plugin-transform-shorthand-properties" "^7.24.6" + "@babel/plugin-transform-spread" "^7.24.6" + "@babel/plugin-transform-sticky-regex" "^7.24.6" + "@babel/plugin-transform-template-literals" "^7.24.6" + "@babel/plugin-transform-typeof-symbol" "^7.24.6" + "@babel/plugin-transform-unicode-escapes" "^7.24.6" + "@babel/plugin-transform-unicode-property-regex" "^7.24.6" + "@babel/plugin-transform-unicode-regex" "^7.24.6" + "@babel/plugin-transform-unicode-sets-regex" "^7.24.6" + "@babel/preset-modules" "0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.4" + babel-plugin-polyfill-regenerator "^0.6.1" + core-js-compat "^3.31.0" + semver "^6.3.1" + +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-typescript@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.6.tgz" + integrity sha512-U10aHPDnokCFRXgyT/MaIRTivUu2K/mu0vJlwRS9LxJmJet+PFQNKpggPyFCUtC6zWSBPjvxjnpNkAn3Uw2m5w== + dependencies: + "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-validator-option" "^7.24.6" + "@babel/plugin-syntax-jsx" "^7.24.6" + "@babel/plugin-transform-modules-commonjs" "^7.24.6" + "@babel/plugin-transform-typescript" "^7.24.6" + +"@babel/regjsgen@^0.8.0": + version "0.8.0" + resolved "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz" + integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== + +"@babel/runtime@^7.8.4": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.6.tgz" + integrity sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.24.6", "@babel/template@^7.3.3": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.24.6.tgz" + integrity sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw== + dependencies: + "@babel/code-frame" "^7.24.6" + "@babel/parser" "^7.24.6" + "@babel/types" "^7.24.6" + +"@babel/traverse@^7.24.6": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.6.tgz" + integrity sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw== + dependencies: + "@babel/code-frame" "^7.24.6" + "@babel/generator" "^7.24.6" + "@babel/helper-environment-visitor" "^7.24.6" + "@babel/helper-function-name" "^7.24.6" + "@babel/helper-hoist-variables" "^7.24.6" + "@babel/helper-split-export-declaration" "^7.24.6" + "@babel/parser" "^7.24.6" + "@babel/types" "^7.24.6" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.24.6", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz" + integrity sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ== + dependencies: + "@babel/helper-string-parser" "^7.24.6" + "@babel/helper-validator-identifier" "^7.24.6" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" @@ -46,16 +1041,270 @@ resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz" integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA== -"@jridgewell/resolve-uri@^3.0.3": +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": + version "0.1.3" + resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== + dependencies: + jest-get-type "^29.6.3" + +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + +"@jest/transform@^29.0.0", "@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + +"@jest/types@^29.0.0", "@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/sourcemap-codec@^1.4.10": +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": version "1.4.15" resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@jridgewell/trace-mapping@^0.3.12": + version "0.3.25" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@jridgewell/trace-mapping@^0.3.18": + version "0.3.25" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@jridgewell/trace-mapping@^0.3.24": + version "0.3.25" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@jridgewell/trace-mapping@0.3.9": version "0.3.9" resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" @@ -125,6 +1374,25 @@ dependencies: "@prisma/debug" "5.14.0" +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sinonjs/commons@^3.0.0": + version "3.0.1" + resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz" + integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.3.0" + resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + "@tsconfig/node10@^1.0.7": version "1.0.11" resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz" @@ -145,6 +1413,39 @@ resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== +"@types/babel__core@^7.1.14": + version "7.20.5" + resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.8" + resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz" + integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.20.6" + resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz" + integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== + dependencies: + "@babel/types" "^7.20.7" + "@types/bcrypt@^5.0.2": version "5.0.2" resolved "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz" @@ -201,6 +1502,13 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/graceful-fs@^4.1.3": + version "4.1.9" + resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz" + integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== + dependencies: + "@types/node" "*" + "@types/http-errors@*": version "2.0.4" resolved "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz" @@ -211,6 +1519,25 @@ resolved "https://registry.npmjs.org/@types/is-email/-/is-email-1.0.0.tgz" integrity sha512-b/76ooKpYY/b+oPrOuc/pmM5eag+ZlzctPsKcRCIKs+TFzh0FL58OeXtSPkbXt3uKNK84YCKHmjnoREtwve5Kg== +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.6" + resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.4" + resolved "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/json-schema@^7.0.6": version "7.0.15" resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" @@ -242,7 +1569,7 @@ dependencies: "@types/express" "*" -"@types/node@*", "@types/node@^20.12.13": +"@types/node@*", "@types/node@^20.10.6", "@types/node@^20.12.13": version "20.12.13" resolved "https://registry.npmjs.org/@types/node/-/node-20.12.13.tgz" integrity sha512-gBGeanV41c1L171rR7wjbMiEpEI/l5XFQdLLfhr/REwpgDy/4U8y89+i8kRiLzDyZdOkXh+cRaTetUnCYutoXA== @@ -308,6 +1635,11 @@ "@types/node" "*" "@types/send" "*" +"@types/stack-utils@^2.0.0": + version "2.0.3" + resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + "@types/swagger-jsdoc@^6.0.4": version "6.0.4" resolved "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz" @@ -321,12 +1653,24 @@ "@types/express" "*" "@types/serve-static" "*" +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^17.0.8": + version "17.0.32" + resolved "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz" + integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== + dependencies: + "@types/yargs-parser" "*" + abbrev@1: version "1.1.1" resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -accepts@~1.3.8: +accepts@^1.3.7, accepts@~1.3.8: version "1.3.8" resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== @@ -351,12 +1695,38 @@ agent-base@6: dependencies: debug "4" +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -anymatch@~3.1.2: +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^3.0.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -387,6 +1757,13 @@ arg@^4.1.0: resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + argparse@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" @@ -397,6 +1774,90 @@ array-flatten@1.1.1: resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== +babel-jest@^29.0.0, babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-plugin-polyfill-corejs2@^0.4.10: + version "0.4.11" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz" + integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== + dependencies: + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.6.2" + semver "^6.3.1" + +babel-plugin-polyfill-corejs3@^0.10.4: + version "0.10.4" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz" + integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.1" + core-js-compat "^3.36.1" + +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.2" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz" + integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.2" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" @@ -453,13 +1914,37 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@~3.0.2: +braces@^3.0.3, braces@~3.0.2: version "3.0.3" resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: fill-range "^7.1.1" +browserslist@^4.22.2, browserslist@^4.23.0, "browserslist@>= 4.21.0": + version "4.23.0" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz" + integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== + dependencies: + caniuse-lite "^1.0.30001587" + electron-to-chromium "^1.4.668" + node-releases "^2.0.14" + update-browserslist-db "^1.0.13" + +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz" @@ -498,6 +1983,48 @@ call-me-maybe@^1.0.1: resolved "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz" integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001587: + version "1.0.30001625" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001625.tgz" + integrity sha512-4KE9N2gcRH+HQhpeiRZXd+1niLB/XNLAhSy4z7fI8EzcbcPoAqjNInxVHTiTwWfTIV4w096XG8OtCOCQQKPv3w== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + chokidar@^3.5.2: version "3.6.0" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" @@ -518,6 +2045,59 @@ chownr@^2.0.0: resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== +ci-info@^3.2.0: + version "3.9.0" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + +cjs-module-lexer@^1.0.0: + version "1.3.1" + resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz" + integrity sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + color-support@^1.1.2: version "1.1.3" resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz" @@ -553,7 +2133,7 @@ console-control-strings@^1.0.0, console-control-strings@^1.1.0: resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz" integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== -content-disposition@0.5.4: +content-disposition@^0.5.3, content-disposition@0.5.4: version "0.5.4" resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== @@ -565,6 +2145,11 @@ content-type@~1.0.4, content-type@~1.0.5: resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" @@ -580,6 +2165,13 @@ cookie@0.6.0: resolved "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz" integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== +core-js-compat@^3.31.0, core-js-compat@^3.36.1: + version "3.37.1" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz" + integrity sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg== + dependencies: + browserslist "^4.23.0" + core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" @@ -593,11 +2185,33 @@ cors@^2.8.5: object-assign "^4" vary "^1" +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + debug@^4: version "4.3.4" resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" @@ -605,6 +2219,27 @@ debug@^4: dependencies: ms "2.1.2" +debug@^4.1.0: + version "4.3.4" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^4.1.1: + version "4.3.4" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^4.3.1: + version "4.3.4" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + debug@2.6.9: version "2.6.9" resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" @@ -619,6 +2254,16 @@ debug@4: dependencies: ms "2.1.2" +dedent@^1.0.0: + version "1.5.3" + resolved "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz" + integrity sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ== + +deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + define-data-property@^1.1.4: version "1.1.4" resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz" @@ -633,6 +2278,11 @@ delegates@^1.0.0: resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== +depd@^1.1.0: + version "1.1.2" + resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + depd@~2.0.0, depd@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" @@ -648,6 +2298,16 @@ detect-libc@^2.0.0: resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz" integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + diff@^4.0.1: version "4.0.2" resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" @@ -677,6 +2337,16 @@ ee-first@1.1.1: resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== +electron-to-chromium@^1.4.668: + version "1.4.787" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.787.tgz" + integrity sha512-d0EFmtLPjctczO3LogReyM2pbBiiZbnsKnGF+cdZhsYzHm/A0GV7W94kqzLD8SN4O3f3iHlgLUChqghgyznvCQ== + +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" @@ -687,6 +2357,13 @@ encodeurl@~1.0.2: resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + es-define-property@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz" @@ -728,11 +2405,31 @@ esbuild@~0.20.2: "@esbuild/win32-ia32" "0.20.2" "@esbuild/win32-x64" "0.20.2" +escalade@^3.1.1, escalade@^3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" @@ -743,6 +2440,37 @@ etag@~1.8.1: resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + 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" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + dependencies: + "@jest/expect-utils" "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + express-session@^1.18.0: version "1.18.0" resolved "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz" @@ -794,6 +2522,18 @@ express@^4.18.2, "express@>=4.0.0 || >=5.0.0-beta": utils-merge "1.0.1" vary "~1.1.2" +fast-json-stable-stringify@^2.1.0, fast-json-stable-stringify@2.x: + version "2.1.0" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + fill-range@^7.1.1: version "7.1.1" resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" @@ -814,12 +2554,20 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== -fresh@0.5.2: +fresh@^0.5.2, fresh@0.5.2: version "0.5.2" resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== @@ -836,7 +2584,7 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.3.2, fsevents@~2.3.3: +fsevents@^2.3.2, fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -861,6 +2609,16 @@ gauge@^3.0.0: strip-ansi "^6.0.1" wide-align "^1.1.2" +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: version "1.2.4" resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz" @@ -872,6 +2630,16 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: has-symbols "^1.0.3" hasown "^2.0.0" +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + get-tsconfig@^4.7.5: version "4.7.5" resolved "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz" @@ -886,7 +2654,7 @@ glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob@^7.1.3: +glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -910,6 +2678,11 @@ glob@7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + gopd@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz" @@ -917,11 +2690,21 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" +graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has-property-descriptors@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz" @@ -951,6 +2734,11 @@ hasown@^2.0.0: dependencies: function-bind "^1.1.2" +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + http-errors@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" @@ -970,6 +2758,11 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" @@ -982,6 +2775,19 @@ ignore-by-default@^1.0.1: resolved "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz" integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" @@ -1000,6 +2806,11 @@ ipaddr.js@1.9.1: resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" @@ -1007,6 +2818,13 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + is-email@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/is-email/-/is-email-1.0.2.tgz" @@ -1022,6 +2840,11 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" @@ -1034,6 +2857,11 @@ is-number@^7.0.0: resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + is-uuid@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/is-uuid/-/is-uuid-1.0.2.tgz" @@ -1044,6 +2872,442 @@ isarray@~1.0.0: resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-instrument@^6.0.0: + version "6.0.2" + resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz" + integrity sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw== + dependencies: + "@babel/core" "^7.23.9" + "@babel/parser" "^7.23.9" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.7" + resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz" + integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^1.0.0" + is-generator-fn "^2.0.0" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + pretty-format "^29.7.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" + jest-get-type "^29.6.3" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@jest/types" "^29.6.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock-extended@^3.0.7: + version "3.0.7" + resolved "https://registry.npmjs.org/jest-mock-extended/-/jest-mock-extended-3.0.7.tgz" + integrity sha512-7lsKdLFcW9B9l5NzZ66S/yTQ9k8rFtnwYdCNuRU/81fqDWicNDVhitTSPnrGmNeNm0xyw0JHexEOShrIKRCIRQ== + dependencies: + ts-essentials "^10.0.0" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + +jest-resolve@*, jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + dependencies: + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" + "@jest/source-map" "^29.6.3" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.7.0" + graceful-fs "^4.2.9" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + natural-compare "^1.4.0" + pretty-format "^29.7.0" + semver "^7.5.3" + +jest-util@^29.0.0, jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.7.0" + string-length "^4.0.1" + +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +"jest@^24.0.0 || ^25.0.0 || ^26.0.0 || ^27.0.0 || ^28.0.0 || ^29.0.0", jest@^29.0.0, jest@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" @@ -1051,6 +3315,26 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + jsonwebtoken@^9.0.2: version "9.0.2" resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz" @@ -1084,6 +3368,33 @@ jws@^3.2.2: jwa "^1.4.1" safe-buffer "^5.0.1" +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz" @@ -1124,6 +3435,11 @@ lodash.isstring@^4.0.1: resolved "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz" integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== +lodash.memoize@4.x: + version "4.1.2" + resolved "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + lodash.mergewith@^4.6.2: version "4.6.2" resolved "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz" @@ -1134,6 +3450,13 @@ lodash.once@^4.0.0: resolved "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz" integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + make-dir@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" @@ -1141,26 +3464,53 @@ make-dir@^3.1.0: dependencies: semver "^6.0.0" -make-error@^1.1.1: +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +make-error@^1.1.1, make-error@1.x: version "1.3.6" resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + media-typer@0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -merge-descriptors@1.0.1: +merge-descriptors@^1.0.1, merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== -methods@~1.1.2: +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +methods@^1.1.2, methods@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== +micromatch@^4.0.4: + version "4.0.7" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz" + integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + mime-db@1.52.0: version "1.52.0" resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" @@ -1173,11 +3523,16 @@ mime-types@~2.1.24, mime-types@~2.1.34: dependencies: mime-db "1.52.0" -mime@1.6.0: +mime@^1.3.4, mime@1.6.0: version "1.6.0" resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" @@ -1278,6 +3633,11 @@ multer@^1.4.5-lts.1: type-is "^1.6.4" xtend "^4.0.0" +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + negotiator@0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" @@ -1295,6 +3655,34 @@ node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-mocks-http@^1.14.1: + version "1.14.1" + resolved "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.14.1.tgz" + integrity sha512-mfXuCGonz0A7uG1FEjnypjm34xegeN5+HI6xeGhYKecfgaZhjsmYoLE9LEFmT+53G1n8IuagPZmVnEL/xNsFaA== + dependencies: + "@types/express" "^4.17.21" + "@types/node" "^20.10.6" + accepts "^1.3.7" + content-disposition "^0.5.3" + depd "^1.1.0" + fresh "^0.5.2" + merge-descriptors "^1.0.1" + methods "^1.1.2" + mime "^1.3.4" + parseurl "^1.3.3" + range-parser "^1.2.0" + type-is "^1.6.18" + +node-releases@^2.0.14: + version "2.0.14" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== + nodemon@^3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/nodemon/-/nodemon-3.1.2.tgz" @@ -1323,6 +3711,13 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + npmlog@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz" @@ -1374,12 +3769,55 @@ once@^1.3.0: dependencies: wrappy "1" +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + openapi-types@>=7: version "12.1.3" resolved "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz" integrity sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw== -parseurl@~1.3.3: +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parseurl@^1.3.3, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== @@ -1416,11 +3854,26 @@ passport@^0.7.0: pause "0.0.1" utils-merge "^1.0.1" +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" @@ -1431,11 +3884,37 @@ pause@0.0.1: resolved "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz" integrity sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg== -picomatch@^2.0.4, picomatch@^2.2.1: +picocolors@^1.0.0, picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pirates@^4.0.4: + version "4.0.6" + resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + prisma@*, prisma@^5.4.2: version "5.14.0" resolved "https://registry.npmjs.org/prisma/-/prisma-5.14.0.tgz" @@ -1448,6 +3927,14 @@ process-nextick-args@~2.0.0: resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" @@ -1461,6 +3948,11 @@ pstree.remy@^1.1.8: resolved "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz" integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== +pure-rand@^6.0.0: + version "6.1.0" + resolved "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz" + integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== + qs@6.11.0: version "6.11.0" resolved "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz" @@ -1473,7 +3965,7 @@ random-bytes@~1.0.0: resolved "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz" integrity sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ== -range-parser@~1.2.1: +range-parser@^1.2.0, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== @@ -1488,6 +3980,11 @@ raw-body@2.5.2: iconv-lite "0.4.24" unpipe "1.0.0" +react-is@^18.0.0: + version "18.3.1" + resolved "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz" + integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== + readable-stream@^2.2.2: version "2.3.8" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" @@ -1517,11 +4014,85 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +regenerate-unicode-properties@^10.1.0: + version "10.1.1" + resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz" + integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== + dependencies: + regenerate "^1.4.2" + +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== + dependencies: + "@babel/runtime" "^7.8.4" + +regexpu-core@^5.3.1: + version "5.3.2" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== + dependencies: + "@babel/regjsgen" "^0.8.0" + regenerate "^1.4.2" + regenerate-unicode-properties "^10.1.0" + regjsparser "^0.9.1" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" + +regjsparser@^0.9.1: + version "0.9.1" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz" + integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== + dependencies: + jsesc "~0.5.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-pkg-maps@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== +resolve.exports@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz" + integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + +resolve@^1.14.2, resolve@^1.20.0: + version "1.22.8" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + rimraf@^3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" @@ -1559,6 +4130,16 @@ semver@^6.0.0: resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== +semver@^6.3.0: + version "6.3.1" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + semver@^7.3.5, semver@^7.5.3, semver@^7.5.4: version "7.6.2" resolved "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz" @@ -1615,6 +4196,18 @@ setprototypeof@1.2.0: resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + side-channel@^1.0.4: version "1.0.6" resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz" @@ -1625,7 +4218,7 @@ side-channel@^1.0.4: get-intrinsic "^1.2.4" object-inspect "^1.13.1" -signal-exit@^3.0.0: +signal-exit@^3.0.0, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -1637,6 +4230,41 @@ simple-update-notifier@^2.0.0: dependencies: semver "^7.5.3" +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + statuses@2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" @@ -1654,7 +4282,15 @@ string_decoder@^1.1.1, string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.2.3: +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -1663,25 +4299,59 @@ string_decoder@^1.1.1, string_decoder@~1.1.1: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -strip-ansi@^6.0.1: +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + superstruct@^1.0.3: version "1.0.4" resolved "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz" integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== -supports-color@^5.5.0: +supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + swagger-jsdoc@^6.2.8: version "6.2.8" resolved "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz" @@ -1725,6 +4395,25 @@ tar@^6.1.11: mkdirp "^1.0.3" yallist "^4.0.0" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" @@ -1747,7 +4436,26 @@ tr46@~0.0.3: resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== -ts-node@^10.9.2: +ts-essentials@^10.0.0: + version "10.0.0" + resolved "https://registry.npmjs.org/ts-essentials/-/ts-essentials-10.0.0.tgz" + integrity sha512-77FHNJEyysF9+1s4G6eejuA1lxw7uMchT3ZPy3CIbh7GIunffpshtM8pTe5G6N5dpOzNevqRHew859ceLWVBfw== + +ts-jest@^29.1.4: + version "29.1.4" + resolved "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.4.tgz" + integrity sha512-YiHwDhSvCiItoAgsKtoLFCuakDzDsJ1DLDnSouTaTmdOcOwIkSzbLXduaQ6M5DRVhuZC/NYaaZ/mtHbWMv/S6Q== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^29.0.0" + json5 "^2.2.3" + lodash.memoize "4.x" + make-error "1.x" + semver "^7.5.3" + yargs-parser "^21.0.1" + +ts-node@^10.9.2, ts-node@>=9.0.0: version "10.9.2" resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz" integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== @@ -1776,7 +4484,17 @@ tsx@^4.11.0: optionalDependencies: fsevents "~2.3.3" -type-is@^1.6.4, type-is@~1.6.18: +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-is@^1.6.18, type-is@^1.6.4, type-is@~1.6.18: version "1.6.18" resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== @@ -1789,7 +4507,7 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typescript@^5.4.5, typescript@>=2.7: +"typescript@^3.0.0 || ^4.0.0 || ^5.0.0", typescript@^5.4.5, typescript@>=2.7, "typescript@>=4.3 <6", typescript@>=4.5.0: version "5.4.5" resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz" integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== @@ -1816,11 +4534,42 @@ undici-types@~5.26.4: resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== + dependencies: + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz" + integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== + unpipe@~1.0.0, unpipe@1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +update-browserslist-db@^1.0.13: + version "1.0.16" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz" + integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ== + dependencies: + escalade "^3.1.2" + picocolors "^1.0.1" + util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" @@ -1836,6 +4585,15 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +v8-to-istanbul@^9.0.1: + version "9.2.0" + resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz" + integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + validator@^13.7.0: version "13.12.0" resolved "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz" @@ -1846,6 +4604,13 @@ vary@^1, vary@~1.1.2: resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" @@ -1859,6 +4624,13 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" +which@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + wide-align@^1.1.2: version "1.1.5" resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz" @@ -1866,16 +4638,43 @@ wide-align@^1.1.2: dependencies: string-width "^1.0.2 || 2 || 3 || 4" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + xtend@^4.0.0: version "4.0.2" resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" @@ -1886,11 +4685,34 @@ yaml@2.0.0-1: resolved "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz" integrity sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ== +yargs-parser@^21.0.1, yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.3.1: + version "17.7.2" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + yn@3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + z-schema@^5.0.1: version "5.0.5" resolved "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz" From 6cb8b19d35a8fc90ae912da82dcc226cfa5213ef Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Mon, 3 Jun 2024 11:13:29 +0900 Subject: [PATCH 44/60] =?UTF-8?q?[#M12]=20feat=20:=20=EC=A4=91=EA=B3=A0?= =?UTF-8?q?=EB=A7=88=EC=BC=93=20product=20=EA=B4=80=EB=A0=A8=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/test/product.test.ts | 78 ----- src/test/productService.test.ts | 507 ++++++++++++++++++++++++++++++++ 3 files changed, 508 insertions(+), 79 deletions(-) delete mode 100644 src/test/product.test.ts create mode 100644 src/test/productService.test.ts diff --git a/package.json b/package.json index 86adb09..e9da8e4 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "scripts": { "start": "tsx --loader ts-node/esm src/app.ts", "dev": "nodemon", - "test": "jest" + "test": "jest --coverage" }, "prisma": { "seed": "tsx prisma/seed.ts" diff --git a/src/test/product.test.ts b/src/test/product.test.ts deleted file mode 100644 index c10a7c8..0000000 --- a/src/test/product.test.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { describe, expect, jest, test } from "@jest/globals"; -import prisma from "../client"; -import { createProduct } from "../services/productService"; - -jest.mock("../client", () => ({ - __esModule: true, - default: { - user: { - findUnique: jest.fn(), - }, - product: { - create: jest.fn(), - }, - }, -})); - -describe("중고마켓", () => { - test("새 상품을 등록한다", async () => { - const userId = 1; - const productData = { - name: "판다인형 테스트", - description: "테스트용 판다인형입니다.", - price: 20000, - }; - const imageUrl = "image1.jpg"; - - const mockUser = { - id: 1, - googleId: null, - email: "test@example.com", - name: "테스트", - nickname: "테스트의왕", - image: null, - password: null, - createdAt: new Date(), - updatedAt: new Date(), - }; - - const mockProduct = { - id: "test-product-id", - ...productData, - writer: mockUser.name, - userId: userId, - tags: [], - favoriteCount: 0, - createdAt: new Date(), - updatedAt: new Date(), - images: [{ imagePath: imageUrl }], - }; - - (prisma.user.findUnique as jest.MockedFunction).mockResolvedValue(mockUser); - (prisma.product.create as jest.MockedFunction).mockResolvedValue(mockProduct); - - const result = await createProduct(userId, productData, imageUrl); - - expect(result).toEqual(mockProduct); - - expect(prisma.user.findUnique).toHaveBeenCalledWith({ - where: { id: userId }, - select: { name: true }, - }); - expect(prisma.product.create).toHaveBeenCalledWith({ - data: { - ...productData, - writer: mockUser.name, - user: { - connect: { id: userId }, - }, - images: { - create: [{ imagePath: imageUrl }], - }, - }, - include: { - images: true, - }, - }); - }); -}); diff --git a/src/test/productService.test.ts b/src/test/productService.test.ts new file mode 100644 index 0000000..45e9804 --- /dev/null +++ b/src/test/productService.test.ts @@ -0,0 +1,507 @@ +import { describe, expect, jest, test } from "@jest/globals"; +import prisma from "../client"; +import { + createProduct, + deleteProduct, + getBestProducts, + getProductById, + getProducts, + likeProduct, + unlikeProduct, + updateProduct, +} from "../services/productService"; +import AppError from "../utils/errors"; + +jest.mock("../client", () => ({ + __esModule: true, + default: { + product: { + findMany: jest.fn(), + create: jest.fn(), + findUnique: jest.fn(), + findUniqueOrThrow: jest.fn(), + update: jest.fn(), + delete: jest.fn(), + }, + user: { + findUnique: jest.fn(), + }, + image: { + update: jest.fn(), + create: jest.fn(), + }, + favorite: { + findUnique: jest.fn(), + create: jest.fn(), + delete: jest.fn(), + }, + $transaction: jest.fn(), + }, +})); + +describe("상품 서비스", () => { + const mockProduct = { + id: "test-product-id", + name: "테스트 상품", + description: "이것은 테스트 상품입니다", + price: 100, + favoriteCount: 0, + createdAt: new Date(), + updatedAt: new Date(), + writer: "테스트 유저", + tags: [], + userId: 1, + images: [{ id: "image-id", imagePath: "image1.jpg" }], + }; + + const mockUser = { + id: 1, + googleId: null, + email: "test@example.com", + name: "테스트 유저", + nickname: "testuser", + image: null, + password: null, + createdAt: new Date(), + updatedAt: new Date(), + }; + + const mockFavorite = { + id: "favorite-id", + createdAt: new Date(), + userId: 1, + productId: "test-product-id", + articleId: null, + }; + + const mockImage = { + id: "image-id", + imagePath: "image1.jpg", + productId: "test-product-id", + createdAt: new Date(), + updatedAt: new Date(), + articleId: null, + }; + + test("상품을 조회한다", async () => { + const products = [mockProduct]; + (prisma.product.findMany as jest.MockedFunction).mockResolvedValue(products); + + const result = await getProducts({ offset: 0, limit: 10, orderBy: "recent", keyword: "" }); + expect(result).toEqual(products); + expect(prisma.product.findMany).toHaveBeenCalledWith({ + orderBy: { createdAt: "desc" }, + skip: 0, + take: 10, + where: { + OR: [{ name: { contains: "", mode: "insensitive" } }, { description: { contains: "", mode: "insensitive" } }], + }, + select: { + id: true, + name: true, + description: true, + price: true, + favoriteCount: true, + createdAt: true, + updatedAt: true, + writer: true, + tags: true, + userId: true, + images: { + select: { imagePath: true }, + }, + }, + }); + }); + + test("베스트 상품을 조회한다", async () => { + const products = [mockProduct]; + (prisma.product.findMany as jest.MockedFunction).mockResolvedValue(products); + + const result = await getBestProducts(); + expect(result).toEqual(products); + expect(prisma.product.findMany).toHaveBeenCalledWith({ + orderBy: { favoriteCount: "desc" }, + take: 4, + select: { + id: true, + name: true, + description: true, + price: true, + favoriteCount: true, + createdAt: true, + updatedAt: true, + writer: true, + tags: true, + userId: true, + images: { + select: { imagePath: true }, + }, + }, + }); + }); + + test("상품을 생성한다", async () => { + (prisma.user.findUnique as jest.MockedFunction).mockResolvedValue(mockUser); + (prisma.product.create as jest.MockedFunction).mockResolvedValue(mockProduct); + + const result = await createProduct( + 1, + { + name: "테스트 상품", + description: "이것은 테스트 상품입니다", + price: 100, + }, + "image1.jpg" + ); + + expect(result).toEqual(mockProduct); + expect(prisma.user.findUnique).toHaveBeenCalledWith({ + where: { id: 1 }, + select: { name: true }, + }); + expect(prisma.product.create).toHaveBeenCalledWith({ + data: { + name: "테스트 상품", + description: "이것은 테스트 상품입니다", + price: 100, + writer: "테스트 유저", + user: { + connect: { id: 1 }, + }, + images: { + create: [{ imagePath: "image1.jpg" }], + }, + }, + include: { images: true }, + }); + }); + + test("유저가 없을 때 상품을 생성하려고 하면 예외를 발생시킨다", async () => { + (prisma.user.findUnique as jest.MockedFunction).mockResolvedValue(null); + await expect( + createProduct( + 1, + { + name: "테스트 상품", + description: "이것은 테스트 상품입니다", + price: 100, + }, + "image1.jpg" + ) + ).rejects.toThrow("유저 정보를 찾을 수 없습니다."); + }); + + test("상품 아이디로 상품을 조회한다", async () => { + (prisma.product.findUnique as jest.MockedFunction).mockResolvedValue(mockProduct); + + const result = await getProductById("test-product-id"); + expect(result).toEqual(mockProduct); + expect(prisma.product.findUnique).toHaveBeenCalledWith({ + where: { id: "test-product-id" }, + select: { + id: true, + name: true, + description: true, + price: true, + favoriteCount: true, + createdAt: true, + writer: true, + images: { + select: { + imagePath: true, + }, + }, + tags: true, + updatedAt: true, + userId: true, + }, + }); + }); + + test("존재하지 않는 상품을 조회하려고 하면 예외를 발생시킨다", async () => { + (prisma.product.findUnique as jest.MockedFunction).mockResolvedValue(null); + await expect(getProductById("non-existent-product-id")).rejects.toThrow("존재하지 않는 상품입니다."); + }); + + test("상품을 업데이트한다", async () => { + ( + prisma.product.findUniqueOrThrow as jest.MockedFunction + ).mockResolvedValue(mockProduct); + (prisma.product.update as jest.MockedFunction).mockResolvedValue(mockProduct); + (prisma.image.update as jest.MockedFunction).mockResolvedValue(mockImage); + (prisma.image.create as jest.MockedFunction).mockResolvedValue(mockImage); + + const result = await updateProduct( + "test-product-id", + 1, + { + name: "업데이트된 상품", + description: "업데이트된 설명", + price: 150, + }, + "image1.jpg" + ); + + expect(result).toEqual(mockProduct); + expect(prisma.product.findUniqueOrThrow).toHaveBeenCalledWith({ + where: { id: "test-product-id" }, + include: { images: true }, + }); + + const existingImage = mockProduct.images[0]; + if (existingImage) { + expect(prisma.image.update).toHaveBeenCalledWith({ + where: { id: existingImage.id }, + data: { imagePath: "image1.jpg" }, + }); + } else { + expect(prisma.image.create).toHaveBeenCalledWith({ + data: { + imagePath: "image1.jpg", + product: { connect: { id: "test-product-id" } }, + }, + }); + } + + expect(prisma.product.update).toHaveBeenCalledWith({ + where: { id: "test-product-id" }, + data: { + name: "업데이트된 상품", + description: "업데이트된 설명", + price: 150, + }, + include: { images: true }, + }); + }); + + test("이미지 URL이 없는 경우 상품을 업데이트한다", async () => { + ( + prisma.product.findUniqueOrThrow as jest.MockedFunction + ).mockResolvedValue(mockProduct); + (prisma.product.update as jest.MockedFunction).mockResolvedValue(mockProduct); + + const result = await updateProduct( + "test-product-id", + 1, + { + name: "업데이트된 상품", + description: "업데이트된 설명", + price: 150, + }, + "" + ); + + expect(result).toEqual(mockProduct); + expect(prisma.product.findUniqueOrThrow).toHaveBeenCalledWith({ + where: { id: "test-product-id" }, + include: { images: true }, + }); + + expect(prisma.image.update).not.toHaveBeenCalled(); + expect(prisma.image.create).not.toHaveBeenCalled(); + + expect(prisma.product.update).toHaveBeenCalledWith({ + where: { id: "test-product-id" }, + data: { + name: "업데이트된 상품", + description: "업데이트된 설명", + price: 150, + }, + include: { images: true }, + }); + }); + + test("존재하지 않는 상품을 업데이트하려고 하면 예외를 발생시킨다", async () => { + ( + prisma.product.findUniqueOrThrow as jest.MockedFunction + ).mockRejectedValue(new AppError("존재하지 않는 상품입니다.", 404)); + + await expect( + updateProduct( + "non-existent-product-id", + 1, + { + name: "업데이트된 상품", + description: "업데이트된 설명", + price: 150, + }, + "image1.jpg" + ) + ).rejects.toThrow("존재하지 않는 상품입니다."); + }); + + test("기존 이미지가 없는 경우 이미지를 생성한다", async () => { + const mockProductWithoutImage = { ...mockProduct, images: [] }; + ( + prisma.product.findUniqueOrThrow as jest.MockedFunction + ).mockResolvedValue(mockProductWithoutImage); + (prisma.product.update as jest.MockedFunction).mockResolvedValue(mockProduct); + (prisma.image.create as jest.MockedFunction).mockResolvedValue(mockImage); + + const result = await updateProduct( + "test-product-id", + 1, + { + name: "업데이트된 상품", + description: "업데이트된 설명", + price: 150, + }, + "image1.jpg" + ); + + expect(result).toEqual(mockProduct); + expect(prisma.product.findUniqueOrThrow).toHaveBeenCalledWith({ + where: { id: "test-product-id" }, + include: { images: true }, + }); + + expect(prisma.image.update).not.toHaveBeenCalled(); + expect(prisma.image.create).toHaveBeenCalledWith({ + data: { + imagePath: "image1.jpg", + product: { connect: { id: "test-product-id" } }, + }, + }); + + expect(prisma.product.update).toHaveBeenCalledWith({ + where: { id: "test-product-id" }, + data: { + name: "업데이트된 상품", + description: "업데이트된 설명", + price: 150, + }, + include: { images: true }, + }); + }); + + test("상품을 삭제한다", async () => { + (prisma.product.findUnique as jest.MockedFunction).mockResolvedValueOnce( + mockProduct + ); + (prisma.product.delete as jest.MockedFunction).mockResolvedValue(mockProduct); + (prisma.product.findUnique as jest.MockedFunction).mockResolvedValueOnce(null); + + await deleteProduct("test-product-id", 1); + + expect(prisma.product.findUnique).toHaveBeenCalledWith({ + where: { id: "test-product-id" }, + }); + + expect(prisma.product.delete).toHaveBeenCalledWith({ + where: { id: "test-product-id" }, + }); + + expect(prisma.product.findUnique).toHaveBeenCalledWith({ + where: { id: "test-product-id" }, + }); + + expect(await prisma.product.findUnique({ where: { id: "test-product-id" } })).toBeNull(); + }); + + test("존재하지 않는 상품을 삭제하려고 하면 예외를 발생시킨다", async () => { + (prisma.product.findUnique as jest.MockedFunction).mockResolvedValue(null); + await expect(deleteProduct("non-existent-product-id", 1)).rejects.toThrow("존재하지 않는 상품입니다."); + }); + + test("상품을 삭제할 권한이 없으면 예외를 발생시킨다", async () => { + const anotherUserProduct = { ...mockProduct, userId: 2 }; + (prisma.product.findUnique as jest.MockedFunction).mockResolvedValue( + anotherUserProduct + ); + + await expect(deleteProduct("test-product-id", 1)).rejects.toThrow("상품을 삭제할 권한이 없습니다."); + }); + + test("상품에 좋아요를 누른다", async () => { + const updatedProduct = { ...mockProduct, favoriteCount: mockProduct.favoriteCount + 1 }; + (prisma.favorite.findUnique as jest.MockedFunction).mockResolvedValue(null); + (prisma.product.update as jest.MockedFunction).mockResolvedValue(updatedProduct); + (prisma.$transaction as jest.MockedFunction).mockResolvedValue([null, updatedProduct]); + + const result = await likeProduct("test-product-id", 1); + expect(result).toEqual(updatedProduct); + expect(result.favoriteCount).toBe(mockProduct.favoriteCount + 1); + expect(prisma.favorite.findUnique).toHaveBeenCalledWith({ + where: { + userId_productId: { + userId: 1, + productId: "test-product-id", + }, + }, + }); + expect(prisma.$transaction).toHaveBeenCalled(); + }); + + test("이미 좋아요가 된 상품에 좋아요를 누를 경우 에러를 반환한다", async () => { + (prisma.favorite.findUnique as jest.MockedFunction).mockResolvedValue( + mockFavorite + ); + + await expect(likeProduct("test-product-id", 1)).rejects.toThrow("이미 좋아요 처리된 상품입니다."); + expect(prisma.favorite.findUnique).toHaveBeenCalledWith({ + where: { + userId_productId: { + userId: 1, + productId: "test-product-id", + }, + }, + }); + }); + + test("상품에 좋아요를 취소한다", async () => { + const updatedProduct = { ...mockProduct, favoriteCount: mockProduct.favoriteCount - 1 }; + (prisma.favorite.findUnique as jest.MockedFunction).mockResolvedValue( + mockFavorite + ); + (prisma.product.update as jest.MockedFunction).mockResolvedValue(updatedProduct); + (prisma.$transaction as jest.MockedFunction).mockResolvedValue([null, updatedProduct]); + + const result = await unlikeProduct("test-product-id", 1); + expect(result).toEqual(updatedProduct); + expect(result.favoriteCount).toBe(mockProduct.favoriteCount - 1); + expect(prisma.favorite.findUnique).toHaveBeenCalledWith({ + where: { + userId_productId: { + userId: 1, + productId: "test-product-id", + }, + }, + }); + expect(prisma.$transaction).toHaveBeenCalled(); + }); + + test("좋아요가 취소된 상품을 다시 취소하려고 할 경우 에러를 반환한다", async () => { + (prisma.favorite.findUnique as jest.MockedFunction).mockResolvedValue(null); + + await expect(unlikeProduct("test-product-id", 1)).rejects.toThrow("아직 좋아요 처리되지 않은 상품입니다."); + expect(prisma.favorite.findUnique).toHaveBeenCalledWith({ + where: { + userId_productId: { + userId: 1, + productId: "test-product-id", + }, + }, + }); + }); + + test("상품을 수정할 권한이 없으면 예외를 발생시킨다", async () => { + const anotherUserProduct = { ...mockProduct, userId: 2 }; + ( + prisma.product.findUniqueOrThrow as jest.MockedFunction + ).mockResolvedValue(anotherUserProduct); + + await expect( + updateProduct( + "test-product-id", + 1, + { + name: "업데이트된 상품", + description: "업데이트된 설명", + price: 150, + }, + "image1.jpg" + ) + ).rejects.toThrow("상품을 수정할 권한이 없습니다."); + }); +}); From 90113afab185760849306f32319ae73c4938953a Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Tue, 4 Jun 2024 07:11:59 +0900 Subject: [PATCH 45/60] =?UTF-8?q?[#M12]=20feat:=20auth=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=A1=9C=EC=A7=81=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/authController.ts | 35 +-- src/services/authService.ts | 5 +- src/test/authController.test.ts | 357 ++++++++++++++++++++++++++++++ src/test/authService.test.ts | 123 ++++++++++ src/test/tokens.test.ts | 29 +++ 5 files changed, 533 insertions(+), 16 deletions(-) create mode 100644 src/test/authController.test.ts create mode 100644 src/test/authService.test.ts create mode 100644 src/test/tokens.test.ts diff --git a/src/controllers/authController.ts b/src/controllers/authController.ts index 07a64e6..04e899c 100644 --- a/src/controllers/authController.ts +++ b/src/controllers/authController.ts @@ -1,33 +1,42 @@ import dotenv from "dotenv"; import { NextFunction, Request, Response } from "express"; import jwt from "jsonwebtoken"; -import { assert } from "superstruct"; +import { StructError, assert } from "superstruct"; import { createUser, findUserByEmail, findUserById, validatePassword } from "../services/authService"; import { CreateUser } from "../structs"; import { generateAccessToken, generateRefreshToken, regenerateRefreshToken } from "../utils/tokens"; - dotenv.config(); const JWT_SECRET = process.env.JWT_SECRET || "kingPanda"; - export const signUp = async (req: Request, res: Response) => { - const { email, password, name, nickname } = req.body; - assert(req.body, CreateUser); + try { + const { email, password, name, nickname } = req.body; + assert(req.body, CreateUser); - const existingUser = await findUserByEmail(email); + const existingUser = await findUserByEmail(email); - if (existingUser) { - res.status(400).json({ message: "이미 가입된 이메일입니다." }); - return; - } + if (existingUser) { + res.status(400).json({ message: "이미 가입된 이메일입니다." }); + return; + } - await createUser(email, password, name, nickname); + await createUser(email, password, name, nickname); - res.status(201).json({ message: "회원가입이 완료되었습니다." }); + res.status(201).json({ message: "회원가입이 완료되었습니다." }); + } catch (error) { + if (error instanceof StructError) { + res.status(400).json({ message: `잘못된 입력값입니다: ${error.message}` }); + return; + } + } }; - export const signIn = async (req: Request, res: Response) => { const { email, password } = req.body; + if (!email || !password) { + res.status(400).json({ message: "이메일과 비밀번호를 입력해주세요." }); + return; + } + const user = await findUserByEmail(email); if (!user || !user.password) { diff --git a/src/services/authService.ts b/src/services/authService.ts index 22dac30..b05a605 100644 --- a/src/services/authService.ts +++ b/src/services/authService.ts @@ -1,7 +1,6 @@ -import { Prisma, PrismaClient } from "@prisma/client"; +import { Prisma } from "@prisma/client"; import bcrypt from "bcrypt"; - -const prisma = new PrismaClient(); +import prisma from "../client"; export const createUser = async (email: string, password: string, name: string, nickname: string) => { const hashedPassword = await bcrypt.hash(password, 10); diff --git a/src/test/authController.test.ts b/src/test/authController.test.ts new file mode 100644 index 0000000..f4e8e20 --- /dev/null +++ b/src/test/authController.test.ts @@ -0,0 +1,357 @@ +import { describe, expect, jest, test } from "@jest/globals"; +import { Request, Response } from "express"; +import jwt from "jsonwebtoken"; +import { refreshToken, signIn, signUp } from "../controllers/authController"; +import { createUser, findUserByEmail, findUserById, validatePassword } from "../services/authService"; +import { generateAccessToken, generateRefreshToken, regenerateRefreshToken } from "../utils/tokens"; + +jest.mock("../services/authService"); +jest.mock("../utils/tokens"); +jest.mock("jsonwebtoken"); + +describe("Auth Controller - signIn", () => { + const setup = () => { + const req = { + body: { + email: "test@example.com", + password: "password", + }, + } as Request; + + const res = { + json: jest.fn(), + status: jest.fn().mockReturnThis(), + } as unknown as Response; + + return { req, res }; + }; + + test("성공적으로 로그인하면 토큰을 반환한다", async () => { + const mockUser = { + id: 1, + googleId: null, + email: "test@example.com", + name: null, + nickname: "", + image: null, + password: "hashedPassword", + createdAt: new Date(), + updatedAt: new Date(), + }; + + const { req, res } = setup(); + + (findUserByEmail as jest.MockedFunction).mockResolvedValue(mockUser); + (validatePassword as jest.MockedFunction).mockResolvedValue(true); + (generateAccessToken as jest.MockedFunction).mockReturnValue("accessToken"); + (generateRefreshToken as jest.MockedFunction).mockReturnValue("refreshToken"); + + await signIn(req, res); + + expect(findUserByEmail).toHaveBeenCalledWith("test@example.com"); + expect(validatePassword).toHaveBeenCalledWith("password", "hashedPassword"); + expect(generateAccessToken).toHaveBeenCalledWith(mockUser); + expect(generateRefreshToken).toHaveBeenCalledWith(mockUser); + expect(res.json).toHaveBeenCalledWith({ accessToken: "accessToken", refreshToken: "refreshToken" }); + }); + + test("비밀번호가 틀리면 401 상태 코드를 반환한다", async () => { + const { req, res } = setup(); + + const mockUser = { + id: 1, + googleId: null, + email: "test@example.com", + name: null, + nickname: "", + image: null, + password: "hashedPassword", + createdAt: new Date(), + updatedAt: new Date(), + }; + + (findUserByEmail as jest.MockedFunction).mockResolvedValue(mockUser); + (validatePassword as jest.MockedFunction).mockResolvedValue(false); + + await signIn(req, res); + + expect(res.status).toHaveBeenCalledWith(401); + expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 확인해주세요." }); + }); + + test("사용자가 존재하지 않으면 401 상태 코드를 반환한다", async () => { + const { req, res } = setup(); + + (findUserByEmail as jest.MockedFunction).mockResolvedValue(null); + + await signIn(req, res); + + expect(res.status).toHaveBeenCalledWith(401); + expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 확인해주세요." }); + }); + + test("입력된 이메일이 없으면 400 상태 코드를 반환한다", async () => { + const req = { + body: { + email: "", + password: "password", + }, + } as Request; + + const res = { + json: jest.fn(), + status: jest.fn().mockReturnThis(), + } as unknown as Response; + + await signIn(req, res); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 입력해주세요." }); + }); + + test("입력된 비밀번호가 없으면 400 상태 코드를 반환한다", async () => { + const req = { + body: { + email: "test@example.com", + password: "", + }, + } as Request; + + const res = { + json: jest.fn(), + status: jest.fn().mockReturnThis(), + } as unknown as Response; + + await signIn(req, res); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 입력해주세요." }); + }); +}); + +describe("Auth Controller - signUp", () => { + const mockUser = { + id: 1, + email: "test@example.com", + name: "Test User", + nickname: "testuser", + password: "hashedPassword", + googleId: null, + image: null, + createdAt: new Date(), + updatedAt: new Date(), + }; + + const setup = () => { + const req = { + body: { + email: "newuser@example.com", + password: "password", + name: "New User", + nickname: "newuser", + }, + } as Request; + + const res = { + json: jest.fn(), + status: jest.fn().mockReturnThis(), + } as unknown as Response; + + return { req, res }; + }; + + test("성공적으로 회원가입하면 201 상태 코드를 반환한다", async () => { + const { req, res } = setup(); + + (findUserByEmail as jest.MockedFunction).mockResolvedValue(null); + (createUser as jest.MockedFunction).mockResolvedValue(mockUser); + + await signUp(req, res); + + expect(res.status).toHaveBeenCalledWith(201); + expect(res.json).toHaveBeenCalledWith({ message: "회원가입이 완료되었습니다." }); + }); + + test("이미 존재하는 이메일로 회원가입하면 400 상태 코드를 반환한다", async () => { + const { req, res } = setup(); + + (findUserByEmail as jest.MockedFunction).mockResolvedValue(mockUser); + + await signUp(req, res); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith({ message: "이미 가입된 이메일입니다." }); + }); + + test("입력된 이메일이 없으면 400 상태 코드를 반환한다", async () => { + const req = { + body: { + email: "", + password: "password", + name: "New User", + nickname: "newuser", + }, + } as Request; + + const res = { + json: jest.fn(), + status: jest.fn().mockReturnThis(), + } as unknown as Response; + + await signUp(req, res); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith({ + message: '잘못된 입력값입니다: At path: email -- Expected a value of type `Email`, but received: `""`', + }); + }); + + test("입력된 비밀번호가 없으면 400 상태 코드를 반환한다", async () => { + const req = { + body: { + email: "newuser@example.com", + password: "", + name: "New User", + nickname: "newuser", + }, + } as Request; + + const res = { + json: jest.fn(), + status: jest.fn().mockReturnThis(), + } as unknown as Response; + + await signUp(req, res); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith({ + message: + "잘못된 입력값입니다: At path: password -- Expected a string with a length between `1` and `32` but received one with a length of `0`", + }); + }); + + test("입력된 이름이 없으면 400 상태 코드를 반환한다", async () => { + const req = { + body: { + email: "newuser@example.com", + password: "password", + name: "", + nickname: "newuser", + }, + } as Request; + + const res = { + json: jest.fn(), + status: jest.fn().mockReturnThis(), + } as unknown as Response; + + await signUp(req, res); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith({ + message: + "잘못된 입력값입니다: At path: name -- Expected a string with a length between `1` and `16` but received one with a length of `0`", + }); + }); + + test("입력된 닉네임이 없으면 400 상태 코드를 반환한다", async () => { + const req = { + body: { + email: "newuser@example.com", + password: "password", + name: "New User", + nickname: "", + }, + } as Request; + + const res = { + json: jest.fn(), + status: jest.fn().mockReturnThis(), + } as unknown as Response; + + await signUp(req, res); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith({ + message: + "잘못된 입력값입니다: At path: nickname -- Expected a string with a length between `1` and `16` but received one with a length of `0`", + }); + }); +}); + +describe("Auth Controller - refreshToken", () => { + const setup = () => { + const req = { + body: { + refreshToken: "validRefreshToken", + }, + } as Request; + + const res = { + json: jest.fn(), + status: jest.fn().mockReturnThis(), + } as unknown as Response; + + return { req, res }; + }; + + const decodedToken = { userId: 1 }; + + test("유효한 refresh token으로 새로운 access token과 refresh token을 반환한다", async () => { + const mockUser = { + id: 1, + googleId: null, + email: "test@example.com", + name: null, + nickname: "testuser", + image: null, + password: null, + createdAt: new Date(), + updatedAt: new Date(), + }; + + const { req, res } = setup(); + + (jwt.verify as jest.MockedFunction).mockReturnValue(decodedToken as any); + (findUserById as jest.MockedFunction).mockResolvedValue(mockUser); + (generateAccessToken as jest.MockedFunction).mockReturnValue("newAccessToken"); + (regenerateRefreshToken as jest.MockedFunction).mockReturnValue("newRefreshToken"); + + await refreshToken(req, res); + + expect(jwt.verify).toHaveBeenCalledWith("newRefreshToken", "kingPanda"); + expect(findUserById).toHaveBeenCalledWith(1); + expect(generateAccessToken).toHaveBeenCalledWith(mockUser); + expect(regenerateRefreshToken).toHaveBeenCalledWith("validRefreshToken"); + expect(res.json).toHaveBeenCalledWith({ accessToken: "newAccessToken", refreshToken: "newRefreshToken" }); + }); + + test("유효하지 않은 refresh token으로 401 상태 코드를 반환한다", async () => { + const { req, res } = setup(); + + (jwt.verify as jest.MockedFunction).mockImplementation(() => { + throw new Error("Invalid token"); + }); + + await refreshToken(req, res); + + expect(res.status).toHaveBeenCalledWith(401); + expect(res.json).toHaveBeenCalledWith({ message: "유효하지 않은 토큰입니다." }); + }); + + test("refresh token이 없으면 401 상태 코드를 반환한다", async () => { + const req = { + body: {}, + } as Request; + + const res = { + json: jest.fn(), + status: jest.fn().mockReturnThis(), + } as unknown as Response; + + await refreshToken(req, res); + + expect(res.status).toHaveBeenCalledWith(401); + expect(res.json).toHaveBeenCalledWith({ message: "토큰은 필수값입니다." }); + }); +}); diff --git a/src/test/authService.test.ts b/src/test/authService.test.ts new file mode 100644 index 0000000..41024c2 --- /dev/null +++ b/src/test/authService.test.ts @@ -0,0 +1,123 @@ +import { beforeEach, describe, expect, jest, test } from "@jest/globals"; +import { Prisma, User } from "@prisma/client"; +import bcrypt from "bcrypt"; +import prisma from "../client"; +import { createUser, findUserByEmail, findUserById, validatePassword } from "../services/authService"; + +// [ ] 토큰 주는지도 테스트해야되나? + +jest.mock("../client", () => ({ + __esModule: true, + default: { + user: { + create: jest.fn(), + findUnique: jest.fn(), + }, + }, +})); + +jest.mock("bcrypt", () => ({ + hash: jest.fn(), + compare: jest.fn(), +})); + +describe("회원가입, 로그인", () => { + const mockUser: User = { + id: 1, + googleId: null, + email: "test@example.com", + name: "테스트 유저", + nickname: "testuser", + image: null, + password: "hashedPassword", + createdAt: new Date(), + updatedAt: new Date(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + test("사용자를 생성한다", async () => { + (bcrypt.hash as jest.MockedFunction<(a: string, b: number) => Promise>).mockResolvedValue("hashedPassword"); + (prisma.user.create as jest.MockedFunction).mockResolvedValue(mockUser); + + const result = await createUser("test@example.com", "password", "Test User", "testuser"); + + expect(result).toEqual(mockUser); + expect(bcrypt.hash).toHaveBeenCalledWith("password", 10); + expect(prisma.user.create).toHaveBeenCalledWith({ + data: { + email: "test@example.com", + password: "hashedPassword", + name: "Test User", + nickname: "testuser", + }, + }); + }); + + test("이미 존재하는 이메일로 사용자를 생성하려고 하면 예외를 발생시킨다", async () => { + (bcrypt.hash as jest.MockedFunction<(a: string, b: number) => Promise>).mockResolvedValue("hashedPassword"); + (prisma.user.create as jest.MockedFunction).mockRejectedValue( + new Prisma.PrismaClientKnownRequestError("이미 존재하는 이메일입니다.", { + code: "P2002", + clientVersion: "3.0.0", + }) + ); + + await expect(createUser("test@example.com", "password", "Test User", "testuser")).rejects.toThrow( + "이미 존재하는 이메일입니다." + ); + }); + + test("다른 예외가 발생하면 예외를 다시 발생시킨다", async () => { + (bcrypt.hash as jest.MockedFunction<(a: string, b: number) => Promise>).mockResolvedValue("hashedPassword"); + (prisma.user.create as jest.MockedFunction).mockRejectedValue( + new Error("Database connection error") + ); + + await expect(createUser("test@example.com", "password", "Test User", "testuser")).rejects.toThrow( + "Database connection error" + ); + }); + + test("이메일로 사용자를 찾는다", async () => { + (prisma.user.findUnique as jest.MockedFunction).mockResolvedValue(mockUser); + + const result = await findUserByEmail("test@example.com"); + + expect(result).toEqual(mockUser); + expect(prisma.user.findUnique).toHaveBeenCalledWith({ + where: { email: "test@example.com" }, + }); + }); + + test("ID로 사용자를 찾는다", async () => { + (prisma.user.findUnique as jest.MockedFunction).mockResolvedValue(mockUser); + + const result = await findUserById(1); + + expect(result).toEqual(mockUser); + expect(prisma.user.findUnique).toHaveBeenCalledWith({ + where: { id: 1 }, + }); + }); + + test("비밀번호를 검증한다", async () => { + (bcrypt.compare as jest.MockedFunction<(a: string, b: string) => Promise>).mockResolvedValue(true); + + const result = await validatePassword("inputPassword", "hashedPassword"); + + expect(result).toBe(true); + expect(bcrypt.compare).toHaveBeenCalledWith("inputPassword", "hashedPassword"); + }); + + test("잘못된 비밀번호를 검증한다", async () => { + (bcrypt.compare as jest.MockedFunction<(a: string, b: string) => Promise>).mockResolvedValue(false); + + const result = await validatePassword("wrongPassword", "hashedPassword"); + + expect(result).toBe(false); + expect(bcrypt.compare).toHaveBeenCalledWith("wrongPassword", "hashedPassword"); + }); +}); diff --git a/src/test/tokens.test.ts b/src/test/tokens.test.ts new file mode 100644 index 0000000..cbc411c --- /dev/null +++ b/src/test/tokens.test.ts @@ -0,0 +1,29 @@ +import { describe, expect, jest, test } from "@jest/globals"; +import jwt from "jsonwebtoken"; +import { generateAccessToken, generateRefreshToken } from "../utils/tokens"; + +jest.mock("jsonwebtoken"); + +describe("Tokens Utility", () => { + const mockUser = { id: 1 }; + + const secret = "kingPanda"; + + test("access token을 생성한다", () => { + (jwt.sign as jest.MockedFunction).mockImplementation(() => "accessToken"); + + const token = generateAccessToken(mockUser); + + expect(jwt.sign).toHaveBeenCalledWith({ userId: mockUser.id }, secret, { expiresIn: "15m" }); + expect(token).toBe("accessToken"); + }); + + test("refresh token을 생성한다", () => { + (jwt.sign as jest.MockedFunction).mockImplementation(() => "refreshToken"); + + const token = generateRefreshToken(mockUser); + + expect(jwt.sign).toHaveBeenCalledWith({ userId: mockUser.id }, secret, { expiresIn: "7d" }); + expect(token).toBe("refreshToken"); + }); +}); From 4c5daf9be76e936e64e3cc2efb6b3cb1f8c26edb Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Wed, 5 Jun 2024 15:27:53 +0900 Subject: [PATCH 46/60] =?UTF-8?q?[#M12]=20feat=20:=20structs=20=EB=B0=8F?= =?UTF-8?q?=20tokens=20=EA=B4=80=EB=A0=A8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - auth 관련 로직 테스트의 커버리지를 높임 --- http/auth.http | 2 +- src/controllers/authController.ts | 24 +- src/middlewares/authenticate.ts | 6 +- src/test/authController.test.ts | 400 +++++++++++++++++------------- src/test/authService.test.ts | 2 - src/test/structs.test.ts | 147 +++++++++++ src/test/tokens.test.ts | 31 ++- src/types/express/index.d.ts | 8 +- 8 files changed, 438 insertions(+), 182 deletions(-) create mode 100644 src/test/structs.test.ts diff --git a/http/auth.http b/http/auth.http index 821ff0c..58e69e9 100644 --- a/http/auth.http +++ b/http/auth.http @@ -25,5 +25,5 @@ POST http://localhost:3000/auth/refresh-token Content-Type: application/json { - "refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODQ4MSwiZXhwIjoxNzE3NzMzMjgxfQ.d-h8rnnuG-lmptA_0ztr4XBDd45c32f73oWGGe_Rsak" + "refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzQ1NjM1MywiZXhwIjoxNzE4MDYxMTUzfQ.DiX7xqEs5maByaq_RhGt382Xde4ILk9rXk95mtOraIE" } \ No newline at end of file diff --git a/src/controllers/authController.ts b/src/controllers/authController.ts index 04e899c..e18f73b 100644 --- a/src/controllers/authController.ts +++ b/src/controllers/authController.ts @@ -5,8 +5,11 @@ import { StructError, assert } from "superstruct"; import { createUser, findUserByEmail, findUserById, validatePassword } from "../services/authService"; import { CreateUser } from "../structs"; import { generateAccessToken, generateRefreshToken, regenerateRefreshToken } from "../utils/tokens"; + dotenv.config(); + const JWT_SECRET = process.env.JWT_SECRET || "kingPanda"; + export const signUp = async (req: Request, res: Response) => { try { const { email, password, name, nickname } = req.body; @@ -24,11 +27,27 @@ export const signUp = async (req: Request, res: Response) => { res.status(201).json({ message: "회원가입이 완료되었습니다." }); } catch (error) { if (error instanceof StructError) { - res.status(400).json({ message: `잘못된 입력값입니다: ${error.message}` }); - return; + const errorMessages = new Set(); + const uniqueFailures = []; + + for (const failure of error.failures()) { + const errorMessage = JSON.stringify({ path: failure.path.join("."), message: failure.message }); + if (!errorMessages.has(errorMessage)) { + errorMessages.add(errorMessage); + uniqueFailures.push({ path: failure.path.join("."), message: failure.message }); + } + } + + res.status(400).json({ + message: "유효성 검사 오류입니다.", + errors: uniqueFailures, + }); + } else { + res.status(500).json({ message: "서버 에러입니다." }); } } }; + export const signIn = async (req: Request, res: Response) => { const { email, password } = req.body; @@ -68,6 +87,7 @@ export const refreshToken = async (req: Request, res: Response) => { try { const newRefreshToken = regenerateRefreshToken(refreshToken); const decoded = jwt.verify(newRefreshToken, JWT_SECRET) as { userId: number }; + req.user = { _id: decoded.userId }; const user = await findUserById(decoded.userId); if (!user) { diff --git a/src/middlewares/authenticate.ts b/src/middlewares/authenticate.ts index aaaf14d..55eb0a6 100644 --- a/src/middlewares/authenticate.ts +++ b/src/middlewares/authenticate.ts @@ -6,10 +6,6 @@ dotenv.config(); const JWT_SECRET = process.env.JWT_SECRET || "your_secret_key"; -export interface UserRequest extends Request { - userId: number; -} - const authenticate: RequestHandler = (req: Request, res: Response, next: NextFunction): void => { const authHeader = req.headers.authorization; if (!authHeader) { @@ -21,7 +17,7 @@ const authenticate: RequestHandler = (req: Request, res: Response, next: NextFun try { const decoded = jwt.verify(token, JWT_SECRET) as { userId: number }; - (req as UserRequest).userId = decoded.userId; + req.user = { _id: decoded.userId }; // 기존 _id를 userId로 설정 next(); } catch (error) { res.status(401).json({ message: "올바르지 않은 토큰입니다." }); diff --git a/src/test/authController.test.ts b/src/test/authController.test.ts index f4e8e20..b6974ea 100644 --- a/src/test/authController.test.ts +++ b/src/test/authController.test.ts @@ -1,20 +1,38 @@ import { describe, expect, jest, test } from "@jest/globals"; -import { Request, Response } from "express"; +import dotenv from "dotenv"; +import { NextFunction, Request, Response } from "express"; import jwt from "jsonwebtoken"; -import { refreshToken, signIn, signUp } from "../controllers/authController"; +import { StructError, assert } from "superstruct"; +import { googleCallback, refreshToken, signIn, signUp } from "../controllers/authController"; import { createUser, findUserByEmail, findUserById, validatePassword } from "../services/authService"; import { generateAccessToken, generateRefreshToken, regenerateRefreshToken } from "../utils/tokens"; +interface JWTPayload { + userId: number; +} + +dotenv.config(); +const JWT_SECRET = process.env.JWT_SECRET || "kingPanda"; + jest.mock("../services/authService"); jest.mock("../utils/tokens"); jest.mock("jsonwebtoken"); +jest.mock("superstruct", () => { + const originalModule = jest.requireActual("superstruct"); + return { + ...originalModule, + assert: jest.fn(), + }; +}); -describe("Auth Controller - signIn", () => { +describe("Auth Controller - 회원가입", () => { const setup = () => { const req = { body: { - email: "test@example.com", + email: "newuser@example.com", password: "password", + name: "New User", + nickname: "newuser", }, } as Request; @@ -26,129 +44,134 @@ describe("Auth Controller - signIn", () => { return { req, res }; }; - test("성공적으로 로그인하면 토큰을 반환한다", async () => { - const mockUser = { - id: 1, - googleId: null, - email: "test@example.com", - name: null, - nickname: "", - image: null, - password: "hashedPassword", - createdAt: new Date(), - updatedAt: new Date(), + test("유효성 검사 오류가 발생하면 400 상태 코드를 반환한다", async () => { + const { req, res } = setup(); + + req.body.email = ""; + + const failure = { + type: "email", + value: req.body.email, + key: "email", + branch: [req.body], + path: ["email"], + refinement: undefined, + message: "Invalid email format", }; - const { req, res } = setup(); + const structError = new StructError(failure, function* () { + yield failure; + }); - (findUserByEmail as jest.MockedFunction).mockResolvedValue(mockUser); - (validatePassword as jest.MockedFunction).mockResolvedValue(true); - (generateAccessToken as jest.MockedFunction).mockReturnValue("accessToken"); - (generateRefreshToken as jest.MockedFunction).mockReturnValue("refreshToken"); + (assert as jest.Mock).mockImplementation(() => { + throw structError; + }); - await signIn(req, res); + await signUp(req, res); - expect(findUserByEmail).toHaveBeenCalledWith("test@example.com"); - expect(validatePassword).toHaveBeenCalledWith("password", "hashedPassword"); - expect(generateAccessToken).toHaveBeenCalledWith(mockUser); - expect(generateRefreshToken).toHaveBeenCalledWith(mockUser); - expect(res.json).toHaveBeenCalledWith({ accessToken: "accessToken", refreshToken: "refreshToken" }); + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith({ + message: "유효성 검사 오류입니다.", + errors: [{ path: "email", message: "Invalid email format" }], + }); }); - test("비밀번호가 틀리면 401 상태 코드를 반환한다", async () => { + test("이미 존재하는 이메일로 회원가입하면 400 상태 코드를 반환한다", async () => { const { req, res } = setup(); - + (assert as jest.Mock).mockImplementation(() => {}); const mockUser = { id: 1, googleId: null, - email: "test@example.com", + email: "asdf@example.com", name: null, - nickname: "", + nickname: "existinguser", image: null, - password: "hashedPassword", + password: null, createdAt: new Date(), updatedAt: new Date(), }; (findUserByEmail as jest.MockedFunction).mockResolvedValue(mockUser); - (validatePassword as jest.MockedFunction).mockResolvedValue(false); - await signIn(req, res); + await signUp(req, res); - expect(res.status).toHaveBeenCalledWith(401); - expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 확인해주세요." }); + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith({ message: "이미 가입된 이메일입니다." }); }); - test("사용자가 존재하지 않으면 401 상태 코드를 반환한다", async () => { + test("StructError가 발생하면 400 상태 코드를 반환한다", async () => { const { req, res } = setup(); - (findUserByEmail as jest.MockedFunction).mockResolvedValue(null); - - await signIn(req, res); - - expect(res.status).toHaveBeenCalledWith(401); - expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 확인해주세요." }); - }); + const failure = { + type: "email", + value: req.body.email, + key: "email", + branch: [req.body], + path: ["email"], + refinement: undefined, + message: "Invalid email format", + }; - test("입력된 이메일이 없으면 400 상태 코드를 반환한다", async () => { - const req = { - body: { - email: "", - password: "password", - }, - } as Request; + const structError = new StructError(failure, function* () { + yield failure; + }); - const res = { - json: jest.fn(), - status: jest.fn().mockReturnThis(), - } as unknown as Response; + (assert as jest.Mock).mockImplementation(() => { + throw structError; + }); - await signIn(req, res); + await signUp(req, res); expect(res.status).toHaveBeenCalledWith(400); - expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 입력해주세요." }); + expect(res.json).toHaveBeenCalledWith({ + message: "유효성 검사 오류입니다.", + errors: [{ path: "email", message: "Invalid email format" }], + }); }); - test("입력된 비밀번호가 없으면 400 상태 코드를 반환한다", async () => { - const req = { - body: { - email: "test@example.com", - password: "", - }, - } as Request; + test("일반적인 오류가 발생하면 500 상태 코드를 반환한다", async () => { + const { req, res } = setup(); + (assert as jest.Mock).mockImplementation(() => {}); + (findUserByEmail as jest.MockedFunction).mockResolvedValue(null); + (createUser as jest.MockedFunction).mockImplementation(() => { + throw new Error("Database error"); + }); - const res = { - json: jest.fn(), - status: jest.fn().mockReturnThis(), - } as unknown as Response; + await signUp(req, res); - await signIn(req, res); + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ message: "서버 에러입니다." }); + }); - expect(res.status).toHaveBeenCalledWith(400); - expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 입력해주세요." }); + test("성공적으로 회원가입하면 201 상태 코드를 반환한다", async () => { + const { req, res } = setup(); + (assert as jest.Mock).mockImplementation(() => {}); + (findUserByEmail as jest.MockedFunction).mockResolvedValue(null); + (createUser as jest.MockedFunction).mockResolvedValue({ + id: 1, + email: req.body.email, + name: req.body.name, + nickname: req.body.nickname, + password: req.body.password, + googleId: null, + image: null, + createdAt: new Date(), + updatedAt: new Date(), + }); + + await signUp(req, res); + + expect(res.status).toHaveBeenCalledWith(201); + expect(res.json).toHaveBeenCalledWith({ message: "회원가입이 완료되었습니다." }); }); }); -describe("Auth Controller - signUp", () => { - const mockUser = { - id: 1, - email: "test@example.com", - name: "Test User", - nickname: "testuser", - password: "hashedPassword", - googleId: null, - image: null, - createdAt: new Date(), - updatedAt: new Date(), - }; - +describe("Auth Controller - signIn", () => { const setup = () => { const req = { body: { - email: "newuser@example.com", + email: "test@example.com", password: "password", - name: "New User", - nickname: "newuser", }, } as Request; @@ -160,59 +183,75 @@ describe("Auth Controller - signUp", () => { return { req, res }; }; - test("성공적으로 회원가입하면 201 상태 코드를 반환한다", async () => { + test("성공적으로 로그인하면 토큰을 반환한다", async () => { + const mockUser = { + id: 1, + email: "test@example.com", + password: "hashedPassword", + createdAt: new Date(), + updatedAt: new Date(), + googleId: null, + name: null, + nickname: "", + image: null, + }; + const { req, res } = setup(); - (findUserByEmail as jest.MockedFunction).mockResolvedValue(null); - (createUser as jest.MockedFunction).mockResolvedValue(mockUser); + (findUserByEmail as jest.MockedFunction).mockResolvedValue(mockUser); + (validatePassword as jest.MockedFunction).mockResolvedValue(true); + (generateAccessToken as jest.MockedFunction).mockReturnValue("accessToken"); + (generateRefreshToken as jest.MockedFunction).mockReturnValue("refreshToken"); - await signUp(req, res); + await signIn(req, res); - expect(res.status).toHaveBeenCalledWith(201); - expect(res.json).toHaveBeenCalledWith({ message: "회원가입이 완료되었습니다." }); + expect(findUserByEmail).toHaveBeenCalledWith("test@example.com"); + expect(validatePassword).toHaveBeenCalledWith("password", "hashedPassword"); + expect(generateAccessToken).toHaveBeenCalledWith(mockUser); + expect(generateRefreshToken).toHaveBeenCalledWith(mockUser); + expect(res.json).toHaveBeenCalledWith({ accessToken: "accessToken", refreshToken: "refreshToken" }); }); - test("이미 존재하는 이메일로 회원가입하면 400 상태 코드를 반환한다", async () => { + test("비밀번호가 틀리면 401 상태 코드를 반환한다", async () => { const { req, res } = setup(); + const mockUser = { + id: 1, + email: "test@example.com", + password: "hashedPassword", + createdAt: new Date(), + updatedAt: new Date(), + googleId: null, + name: null, + nickname: "", + image: null, + }; + (findUserByEmail as jest.MockedFunction).mockResolvedValue(mockUser); + (validatePassword as jest.MockedFunction).mockResolvedValue(false); - await signUp(req, res); + await signIn(req, res); - expect(res.status).toHaveBeenCalledWith(400); - expect(res.json).toHaveBeenCalledWith({ message: "이미 가입된 이메일입니다." }); + expect(res.status).toHaveBeenCalledWith(401); + expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 확인해주세요." }); }); - test("입력된 이메일이 없으면 400 상태 코드를 반환한다", async () => { - const req = { - body: { - email: "", - password: "password", - name: "New User", - nickname: "newuser", - }, - } as Request; + test("사용자가 존재하지 않으면 401 상태 코드를 반환한다", async () => { + const { req, res } = setup(); - const res = { - json: jest.fn(), - status: jest.fn().mockReturnThis(), - } as unknown as Response; + (findUserByEmail as jest.MockedFunction).mockResolvedValue(null); - await signUp(req, res); + await signIn(req, res); - expect(res.status).toHaveBeenCalledWith(400); - expect(res.json).toHaveBeenCalledWith({ - message: '잘못된 입력값입니다: At path: email -- Expected a value of type `Email`, but received: `""`', - }); + expect(res.status).toHaveBeenCalledWith(401); + expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 확인해주세요." }); }); - test("입력된 비밀번호가 없으면 400 상태 코드를 반환한다", async () => { + test("입력된 이메일이 없으면 400 상태 코드를 반환한다", async () => { const req = { body: { - email: "newuser@example.com", - password: "", - name: "New User", - nickname: "newuser", + email: "", + password: "password", }, } as Request; @@ -221,22 +260,17 @@ describe("Auth Controller - signUp", () => { status: jest.fn().mockReturnThis(), } as unknown as Response; - await signUp(req, res); + await signIn(req, res); expect(res.status).toHaveBeenCalledWith(400); - expect(res.json).toHaveBeenCalledWith({ - message: - "잘못된 입력값입니다: At path: password -- Expected a string with a length between `1` and `32` but received one with a length of `0`", - }); + expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 입력해주세요." }); }); - test("입력된 이름이 없으면 400 상태 코드를 반환한다", async () => { + test("입력된 비밀번호가 없으면 400 상태 코드를 반환한다", async () => { const req = { body: { - email: "newuser@example.com", - password: "password", - name: "", - nickname: "newuser", + email: "test@example.com", + password: "", }, } as Request; @@ -245,22 +279,17 @@ describe("Auth Controller - signUp", () => { status: jest.fn().mockReturnThis(), } as unknown as Response; - await signUp(req, res); + await signIn(req, res); expect(res.status).toHaveBeenCalledWith(400); - expect(res.json).toHaveBeenCalledWith({ - message: - "잘못된 입력값입니다: At path: name -- Expected a string with a length between `1` and `16` but received one with a length of `0`", - }); + expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 입력해주세요." }); }); - test("입력된 닉네임이 없으면 400 상태 코드를 반환한다", async () => { + test("입력된 이메일 형식이 유효하지 않으면 401 상태 코드를 반환한다", async () => { const req = { body: { - email: "newuser@example.com", + email: "invalid-email", password: "password", - name: "New User", - nickname: "", }, } as Request; @@ -269,13 +298,10 @@ describe("Auth Controller - signUp", () => { status: jest.fn().mockReturnThis(), } as unknown as Response; - await signUp(req, res); + await signIn(req, res); - expect(res.status).toHaveBeenCalledWith(400); - expect(res.json).toHaveBeenCalledWith({ - message: - "잘못된 입력값입니다: At path: nickname -- Expected a string with a length between `1` and `16` but received one with a length of `0`", - }); + expect(res.status).toHaveBeenCalledWith(401); + expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 확인해주세요." }); }); }); @@ -283,7 +309,7 @@ describe("Auth Controller - refreshToken", () => { const setup = () => { const req = { body: { - refreshToken: "validRefreshToken", + refreshToken: "validToken", }, } as Request; @@ -292,44 +318,40 @@ describe("Auth Controller - refreshToken", () => { status: jest.fn().mockReturnThis(), } as unknown as Response; - return { req, res }; - }; + const next = jest.fn() as NextFunction; - const decodedToken = { userId: 1 }; + return { req, res, next }; + }; - test("유효한 refresh token으로 새로운 access token과 refresh token을 반환한다", async () => { + test("유효한 토큰이면 새로운 액세스 토큰과 리프레시 토큰을 반환한다", async () => { + const { req, res } = setup(); const mockUser = { id: 1, - googleId: null, email: "test@example.com", - name: null, - nickname: "testuser", - image: null, - password: null, + password: "hashedPassword", createdAt: new Date(), updatedAt: new Date(), + googleId: null, + name: null, + nickname: "", + image: null, }; - const { req, res } = setup(); - - (jwt.verify as jest.MockedFunction).mockReturnValue(decodedToken as any); + (regenerateRefreshToken as jest.MockedFunction).mockReturnValue("validToken"); + (jwt.verify as jest.Mock).mockReturnValue({ userId: mockUser.id } as JWTPayload); (findUserById as jest.MockedFunction).mockResolvedValue(mockUser); (generateAccessToken as jest.MockedFunction).mockReturnValue("newAccessToken"); - (regenerateRefreshToken as jest.MockedFunction).mockReturnValue("newRefreshToken"); await refreshToken(req, res); - expect(jwt.verify).toHaveBeenCalledWith("newRefreshToken", "kingPanda"); - expect(findUserById).toHaveBeenCalledWith(1); - expect(generateAccessToken).toHaveBeenCalledWith(mockUser); - expect(regenerateRefreshToken).toHaveBeenCalledWith("validRefreshToken"); - expect(res.json).toHaveBeenCalledWith({ accessToken: "newAccessToken", refreshToken: "newRefreshToken" }); + expect(jwt.verify).toHaveBeenCalledWith("validToken", JWT_SECRET); + expect(res.json).toHaveBeenCalledWith({ accessToken: "newAccessToken", refreshToken: "validToken" }); }); - test("유효하지 않은 refresh token으로 401 상태 코드를 반환한다", async () => { + test("유효하지 않은 토큰이면 401 상태 코드를 반환한다", async () => { const { req, res } = setup(); - (jwt.verify as jest.MockedFunction).mockImplementation(() => { + (regenerateRefreshToken as jest.MockedFunction).mockImplementation(() => { throw new Error("Invalid token"); }); @@ -339,7 +361,7 @@ describe("Auth Controller - refreshToken", () => { expect(res.json).toHaveBeenCalledWith({ message: "유효하지 않은 토큰입니다." }); }); - test("refresh token이 없으면 401 상태 코드를 반환한다", async () => { + test("토큰이 없으면 401 상태 코드를 반환한다", async () => { const req = { body: {}, } as Request; @@ -354,4 +376,50 @@ describe("Auth Controller - refreshToken", () => { expect(res.status).toHaveBeenCalledWith(401); expect(res.json).toHaveBeenCalledWith({ message: "토큰은 필수값입니다." }); }); + + test("findUserById가 null을 반환하면 401 상태 코드를 반환한다", async () => { + const { req, res } = setup(); + + (regenerateRefreshToken as jest.MockedFunction).mockReturnValue("newRefreshToken"); + (jwt.verify as jest.Mock).mockReturnValue({ userId: 1 } as JWTPayload); + (findUserById as jest.MockedFunction).mockResolvedValue(null); + + await refreshToken(req, res); + + expect(res.status).toHaveBeenCalledWith(401); + expect(res.json).toHaveBeenCalledWith({ message: "유효하지 않은 토큰입니다." }); + }); +}); +describe("Auth Controller - googleCallback", () => { + const setup = () => { + const req = {} as Request; + const res = { + json: jest.fn(), + status: jest.fn().mockReturnThis(), + } as unknown as Response; + const next = jest.fn(); + + return { req, res, next }; + }; + + test("사용자 정보가 없으면 에러를 반환한다", () => { + const { req, res, next } = setup(); + + googleCallback(req, res, next); + + expect(next).toHaveBeenCalledWith(new Error("사용자 정보를 찾을 수 없습니다.")); + }); + + test("사용자 정보가 있으면 토큰을 반환한다", () => { + const { req, res, next } = setup(); + req.user = { + _id: 1, + accessToken: "accessToken", + refreshToken: "refreshToken", + }; + + googleCallback(req, res, next); + + expect(res.json).toHaveBeenCalledWith({ accessToken: "accessToken", refreshToken: "refreshToken" }); + }); }); diff --git a/src/test/authService.test.ts b/src/test/authService.test.ts index 41024c2..beca5b5 100644 --- a/src/test/authService.test.ts +++ b/src/test/authService.test.ts @@ -4,8 +4,6 @@ import bcrypt from "bcrypt"; import prisma from "../client"; import { createUser, findUserByEmail, findUserById, validatePassword } from "../services/authService"; -// [ ] 토큰 주는지도 테스트해야되나? - jest.mock("../client", () => ({ __esModule: true, default: { diff --git a/src/test/structs.test.ts b/src/test/structs.test.ts new file mode 100644 index 0000000..534ca7d --- /dev/null +++ b/src/test/structs.test.ts @@ -0,0 +1,147 @@ +import { describe, expect, jest, test } from "@jest/globals"; +import * as s from "superstruct"; +import { + CreateArticle, + CreateComment, + CreateProduct, + CreateUser, + PatchArticle, + PatchComment, + PatchProduct, +} from "../structs"; + +jest.mock("is-email", () => { + return jest.fn(() => true); +}); + +describe("구조체 유효성 검사", () => { + test("유효한 CreateProduct 객체를 검증한다", () => { + const validProduct = { + tags: ["tag1"], + price: 999, + description: "유효한 설명", + name: "유효한 제품 이름", + imageUrl: "http://example.com/image.jpg", + }; + + expect(() => s.assert(validProduct, CreateProduct)).not.toThrow(); + }); + + test("유효하지 않은 CreateProduct 객체를 검증한다", () => { + const invalidProduct = { + tags: [""], + price: -1, + description: "", + name: "", + }; + + expect(() => s.assert(invalidProduct, CreateProduct)).toThrow(); + }); + + test("유효한 PatchProduct 객체를 검증한다", () => { + const validPatch = { + price: 100, + }; + + expect(() => s.assert(validPatch, PatchProduct)).not.toThrow(); + }); + + test("유효하지 않은 PatchProduct 객체를 검증한다", () => { + const invalidPatch = { + price: -100, + }; + + expect(() => s.assert(invalidPatch, PatchProduct)).toThrow(); + }); + + test("유효한 CreateArticle 객체를 검증한다", () => { + const validArticle = { + title: "유효한 제목", + content: "유효한 내용", + imageUrl: "http://example.com/image.jpg", + writer: "작성자", + }; + + expect(() => s.assert(validArticle, CreateArticle)).not.toThrow(); + }); + + test("유효하지 않은 CreateArticle 객체를 검증한다", () => { + const invalidArticle = { + title: "", + content: "", + }; + + expect(() => s.assert(invalidArticle, CreateArticle)).toThrow(); + }); + + test("유효한 PatchArticle 객체를 검증한다", () => { + const validPatch = { + title: "유효한 제목", + }; + + expect(() => s.assert(validPatch, PatchArticle)).not.toThrow(); + }); + + test("유효하지 않은 PatchArticle 객체를 검증한다", () => { + const invalidPatch = { + title: "", + }; + + expect(() => s.assert(invalidPatch, PatchArticle)).toThrow(); + }); + + test("유효한 CreateComment 객체를 검증한다", () => { + const validComment = { + content: "유효한 내용", + writer: "댓글 작성자", + }; + + expect(() => s.assert(validComment, CreateComment)).not.toThrow(); + }); + + test("유효하지 않은 CreateComment 객체를 검증한다", () => { + const invalidComment = { + content: null, + }; + + expect(() => s.assert(invalidComment, CreateComment)).toThrow(); + }); + + test("유효한 PatchComment 객체를 검증한다", () => { + const validPatch = { + content: "유효한 내용", + }; + + expect(() => s.assert(validPatch, PatchComment)).not.toThrow(); + }); + + test("유효하지 않은 PatchComment 객체를 검증한다", () => { + const invalidPatch = { + content: null, + }; + + expect(() => s.assert(invalidPatch, PatchComment)).toThrow(); + }); + + test("유효한 CreateUser 객체를 검증한다", () => { + const validUser = { + email: "test@example.com", + password: "validpassword", + name: "유효한 이름", + nickname: "닉네임", + }; + + expect(() => s.assert(validUser, CreateUser)).not.toThrow(); + }); + + test("유효하지 않은 CreateUser 객체를 검증한다", () => { + const invalidUser = { + email: "invalid-email", + password: "", + name: "", + nickname: "", + }; + + expect(() => s.assert(invalidUser, CreateUser)).toThrow(); + }); +}); diff --git a/src/test/tokens.test.ts b/src/test/tokens.test.ts index cbc411c..ae35ac8 100644 --- a/src/test/tokens.test.ts +++ b/src/test/tokens.test.ts @@ -1,9 +1,11 @@ import { describe, expect, jest, test } from "@jest/globals"; import jwt from "jsonwebtoken"; -import { generateAccessToken, generateRefreshToken } from "../utils/tokens"; +import { generateAccessToken, generateRefreshToken, regenerateRefreshToken } from "../utils/tokens"; jest.mock("jsonwebtoken"); - +type JWTPayload = { + userId: number; +}; describe("Tokens Utility", () => { const mockUser = { id: 1 }; @@ -26,4 +28,29 @@ describe("Tokens Utility", () => { expect(jwt.sign).toHaveBeenCalledWith({ userId: mockUser.id }, secret, { expiresIn: "7d" }); expect(token).toBe("refreshToken"); }); + // 추가된 테스트 케이스: 유효한 리프레시 토큰을 사용하여 새로운 리프레시 토큰을 생성하는 경우 + + test("유효한 리프레시 토큰을 사용하여 새로운 리프레시 토큰을 생성한다", () => { + const refreshToken = "validRefreshToken"; + const decodedToken = { userId: mockUser.id }; + (jwt.verify as jest.Mock).mockReturnValue(decodedToken as JWTPayload); + (jwt.sign as jest.MockedFunction).mockImplementation(() => "newRefreshToken"); + + const token = regenerateRefreshToken(refreshToken); + + expect(jwt.verify).toHaveBeenCalledWith(refreshToken, secret); + expect(jwt.sign).toHaveBeenCalledWith({ userId: decodedToken.userId }, secret, { expiresIn: "7d" }); + expect(token).toBe("newRefreshToken"); + }); + + // 추가된 테스트 케이스: 유효하지 않은 리프레시 토큰으로 인해 오류가 발생하는 경우 + test("유효하지 않은 리프레시 토큰으로 인해 오류가 발생한다", () => { + const refreshToken = "invalidRefreshToken"; + + (jwt.verify as jest.MockedFunction).mockImplementation(() => { + throw new Error("Invalid token"); + }); + + expect(() => regenerateRefreshToken(refreshToken)).toThrow("Invalid refresh token"); + }); }); diff --git a/src/types/express/index.d.ts b/src/types/express/index.d.ts index f45b7f5..c335c80 100644 --- a/src/types/express/index.d.ts +++ b/src/types/express/index.d.ts @@ -1,9 +1,9 @@ declare namespace Express { interface User { - accessToken: string; - refreshToken: string; - username: string; - _id?: number; + _id: number; + accessToken?: string; + refreshToken?: string; + username?: string; } interface Request { From e6eaf22f528b7a059f6358315e957a081311acd7 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Wed, 5 Jun 2024 16:30:23 +0900 Subject: [PATCH 47/60] =?UTF-8?q?[#M12]=20feat=20:=20AWS=20S3=EC=9D=84=20?= =?UTF-8?q?=EC=9D=B4=EC=9A=A9=ED=95=9C=20=ED=8C=8C=EC=9D=BC=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EA=B5=AC?= =?UTF-8?q?=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 1917 +++++++++++++++++++++++++++- package.json | 4 + src/app.ts | 7 +- src/controllers/imageController.ts | 4 +- src/routes/imageRoutes.ts | 22 +- src/services/imageService.ts | 38 +- src/test/productService.test.ts | 40 +- src/types/express/index.d.ts | 4 + test.html | 19 +- yarn.lock | 1358 +++++++++++++++++++- 10 files changed, 3337 insertions(+), 76 deletions(-) diff --git a/package-lock.json b/package-lock.json index 689780e..256a95c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,7 +5,9 @@ "packages": { "": { "dependencies": { + "@aws-sdk/client-s3": "^3.590.0", "@prisma/client": "^5.4.2", + "aws-sdk": "^2.1634.0", "bcrypt": "^5.1.1", "dotenv": "^16.3.1", "express": "^4.18.2", @@ -15,6 +17,7 @@ "jsonwebtoken": "^9.0.2", "moment-timezone": "^0.5.45", "multer": "^1.4.5-lts.1", + "multer-s3": "^3.0.1", "passport": "^0.7.0", "passport-google-oauth20": "^2.0.0", "prisma": "^5.4.2", @@ -34,6 +37,7 @@ "@types/jsonwebtoken": "^9.0.6", "@types/morgan": "^1.9.9", "@types/multer": "^1.4.11", + "@types/multer-s3": "^3.0.3", "@types/node": "^20.12.13", "@types/passport": "^1.0.16", "@types/passport-google-oauth20": "^2.0.16", @@ -113,6 +117,847 @@ "openapi-types": ">=7" } }, + "node_modules/@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/crc32/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/crc32c": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz", + "integrity": "sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/crc32c/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/ie11-detection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/sha1-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz", + "integrity": "sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==", + "dependencies": { + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "dependencies": { + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/util/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.590.0.tgz", + "integrity": "sha512-so+pNua0ihsHaSdskw8HCwruoYTAfYSEs3ix4GD1++83C96KaJp3udAutYiCA+84JXg9zitFa7eK7ORJAVZmTw==", + "dependencies": { + "@aws-crypto/sha1-browser": "3.0.0", + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sso-oidc": "3.590.0", + "@aws-sdk/client-sts": "3.590.0", + "@aws-sdk/core": "3.588.0", + "@aws-sdk/credential-provider-node": "3.590.0", + "@aws-sdk/middleware-bucket-endpoint": "3.587.0", + "@aws-sdk/middleware-expect-continue": "3.577.0", + "@aws-sdk/middleware-flexible-checksums": "3.587.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-location-constraint": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-sdk-s3": "3.587.0", + "@aws-sdk/middleware-signing": "3.587.0", + "@aws-sdk/middleware-ssec": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/signature-v4-multi-region": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@aws-sdk/xml-builder": "3.575.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.1.1", + "@smithy/eventstream-serde-browser": "^3.0.0", + "@smithy/eventstream-serde-config-resolver": "^3.0.0", + "@smithy/eventstream-serde-node": "^3.0.0", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-blob-browser": "^3.0.0", + "@smithy/hash-node": "^3.0.0", + "@smithy/hash-stream-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/md5-js": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-stream": "^3.0.1", + "@smithy/util-utf8": "^3.0.0", + "@smithy/util-waiter": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.590.0.tgz", + "integrity": "sha512-6xbC6oQVJKBRTyXyR3C15ksUsPOyW4p+uCj7dlKYWGJvh4vGTV8KhZKS53oPG8t4f1+OMJWjr5wKuXRoaFsmhQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.588.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.1.1", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.590.0.tgz", + "integrity": "sha512-3yCLPjq6WFfDpdUJKk/gSz4eAPDTjVknXaveMPi2QoVBCshneOnJsV16uNKlpVF1frTHrrDRfKYmbaVh6nFBvQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.590.0", + "@aws-sdk/core": "3.588.0", + "@aws-sdk/credential-provider-node": "3.590.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.1.1", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.590.0.tgz", + "integrity": "sha512-f4R1v1LSn4uLYZ5qj4DyL6gp7PXXzJeJsm2seheiJX+53LSF5L7XSDnQVtX1p9Tevv0hp2YUWUTg6QYwIVSuGg==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sso-oidc": "3.590.0", + "@aws-sdk/core": "3.588.0", + "@aws-sdk/credential-provider-node": "3.590.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.1.1", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.588.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.588.0.tgz", + "integrity": "sha512-O1c2+9ce46Z+iiid+W3iC1IvPbfIo5ev9CBi54GdNB9SaI8/3+f8MJcux0D6c9toCF0ArMersN/gp8ek57e9uQ==", + "dependencies": { + "@smithy/core": "^2.1.1", + "@smithy/protocol-http": "^4.0.0", + "@smithy/signature-v4": "^3.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.587.0.tgz", + "integrity": "sha512-Hyg/5KFECIk2k5o8wnVEiniV86yVkhn5kzITUydmNGCkXdBFHMHRx6hleQ1bqwJHbBskyu8nbYamzcwymmGwmw==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.587.0.tgz", + "integrity": "sha512-Su1SRWVRCuR1e32oxX3C1V4c5hpPN20WYcRfdcr2wXwHqSvys5DrnmuCC+JoEnS/zt3adUJhPliTqpfKgSdMrA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/util-stream": "^3.0.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.590.0.tgz", + "integrity": "sha512-Y5cFciAK38VIvRgZeND7HvFNR32thGtQb8Xop6cMn33FC78uwcRIu9Hc9699XTclCZqz4+Xl1WU+dZ+rnFn2AA==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.587.0", + "@aws-sdk/credential-provider-http": "3.587.0", + "@aws-sdk/credential-provider-process": "3.587.0", + "@aws-sdk/credential-provider-sso": "3.590.0", + "@aws-sdk/credential-provider-web-identity": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@smithy/credential-provider-imds": "^3.1.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.590.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.590.0.tgz", + "integrity": "sha512-Ky38mNFoXobGrDQ11P3dU1e+q1nRJ7eZl8l15KUpvZCe/hOudbxQi/epQrCazD/gRYV2fTyczdLlZzB5ZZ8DhQ==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.587.0", + "@aws-sdk/credential-provider-http": "3.587.0", + "@aws-sdk/credential-provider-ini": "3.590.0", + "@aws-sdk/credential-provider-process": "3.587.0", + "@aws-sdk/credential-provider-sso": "3.590.0", + "@aws-sdk/credential-provider-web-identity": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@smithy/credential-provider-imds": "^3.1.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.587.0.tgz", + "integrity": "sha512-V4xT3iCqkF8uL6QC4gqBJg/2asd/damswP1h9HCfqTllmPWzImS+8WD3VjgTLw5b0KbTy+ZdUhKc0wDnyzkzxg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.590.0.tgz", + "integrity": "sha512-v+0j/I+je9okfwXsgmLppmwIE+TuMp5WqLz7r7PHz9KjzLyKaKTDvfllFD+8oPpBqnmOWiJ9qTGPkrfhB7a/fQ==", + "dependencies": { + "@aws-sdk/client-sso": "3.590.0", + "@aws-sdk/token-providers": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.587.0.tgz", + "integrity": "sha512-XqIx/I2PG7kyuw3WjAP9wKlxy8IvFJwB8asOFT1xPFoVfZYKIogjG9oLP5YiRtfvDkWIztHmg5MlVv3HdJDGRw==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.587.0" + } + }, + "node_modules/@aws-sdk/lib-storage": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.590.0.tgz", + "integrity": "sha512-GPR9Kg8N/wM3BCtsj/Bk8k9OIshGMdMmTWgVg+fdLnP5KHH+OMNfvF9aw7JHWjY5c9sM4wKYceBGWNLVSw+lPQ==", + "dependencies": { + "@smithy/abort-controller": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/smithy-client": "^3.1.1", + "buffer": "5.6.0", + "events": "3.3.0", + "stream-browserify": "3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-s3": "^3.590.0" + } + }, + "node_modules/@aws-sdk/lib-storage/node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/@aws-sdk/lib-storage/node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.587.0.tgz", + "integrity": "sha512-HkFXLPl8pr6BH/Q0JpOESqEKL0ZK3sk7aSZ1S6GE4RXET7H5R94THULXqQFZzD48gZcyFooO/yNKZTqrZFaWKg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-config-provider": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.577.0.tgz", + "integrity": "sha512-6dPp8Tv4F0of4un5IAyG6q++GrRrNQQ4P2NAMB1W0VO4JoEu1C8GievbbDLi88TFIFmtKpnHB0ODCzwnoe8JsA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.587.0.tgz", + "integrity": "sha512-URMwp/budDvKhIvZ4a6zIBfFTun/iDlPWXqsGKYjEtHt8jz27OSjCZtDtIeqW4WTBdKL8KZgQcl+DdaE5M1qiQ==", + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@aws-crypto/crc32c": "3.0.0", + "@aws-sdk/types": "3.577.0", + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.577.0.tgz", + "integrity": "sha512-9ca5MJz455CODIVXs0/sWmJm7t3QO4EUa1zf8pE8grLpzf0J94bz/skDWm37Pli13T3WaAQBHCTiH2gUVfCsWg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.577.0.tgz", + "integrity": "sha512-DKPTD2D2s+t2QUo/IXYtVa/6Un8GZ+phSTBkyBNx2kfZz4Kwavhl/JJzSqTV3GfCXkVdFu7CrjoX7BZ6qWeTUA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.577.0.tgz", + "integrity": "sha512-aPFGpGjTZcJYk+24bg7jT4XdIp42mFXSuPt49lw5KygefLyJM/sB0bKKqPYYivW0rcuZ9brQ58eZUNthrzYAvg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.577.0.tgz", + "integrity": "sha512-pn3ZVEd2iobKJlR3H+bDilHjgRnNrQ6HMmK9ZzZw89Ckn3Dcbv48xOv4RJvu0aU8SDLl/SNCxppKjeLDTPGBNA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.587.0.tgz", + "integrity": "sha512-vtXTGEiw1E9Fax4LmcU2Z208gbrC8ShrdsSLmGcRPpu5NPOGBFBSDG5sy5EDNClrFxIl/Le8coQnD0EDBtx+uQ==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/signature-v4": "^3.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/util-config-provider": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.587.0.tgz", + "integrity": "sha512-tiZaTDj4RvhXGRAlncFn7CSEfL3iNPO67WSaxAq+Ls5j1VgczPhu5262cWONNoMgth3nXR1hhLC4ITSl/a6AzA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/signature-v4": "^3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.577.0.tgz", + "integrity": "sha512-i2BPJR+rp8xmRVIGc0h1kDRFcM2J9GnClqqpc+NLSjmYadlcg4mPklisz9HzwFVcRPJ5XcGf3U4BYs5G8+iTyg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.587.0.tgz", + "integrity": "sha512-SyDomN+IOrygLucziG7/nOHkjUXES5oH5T7p8AboO8oakMQJdnudNXiYWTicQWO52R51U6CR27rcMPTGeMedYA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.587.0.tgz", + "integrity": "sha512-93I7IPZtulZQoRK+O20IJ4a1syWwYPzoO2gc3v+/GNZflZPV3QJXuVbIm0pxBsu0n/mzKGUKqSOLPIaN098HcQ==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.587.0.tgz", + "integrity": "sha512-TR9+ZSjdXvXUz54ayHcCihhcvxI9W7102J1OK6MrLgBlPE7uRhAx42BR9L5lLJ86Xj3LuqPWf//o9d/zR9WVIg==", + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/signature-v4": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.587.0.tgz", + "integrity": "sha512-ULqhbnLy1hmJNRcukANBWJmum3BbjXnurLPSFXoGdV0llXYlG55SzIla2VYqdveQEEjmsBuTZdFvXAtNpmS5Zg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sso-oidc": "^3.587.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.577.0.tgz", + "integrity": "sha512-FT2JZES3wBKN/alfmhlo+3ZOq/XJ0C7QOZcDNrpKjB0kqYoKjhVKZ/Hx6ArR0czkKfHzBBEs6y40ebIHx2nSmA==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz", + "integrity": "sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.587.0.tgz", + "integrity": "sha512-8I1HG6Em8wQWqKcRW6m358mqebRVNpL8XrrEoT4In7xqkKkmYtHRNVYP6lcmiQh5pZ/c/FXu8dSchuFIWyEtqQ==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "@smithy/util-endpoints": "^2.0.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz", + "integrity": "sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.577.0.tgz", + "integrity": "sha512-zEAzHgR6HWpZOH7xFgeJLc6/CzMcx4nxeQolZxVZoB5pPaJd3CjyRhZN0xXeZB0XIRCWmb4yJBgyiugXLNMkLA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.587.0.tgz", + "integrity": "sha512-Pnl+DUe/bvnbEEDHP3iVJrOtE3HbFJBPgsD6vJ+ml/+IYk1Eq49jEG+EHZdNTPz3SDG0kbp2+7u41MKYJHR/iQ==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.575.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.575.0.tgz", + "integrity": "sha512-cWgAwmbFYNCFzPwxL705+lWps0F3ZvOckufd2KKoEZUmtpVw9/txUXNrPySUXSmRTSRhoatIMABNfStWR043bQ==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.24.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz", @@ -2841,25 +3686,662 @@ "@prisma/debug": "5.14.0" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-p6GlFGBt9K4MYLu72YuJ523NVR4A8oHlC5M2JO6OmQqN8kAc/uh1JqLE+FizTokrSJGg0CSvC+BrsmGzKtsZKA==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-3.0.0.tgz", + "integrity": "sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz", + "integrity": "sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg==", + "dependencies": { + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.1.tgz", + "integrity": "sha512-hbkYJc20SBDz2qqLzttjI/EqXemtmWk0ooRznLsiXp3066KQRTvuKHa7U4jCZCJq6Dozqvy0R1/vNESC9inPJg==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.2.0.tgz", + "integrity": "sha512-ygLZSSKgt9bR8HAxR9mK+U5obvAJBr6zlQuhN5soYWx/amjDoQN4dTkydTypgKe6rIbUjTILyLU+W5XFwXr4kg==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.1.0.tgz", + "integrity": "sha512-q4A4d38v8pYYmseu/jTS3Z5I3zXlEOe5Obi+EJreVKgSVyWUHOd7/yaVCinC60QG4MRyCs98tcxBH1IMC0bu7Q==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.0.0.tgz", + "integrity": "sha512-PUtyEA0Oik50SaEFCZ0WPVtF9tz/teze2fDptW6WRXl+RrEenH8UbEjudOz8iakiMl3lE3lCVqYf2Y+znL8QFQ==", + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.0.tgz", + "integrity": "sha512-NB7AFiPN4NxP/YCAnrvYR18z2/ZsiHiF7VtG30gshO9GbFrIb1rC8ep4NGpJSWrz6P64uhPXeo4M0UsCLnZKqw==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.0.tgz", + "integrity": "sha512-RUQG3vQ3LX7peqqHAbmayhgrF5aTilPnazinaSGF1P0+tgM3vvIRWPHmlLIz2qFqB9LqFIxditxc8O2Z6psrRw==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.0.tgz", + "integrity": "sha512-baRPdMBDMBExZXIUAoPGm/hntixjt/VFpU6+VmCyiYJYzRHRxoaI1MN+5XE+hIS8AJ2GCHLMFEIOLzq9xx1EgQ==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.0.tgz", + "integrity": "sha512-HNFfShmotWGeAoW4ujP8meV9BZavcpmerDbPIjkJbxKbN8RsUcpRQ/2OyIxWNxXNH2GWCAxuSB7ynmIGJlQ3Dw==", + "dependencies": { + "@smithy/eventstream-codec": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.0.1.tgz", + "integrity": "sha512-uaH74i5BDj+rBwoQaXioKpI0SHBJFtOVwzrCpxZxphOW0ki5jhj7dXvDMYM2IJem8TpdFvS2iC08sjOblfFGFg==", + "dependencies": { + "@smithy/protocol-http": "^4.0.0", + "@smithy/querystring-builder": "^3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/hash-blob-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-3.0.0.tgz", + "integrity": "sha512-/Wbpdg+bwJvW7lxR/zpWAc1/x/YkcqguuF2bAzkJrvXriZu1vm8r+PUdE4syiVwQg7PPR2dXpi3CLBb9qRDaVQ==", + "dependencies": { + "@smithy/chunked-blob-reader": "^3.0.0", + "@smithy/chunked-blob-reader-native": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/hash-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.0.tgz", + "integrity": "sha512-84qXstNemP3XS5jcof0el6+bDfjzuvhJPQTEfro3lgtbCtKgzPm3MgiS6ehXVPjeQ5+JS0HqmTz8f/RYfzHVxw==", + "dependencies": { + "@smithy/types": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/hash-stream-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-3.0.0.tgz", + "integrity": "sha512-J0i7de+EgXDEGITD4fxzmMX8CyCNETTIRXlxjMiNUvvu76Xn3GJ31wQR85ynlPk2wI1lqoknAFJaD1fiNDlbIA==", + "dependencies": { + "@smithy/types": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.0.tgz", + "integrity": "sha512-F6wBBaEFgJzj0s4KUlliIGPmqXemwP6EavgvDqYwCH40O5Xr2iMHvS8todmGVZtuJCorBkXsYLyTu4PuizVq5g==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/md5-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-3.0.0.tgz", + "integrity": "sha512-Tm0vrrVzjlD+6RCQTx7D3Ls58S3FUH1ZCtU1MIh/qQmaOo1H9lMN2as6CikcEwgattnA9SURSdoJJ27xMcEfMA==", + "dependencies": { + "@smithy/types": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.0.tgz", + "integrity": "sha512-3C4s4d/iGobgCtk2tnWW6+zSTOBg1PRAm2vtWZLdriwTroFbbWNSr3lcyzHdrQHnEXYCC5K52EbpfodaIUY8sg==", + "dependencies": { + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.0.1.tgz", + "integrity": "sha512-lQ/UOdGD4KM5kLZiAl0q8Qy3dPbynvAXKAdXnYlrA1OpaUwr+neSsVokDZpY6ZVb5Yx8jnus29uv6XWpM9P4SQ==", + "dependencies": { + "@smithy/middleware-serde": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.3.tgz", + "integrity": "sha512-Wve1qzJb83VEU/6q+/I0cQdAkDnuzELC6IvIBwDzUEiGpKqXgX1v10FUuZGbRS6Ov/P+HHthcAoHOJZQvZNAkA==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/service-error-classification": "^3.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.0.tgz", + "integrity": "sha512-I1vKG1foI+oPgG9r7IMY1S+xBnmAn1ISqployvqkwHoSb8VPsngHDTOgYGYBonuOKndaWRUGJZrKYYLB+Ane6w==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.0.tgz", + "integrity": "sha512-+H0jmyfAyHRFXm6wunskuNAqtj7yfmwFB6Fp37enytp2q047/Od9xetEaUbluyImOlGnGpaVGaVfjwawSr+i6Q==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.0.tgz", + "integrity": "sha512-ngfB8QItUfTFTfHMvKuc2g1W60V1urIgZHqD1JNFZC2tTWXahqf2XvKXqcBS7yZqR7GqkQQZy11y/lNOUWzq7Q==", + "dependencies": { + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.0.0.tgz", + "integrity": "sha512-3trD4r7NOMygwLbUJo4eodyQuypAWr7uvPnebNJ9a70dQhVn+US8j/lCnvoJS6BXfZeF7PkkkI0DemVJw+n+eQ==", + "dependencies": { + "@smithy/abort-controller": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/querystring-builder": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.0.tgz", + "integrity": "sha512-Tj3+oVhqdZgemjCiWjFlADfhvLF4C/uKDuKo7/tlEsRQ9+3emCreR2xndj970QSRSsiCEU8hZW3/8JQu+n5w4Q==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.0.0.tgz", + "integrity": "sha512-qOQZOEI2XLWRWBO9AgIYuHuqjZ2csyr8/IlgFDHDNuIgLAMRx2Bl8ck5U5D6Vh9DPdoaVpuzwWMa0xcdL4O/AQ==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.0.tgz", + "integrity": "sha512-bW8Fi0NzyfkE0TmQphDXr1AmBDbK01cA4C1Z7ggwMAU5RDz5AAv/KmoRwzQAS0kxXNf/D2ALTEgwK0U2c4LtRg==", + "dependencies": { + "@smithy/types": "^3.0.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.0.tgz", + "integrity": "sha512-UzHwthk0UEccV4dHzPySnBy34AWw3V9lIqUTxmozQ+wPDAO9csCWMfOLe7V9A2agNYy7xE+Pb0S6K/J23JSzfQ==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.0.tgz", + "integrity": "sha512-3BsBtOUt2Gsnc3X23ew+r2M71WwtpHfEDGhHYHSDg6q1t8FrWh15jT25DLajFV1H+PpxAJ6gqe9yYeRUsmSdFA==", + "dependencies": { + "@smithy/types": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.0.tgz", + "integrity": "sha512-dAM7wSX0NR3qTNyGVN/nwwpEDzfV9T/3AN2eABExWmda5VqZKSsjlINqomO5hjQWGv+IIkoXfs3u2vGSNz8+Rg==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-3.0.0.tgz", + "integrity": "sha512-kXFOkNX+BQHe2qnLxpMEaCRGap9J6tUGLzc3A9jdn+nD4JdMwCKTJ+zFwQ20GkY+mAXGatyTw3HcoUlR39HwmA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.1.tgz", + "integrity": "sha512-tj4Ku7MpzZR8cmVuPcSbrLFVxmptWktmJMwST/uIEq4sarabEdF8CbmQdYB7uJ/X51Qq2EYwnRsoS7hdR4B7rA==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-stream": "^3.0.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.0.0.tgz", + "integrity": "sha512-VvWuQk2RKFuOr98gFhjca7fkBS+xLLURT8bUjk5XQoV0ZLm7WPwWPPY3/AwzTLuUBDeoKDCthfe1AsTUWaSEhw==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.0.tgz", + "integrity": "sha512-2XLazFgUu+YOGHtWihB3FSLAfCUajVfNBXGGYjOaVKjLAuAxx3pSBY3hBgLzIgB17haf59gOG3imKqTy8mcrjw==", + "dependencies": { + "@smithy/querystring-parser": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.3.tgz", + "integrity": "sha512-3DFON2bvXJAukJe+qFgPV/rorG7ZD3m4gjCXHD1V5z/tgKQp5MCTCLntrd686tX6tj8Uli3lefWXJudNg5WmCA==", + "dependencies": { + "@smithy/property-provider": "^3.1.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.3.tgz", + "integrity": "sha512-D0b8GJXecT00baoSQ3Iieu3k3mZ7GY8w1zmg8pdogYrGvWJeLcIclqk2gbkG4K0DaBGWrO6v6r20iwIFfDYrmA==", + "dependencies": { + "@smithy/config-resolver": "^3.0.1", + "@smithy/credential-provider-imds": "^3.1.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.0.1.tgz", + "integrity": "sha512-ZRT0VCOnKlVohfoABMc8lWeQo/JEFuPWctfNRXgTHbyOVssMOLYFUNWukxxiHRGVAhV+n3c0kPW+zUqckjVPEA==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.0.tgz", + "integrity": "sha512-q5ITdOnV2pXHSVDnKWrwgSNTDBAMHLptFE07ua/5Ty5WJ11bvr0vk2a7agu7qRhrCFRQlno5u3CneU5EELK+DQ==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.0.tgz", + "integrity": "sha512-nK99bvJiziGv/UOKJlDvFF45F00WgPLKVIGUfAK+mDhzVN2hb/S33uW2Tlhg5PVBoqY7tDVqL0zmu4OxAHgo9g==", + "dependencies": { + "@smithy/service-error-classification": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.0.1.tgz", + "integrity": "sha512-7F7VNNhAsfMRA8I986YdOY5fE0/T1/ZjFF6OLsqkvQVNP3vZ/szYDfGCyphb7ioA09r32K/0qbSFfNFU68aSzA==", + "dependencies": { + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", "dependencies": { - "type-detect": "4.0.8" + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "node_modules/@smithy/util-waiter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-3.0.0.tgz", + "integrity": "sha512-+fEXJxGDLCoqRKVSmo0auGxaqbiCo+8oph+4auefYjaNxjOLKSY2MxVQfRzo65PaZv4fr+5lWg+au7vSuJJ/zw==", "dependencies": { - "@sinonjs/commons": "^3.0.0" + "@smithy/abort-controller": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, "node_modules/@tsconfig/node10": { @@ -3072,6 +4554,17 @@ "@types/express": "*" } }, + "node_modules/@types/multer-s3": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/multer-s3/-/multer-s3-3.0.3.tgz", + "integrity": "sha512-VgWygI9UwyS7loLithUUi0qAMIDWdNrERS2Sb06UuPYiLzKuIFn2NgL7satyl4v8sh/LLoU7DiPanvbQaRg9Yg==", + "dev": true, + "dependencies": { + "@aws-sdk/client-s3": "^3.0.0", + "@types/multer": "*", + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "20.12.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.13.tgz", @@ -3357,6 +4850,49 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sdk": { + "version": "2.1634.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1634.0.tgz", + "integrity": "sha512-uSEjzAyGIbfpALzxPYES+hsBK1zuUY/8wSv2mAwijAcQfTMV89jQ4VHI/5KsyyZhDSeS/rV9cn6376KO+HDU2w==", + "hasInstallScript": true, + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "util": "^0.12.4", + "uuid": "8.0.0", + "xml2js": "0.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aws-sdk/node_modules/uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -3519,6 +5055,25 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/base64url": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", @@ -3593,6 +5148,11 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3664,6 +5224,16 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -4312,6 +5882,14 @@ "node": ">= 0.6" } }, + "node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -4428,6 +6006,27 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "node_modules/fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -4436,6 +6035,14 @@ "bser": "2.1.1" } }, + "node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -4476,6 +6083,14 @@ "node": ">=8" } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -4722,6 +6337,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -4738,6 +6367,11 @@ "node": ">= 0.4" } }, + "node_modules/html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==" + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -4810,6 +6444,11 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, "node_modules/ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", @@ -4865,6 +6504,21 @@ "node": ">= 0.10" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -4882,6 +6536,17 @@ "node": ">=8" } }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", @@ -4923,6 +6588,20 @@ "node": ">=6" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -4954,6 +6633,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-uuid": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-uuid/-/is-uuid-1.0.2.tgz", @@ -5631,6 +7324,14 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6068,6 +7769,23 @@ "node": ">= 6.0.0" } }, + "node_modules/multer-s3": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/multer-s3/-/multer-s3-3.0.1.tgz", + "integrity": "sha512-BFwSO80a5EW4GJRBdUuSHblz2jhVSAze33ZbnGpcfEicoT0iRolx4kWR+AJV07THFRCQ78g+kelKFdjkCCaXeQ==", + "dependencies": { + "@aws-sdk/lib-storage": "^3.46.0", + "file-type": "^3.3.0", + "html-comment-regex": "^1.1.2", + "run-parallel": "^1.1.6" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-s3": "^3.0.0" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6513,6 +8231,14 @@ "node": ">=8" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -6587,6 +8313,11 @@ "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", "dev": true }, + "node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" + }, "node_modules/pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", @@ -6616,6 +8347,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -6829,6 +8588,28 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -6853,6 +8634,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" + }, "node_modules/semver": { "version": "7.6.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", @@ -7039,6 +8825,28 @@ "node": ">= 0.8" } }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-browserify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -7123,6 +8931,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, "node_modules/superstruct": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", @@ -7411,6 +9224,11 @@ } } }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, "node_modules/tsx": { "version": "4.11.0", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.11.0.tgz", @@ -7583,6 +9401,27 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -7596,6 +9435,18 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -7676,6 +9527,24 @@ "node": ">= 8" } }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -7717,6 +9586,26 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index e9da8e4..7f99b54 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,8 @@ { "dependencies": { + "@aws-sdk/client-s3": "^3.590.0", "@prisma/client": "^5.4.2", + "aws-sdk": "^2.1634.0", "bcrypt": "^5.1.1", "dotenv": "^16.3.1", "express": "^4.18.2", @@ -10,6 +12,7 @@ "jsonwebtoken": "^9.0.2", "moment-timezone": "^0.5.45", "multer": "^1.4.5-lts.1", + "multer-s3": "^3.0.1", "passport": "^0.7.0", "passport-google-oauth20": "^2.0.0", "prisma": "^5.4.2", @@ -29,6 +32,7 @@ "@types/jsonwebtoken": "^9.0.6", "@types/morgan": "^1.9.9", "@types/multer": "^1.4.11", + "@types/multer-s3": "^3.0.3", "@types/node": "^20.12.13", "@types/passport": "^1.0.16", "@types/passport-google-oauth20": "^2.0.16", diff --git a/src/app.ts b/src/app.ts index 883cd05..4ca2971 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,6 +1,6 @@ import cors from "cors"; import dotenv from "dotenv"; -import express from "express"; +import express, { NextFunction, Request, Response } from "express"; import session from "express-session"; import fs from "fs"; import moment from "moment-timezone"; @@ -45,6 +45,11 @@ app.use(session({ secret: JWT_SECRET, resave: false, saveUninitialized: true })) app.use(passport.initialize()); app.use(passport.session()); +app.use((err: Error, req: Request, res: Response, next: NextFunction) => { + console.error(err.stack); + res.status(500).send("Something broke!"); +}); + app.use("/products", productsRouter); app.use("/articles", articlesRouter); app.use("/images", imagesRouter); diff --git a/src/controllers/imageController.ts b/src/controllers/imageController.ts index 6eac983..224da79 100644 --- a/src/controllers/imageController.ts +++ b/src/controllers/imageController.ts @@ -2,10 +2,8 @@ import { Request, Response } from "express"; import * as imageService from "../services/imageService"; export const uploadImage = async (req: Request, res: Response) => { - const file = req.file; - try { - const imageUrl = await imageService.uploadImage(file); + const imageUrl = await imageService.uploadImage(req); res.status(200).json({ url: imageUrl }); } catch (error) { res.status(400).send((error as Error).message); diff --git a/src/routes/imageRoutes.ts b/src/routes/imageRoutes.ts index 4966f1a..b890fff 100644 --- a/src/routes/imageRoutes.ts +++ b/src/routes/imageRoutes.ts @@ -1,23 +1,9 @@ import express from "express"; -import multer from "multer"; -import path from "path"; -import * as imageController from "../controllers/imageController.js"; -import authenticate from "../middlewares/authenticate.js"; - +import * as imageController from "../controllers/imageController"; +import authenticate from "../middlewares/authenticate"; +import { uploadImageToS3 } from "../services/imageService"; const router = express.Router(); -const storage = multer.diskStorage({ - destination: (req, file, cb) => { - cb(null, "uploads/"); - }, - filename: (req, file, cb) => { - const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9); - cb(null, file.fieldname + "-" + uniqueSuffix + path.extname(file.originalname)); - }, -}); - -const upload = multer({ storage: storage }); - /** * @swagger * tags: @@ -65,6 +51,6 @@ const upload = multer({ storage: storage }); * type: string * example: "이미지 파일을 선택해주세요." */ -router.post("/upload", authenticate, upload.single("image"), imageController.uploadImage); +router.post("/upload", authenticate, uploadImageToS3, imageController.uploadImage); export default router; diff --git a/src/services/imageService.ts b/src/services/imageService.ts index 0e9f359..dfa7e1e 100644 --- a/src/services/imageService.ts +++ b/src/services/imageService.ts @@ -1,19 +1,47 @@ +import { S3Client } from "@aws-sdk/client-s3"; import { PrismaClient } from "@prisma/client"; +import { Request } from "express"; +import multer from "multer"; +import multerS3 from "multer-s3"; const prisma = new PrismaClient(); -const SERVER_URL = "http://localhost:3000"; -export const uploadImage = async (file: Express.Multer.File | undefined): Promise => { +const s3Config = new S3Client({ + region: "ap-northeast-2", + credentials: { + accessKeyId: process.env.AWS_ACCESS_KEY_ID || "", + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || "", + }, +}); + +const upload = multer({ + storage: multerS3({ + s3: s3Config, + bucket: process.env.AWS_S3_BUCKET_NAME || "", + acl: "public-read", + metadata: function (req, file, cb) { + cb(null, { fieldName: file.fieldname }); + }, + key: function (req, file, cb) { + cb(null, `images/${Date.now().toString()}_${file.originalname}`); + }, + }), +}); + +export const uploadImageToS3 = upload.single("image"); + +export const uploadImage = async (req: Request): Promise => { + const file = req.file as Express.MulterS3File; + if (!file) { throw new Error("이미지 파일을 선택해주세요."); } - const imagePath = file.path; - const imageUrl = `${SERVER_URL}/${imagePath.replace(/\\/g, "/")}`; + const imageUrl: string = file.location; await prisma.image.create({ data: { - imagePath: imagePath, + imagePath: imageUrl, }, }); diff --git a/src/test/productService.test.ts b/src/test/productService.test.ts index 45e9804..ac5495b 100644 --- a/src/test/productService.test.ts +++ b/src/test/productService.test.ts @@ -224,6 +224,26 @@ describe("상품 서비스", () => { await expect(getProductById("non-existent-product-id")).rejects.toThrow("존재하지 않는 상품입니다."); }); + test("상품을 수정할 권한이 없으면 예외를 발생시킨다", async () => { + const anotherUserProduct = { ...mockProduct, userId: 2 }; + ( + prisma.product.findUniqueOrThrow as jest.MockedFunction + ).mockResolvedValue(anotherUserProduct); + + await expect( + updateProduct( + "test-product-id", + 1, + { + name: "업데이트된 상품", + description: "업데이트된 설명", + price: 150, + }, + "image1.jpg" + ) + ).rejects.toThrow("상품을 수정할 권한이 없습니다."); + }); + test("상품을 업데이트한다", async () => { ( prisma.product.findUniqueOrThrow as jest.MockedFunction @@ -484,24 +504,4 @@ describe("상품 서비스", () => { }, }); }); - - test("상품을 수정할 권한이 없으면 예외를 발생시킨다", async () => { - const anotherUserProduct = { ...mockProduct, userId: 2 }; - ( - prisma.product.findUniqueOrThrow as jest.MockedFunction - ).mockResolvedValue(anotherUserProduct); - - await expect( - updateProduct( - "test-product-id", - 1, - { - name: "업데이트된 상품", - description: "업데이트된 설명", - price: 150, - }, - "image1.jpg" - ) - ).rejects.toThrow("상품을 수정할 권한이 없습니다."); - }); }); diff --git a/src/types/express/index.d.ts b/src/types/express/index.d.ts index c335c80..1bcee93 100644 --- a/src/types/express/index.d.ts +++ b/src/types/express/index.d.ts @@ -9,4 +9,8 @@ declare namespace Express { interface Request { user?: User; } + + interface MulterS3File extends Multer.File { + location: string; + } } diff --git a/test.html b/test.html index ddb7fb2..7326125 100644 --- a/test.html +++ b/test.html @@ -5,6 +5,7 @@ Upload Image + @@ -19,25 +20,21 @@ const form = event.target; const formData = new FormData(form); - const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNjg3NTQ4MCwiZXhwIjoxNzE2ODc2MzgwfQ.c07c8gt-7uMUXVssa1cf5CtZFCFaWXHczV1m_rAtSJo'; + const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzU3NjczNCwiZXhwIjoxNzE3NTc3NjM0fQ.xne1SC64b-ebpHbw9s2Cbj5l2Q6AuaRi6d3uWIry3wM'; try { - const response = await fetch('http://localhost:3000/images/upload', { - method: 'POST', - body: formData, + const response = await axios.post('http://localhost:3000/images/upload', formData, { headers: { - 'Authorization': `Bearer ${token}` + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'multipart/form-data' } }); - if (!response.ok) { - throw new Error('Network response was not ok ' + response.statusText); - } - - const data = await response.json(); - console.log('Success:', data); + console.log('Success:', response.data); + alert(`Image uploaded successfully: ${response.data.url}`); } catch (error) { console.error('Error:', error); + alert('Error uploading image'); } }); diff --git a/yarn.lock b/yarn.lock index be9055a..3065afd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -42,6 +42,628 @@ call-me-maybe "^1.0.1" z-schema "^5.0.1" +"@aws-crypto/crc32@3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz" + integrity sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA== + dependencies: + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + tslib "^1.11.1" + +"@aws-crypto/crc32c@3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz" + integrity sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w== + dependencies: + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + tslib "^1.11.1" + +"@aws-crypto/ie11-detection@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz" + integrity sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q== + dependencies: + tslib "^1.11.1" + +"@aws-crypto/sha1-browser@3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz" + integrity sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw== + dependencies: + "@aws-crypto/ie11-detection" "^3.0.0" + "@aws-crypto/supports-web-crypto" "^3.0.0" + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@aws-sdk/util-utf8-browser" "^3.0.0" + tslib "^1.11.1" + +"@aws-crypto/sha256-browser@3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz" + integrity sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ== + dependencies: + "@aws-crypto/ie11-detection" "^3.0.0" + "@aws-crypto/sha256-js" "^3.0.0" + "@aws-crypto/supports-web-crypto" "^3.0.0" + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@aws-sdk/util-utf8-browser" "^3.0.0" + tslib "^1.11.1" + +"@aws-crypto/sha256-js@^3.0.0", "@aws-crypto/sha256-js@3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz" + integrity sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ== + dependencies: + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + tslib "^1.11.1" + +"@aws-crypto/supports-web-crypto@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz" + integrity sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg== + dependencies: + tslib "^1.11.1" + +"@aws-crypto/util@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz" + integrity sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w== + dependencies: + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-utf8-browser" "^3.0.0" + tslib "^1.11.1" + +"@aws-sdk/client-s3@^3.0.0", "@aws-sdk/client-s3@^3.590.0": + version "3.590.0" + resolved "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.590.0.tgz" + integrity sha512-so+pNua0ihsHaSdskw8HCwruoYTAfYSEs3ix4GD1++83C96KaJp3udAutYiCA+84JXg9zitFa7eK7ORJAVZmTw== + dependencies: + "@aws-crypto/sha1-browser" "3.0.0" + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sso-oidc" "3.590.0" + "@aws-sdk/client-sts" "3.590.0" + "@aws-sdk/core" "3.588.0" + "@aws-sdk/credential-provider-node" "3.590.0" + "@aws-sdk/middleware-bucket-endpoint" "3.587.0" + "@aws-sdk/middleware-expect-continue" "3.577.0" + "@aws-sdk/middleware-flexible-checksums" "3.587.0" + "@aws-sdk/middleware-host-header" "3.577.0" + "@aws-sdk/middleware-location-constraint" "3.577.0" + "@aws-sdk/middleware-logger" "3.577.0" + "@aws-sdk/middleware-recursion-detection" "3.577.0" + "@aws-sdk/middleware-sdk-s3" "3.587.0" + "@aws-sdk/middleware-signing" "3.587.0" + "@aws-sdk/middleware-ssec" "3.577.0" + "@aws-sdk/middleware-user-agent" "3.587.0" + "@aws-sdk/region-config-resolver" "3.587.0" + "@aws-sdk/signature-v4-multi-region" "3.587.0" + "@aws-sdk/types" "3.577.0" + "@aws-sdk/util-endpoints" "3.587.0" + "@aws-sdk/util-user-agent-browser" "3.577.0" + "@aws-sdk/util-user-agent-node" "3.587.0" + "@aws-sdk/xml-builder" "3.575.0" + "@smithy/config-resolver" "^3.0.1" + "@smithy/core" "^2.1.1" + "@smithy/eventstream-serde-browser" "^3.0.0" + "@smithy/eventstream-serde-config-resolver" "^3.0.0" + "@smithy/eventstream-serde-node" "^3.0.0" + "@smithy/fetch-http-handler" "^3.0.1" + "@smithy/hash-blob-browser" "^3.0.0" + "@smithy/hash-node" "^3.0.0" + "@smithy/hash-stream-node" "^3.0.0" + "@smithy/invalid-dependency" "^3.0.0" + "@smithy/md5-js" "^3.0.0" + "@smithy/middleware-content-length" "^3.0.0" + "@smithy/middleware-endpoint" "^3.0.1" + "@smithy/middleware-retry" "^3.0.3" + "@smithy/middleware-serde" "^3.0.0" + "@smithy/middleware-stack" "^3.0.0" + "@smithy/node-config-provider" "^3.1.0" + "@smithy/node-http-handler" "^3.0.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/smithy-client" "^3.1.1" + "@smithy/types" "^3.0.0" + "@smithy/url-parser" "^3.0.0" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.3" + "@smithy/util-defaults-mode-node" "^3.0.3" + "@smithy/util-endpoints" "^2.0.1" + "@smithy/util-retry" "^3.0.0" + "@smithy/util-stream" "^3.0.1" + "@smithy/util-utf8" "^3.0.0" + "@smithy/util-waiter" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-sso-oidc@^3.587.0", "@aws-sdk/client-sso-oidc@3.590.0": + version "3.590.0" + resolved "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.590.0.tgz" + integrity sha512-3yCLPjq6WFfDpdUJKk/gSz4eAPDTjVknXaveMPi2QoVBCshneOnJsV16uNKlpVF1frTHrrDRfKYmbaVh6nFBvQ== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.590.0" + "@aws-sdk/core" "3.588.0" + "@aws-sdk/credential-provider-node" "3.590.0" + "@aws-sdk/middleware-host-header" "3.577.0" + "@aws-sdk/middleware-logger" "3.577.0" + "@aws-sdk/middleware-recursion-detection" "3.577.0" + "@aws-sdk/middleware-user-agent" "3.587.0" + "@aws-sdk/region-config-resolver" "3.587.0" + "@aws-sdk/types" "3.577.0" + "@aws-sdk/util-endpoints" "3.587.0" + "@aws-sdk/util-user-agent-browser" "3.577.0" + "@aws-sdk/util-user-agent-node" "3.587.0" + "@smithy/config-resolver" "^3.0.1" + "@smithy/core" "^2.1.1" + "@smithy/fetch-http-handler" "^3.0.1" + "@smithy/hash-node" "^3.0.0" + "@smithy/invalid-dependency" "^3.0.0" + "@smithy/middleware-content-length" "^3.0.0" + "@smithy/middleware-endpoint" "^3.0.1" + "@smithy/middleware-retry" "^3.0.3" + "@smithy/middleware-serde" "^3.0.0" + "@smithy/middleware-stack" "^3.0.0" + "@smithy/node-config-provider" "^3.1.0" + "@smithy/node-http-handler" "^3.0.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/smithy-client" "^3.1.1" + "@smithy/types" "^3.0.0" + "@smithy/url-parser" "^3.0.0" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.3" + "@smithy/util-defaults-mode-node" "^3.0.3" + "@smithy/util-endpoints" "^2.0.1" + "@smithy/util-middleware" "^3.0.0" + "@smithy/util-retry" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-sso@3.590.0": + version "3.590.0" + resolved "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.590.0.tgz" + integrity sha512-6xbC6oQVJKBRTyXyR3C15ksUsPOyW4p+uCj7dlKYWGJvh4vGTV8KhZKS53oPG8t4f1+OMJWjr5wKuXRoaFsmhQ== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/core" "3.588.0" + "@aws-sdk/middleware-host-header" "3.577.0" + "@aws-sdk/middleware-logger" "3.577.0" + "@aws-sdk/middleware-recursion-detection" "3.577.0" + "@aws-sdk/middleware-user-agent" "3.587.0" + "@aws-sdk/region-config-resolver" "3.587.0" + "@aws-sdk/types" "3.577.0" + "@aws-sdk/util-endpoints" "3.587.0" + "@aws-sdk/util-user-agent-browser" "3.577.0" + "@aws-sdk/util-user-agent-node" "3.587.0" + "@smithy/config-resolver" "^3.0.1" + "@smithy/core" "^2.1.1" + "@smithy/fetch-http-handler" "^3.0.1" + "@smithy/hash-node" "^3.0.0" + "@smithy/invalid-dependency" "^3.0.0" + "@smithy/middleware-content-length" "^3.0.0" + "@smithy/middleware-endpoint" "^3.0.1" + "@smithy/middleware-retry" "^3.0.3" + "@smithy/middleware-serde" "^3.0.0" + "@smithy/middleware-stack" "^3.0.0" + "@smithy/node-config-provider" "^3.1.0" + "@smithy/node-http-handler" "^3.0.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/smithy-client" "^3.1.1" + "@smithy/types" "^3.0.0" + "@smithy/url-parser" "^3.0.0" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.3" + "@smithy/util-defaults-mode-node" "^3.0.3" + "@smithy/util-endpoints" "^2.0.1" + "@smithy/util-middleware" "^3.0.0" + "@smithy/util-retry" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-sts@^3.587.0", "@aws-sdk/client-sts@^3.590.0", "@aws-sdk/client-sts@3.590.0": + version "3.590.0" + resolved "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.590.0.tgz" + integrity sha512-f4R1v1LSn4uLYZ5qj4DyL6gp7PXXzJeJsm2seheiJX+53LSF5L7XSDnQVtX1p9Tevv0hp2YUWUTg6QYwIVSuGg== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sso-oidc" "3.590.0" + "@aws-sdk/core" "3.588.0" + "@aws-sdk/credential-provider-node" "3.590.0" + "@aws-sdk/middleware-host-header" "3.577.0" + "@aws-sdk/middleware-logger" "3.577.0" + "@aws-sdk/middleware-recursion-detection" "3.577.0" + "@aws-sdk/middleware-user-agent" "3.587.0" + "@aws-sdk/region-config-resolver" "3.587.0" + "@aws-sdk/types" "3.577.0" + "@aws-sdk/util-endpoints" "3.587.0" + "@aws-sdk/util-user-agent-browser" "3.577.0" + "@aws-sdk/util-user-agent-node" "3.587.0" + "@smithy/config-resolver" "^3.0.1" + "@smithy/core" "^2.1.1" + "@smithy/fetch-http-handler" "^3.0.1" + "@smithy/hash-node" "^3.0.0" + "@smithy/invalid-dependency" "^3.0.0" + "@smithy/middleware-content-length" "^3.0.0" + "@smithy/middleware-endpoint" "^3.0.1" + "@smithy/middleware-retry" "^3.0.3" + "@smithy/middleware-serde" "^3.0.0" + "@smithy/middleware-stack" "^3.0.0" + "@smithy/node-config-provider" "^3.1.0" + "@smithy/node-http-handler" "^3.0.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/smithy-client" "^3.1.1" + "@smithy/types" "^3.0.0" + "@smithy/url-parser" "^3.0.0" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.3" + "@smithy/util-defaults-mode-node" "^3.0.3" + "@smithy/util-endpoints" "^2.0.1" + "@smithy/util-middleware" "^3.0.0" + "@smithy/util-retry" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/core@3.588.0": + version "3.588.0" + resolved "https://registry.npmjs.org/@aws-sdk/core/-/core-3.588.0.tgz" + integrity sha512-O1c2+9ce46Z+iiid+W3iC1IvPbfIo5ev9CBi54GdNB9SaI8/3+f8MJcux0D6c9toCF0ArMersN/gp8ek57e9uQ== + dependencies: + "@smithy/core" "^2.1.1" + "@smithy/protocol-http" "^4.0.0" + "@smithy/signature-v4" "^3.0.0" + "@smithy/smithy-client" "^3.1.1" + "@smithy/types" "^3.0.0" + fast-xml-parser "4.2.5" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-env@3.587.0": + version "3.587.0" + resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.587.0.tgz" + integrity sha512-Hyg/5KFECIk2k5o8wnVEiniV86yVkhn5kzITUydmNGCkXdBFHMHRx6hleQ1bqwJHbBskyu8nbYamzcwymmGwmw== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/property-provider" "^3.1.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-http@3.587.0": + version "3.587.0" + resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.587.0.tgz" + integrity sha512-Su1SRWVRCuR1e32oxX3C1V4c5hpPN20WYcRfdcr2wXwHqSvys5DrnmuCC+JoEnS/zt3adUJhPliTqpfKgSdMrA== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/fetch-http-handler" "^3.0.1" + "@smithy/node-http-handler" "^3.0.0" + "@smithy/property-provider" "^3.1.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/smithy-client" "^3.1.1" + "@smithy/types" "^3.0.0" + "@smithy/util-stream" "^3.0.1" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-ini@3.590.0": + version "3.590.0" + resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.590.0.tgz" + integrity sha512-Y5cFciAK38VIvRgZeND7HvFNR32thGtQb8Xop6cMn33FC78uwcRIu9Hc9699XTclCZqz4+Xl1WU+dZ+rnFn2AA== + dependencies: + "@aws-sdk/credential-provider-env" "3.587.0" + "@aws-sdk/credential-provider-http" "3.587.0" + "@aws-sdk/credential-provider-process" "3.587.0" + "@aws-sdk/credential-provider-sso" "3.590.0" + "@aws-sdk/credential-provider-web-identity" "3.587.0" + "@aws-sdk/types" "3.577.0" + "@smithy/credential-provider-imds" "^3.1.0" + "@smithy/property-provider" "^3.1.0" + "@smithy/shared-ini-file-loader" "^3.1.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-node@3.590.0": + version "3.590.0" + resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.590.0.tgz" + integrity sha512-Ky38mNFoXobGrDQ11P3dU1e+q1nRJ7eZl8l15KUpvZCe/hOudbxQi/epQrCazD/gRYV2fTyczdLlZzB5ZZ8DhQ== + dependencies: + "@aws-sdk/credential-provider-env" "3.587.0" + "@aws-sdk/credential-provider-http" "3.587.0" + "@aws-sdk/credential-provider-ini" "3.590.0" + "@aws-sdk/credential-provider-process" "3.587.0" + "@aws-sdk/credential-provider-sso" "3.590.0" + "@aws-sdk/credential-provider-web-identity" "3.587.0" + "@aws-sdk/types" "3.577.0" + "@smithy/credential-provider-imds" "^3.1.0" + "@smithy/property-provider" "^3.1.0" + "@smithy/shared-ini-file-loader" "^3.1.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-process@3.587.0": + version "3.587.0" + resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.587.0.tgz" + integrity sha512-V4xT3iCqkF8uL6QC4gqBJg/2asd/damswP1h9HCfqTllmPWzImS+8WD3VjgTLw5b0KbTy+ZdUhKc0wDnyzkzxg== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/property-provider" "^3.1.0" + "@smithy/shared-ini-file-loader" "^3.1.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-sso@3.590.0": + version "3.590.0" + resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.590.0.tgz" + integrity sha512-v+0j/I+je9okfwXsgmLppmwIE+TuMp5WqLz7r7PHz9KjzLyKaKTDvfllFD+8oPpBqnmOWiJ9qTGPkrfhB7a/fQ== + dependencies: + "@aws-sdk/client-sso" "3.590.0" + "@aws-sdk/token-providers" "3.587.0" + "@aws-sdk/types" "3.577.0" + "@smithy/property-provider" "^3.1.0" + "@smithy/shared-ini-file-loader" "^3.1.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-web-identity@3.587.0": + version "3.587.0" + resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.587.0.tgz" + integrity sha512-XqIx/I2PG7kyuw3WjAP9wKlxy8IvFJwB8asOFT1xPFoVfZYKIogjG9oLP5YiRtfvDkWIztHmg5MlVv3HdJDGRw== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/property-provider" "^3.1.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/lib-storage@^3.46.0": + version "3.590.0" + resolved "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.590.0.tgz" + integrity sha512-GPR9Kg8N/wM3BCtsj/Bk8k9OIshGMdMmTWgVg+fdLnP5KHH+OMNfvF9aw7JHWjY5c9sM4wKYceBGWNLVSw+lPQ== + dependencies: + "@smithy/abort-controller" "^3.0.0" + "@smithy/middleware-endpoint" "^3.0.1" + "@smithy/smithy-client" "^3.1.1" + buffer "5.6.0" + events "3.3.0" + stream-browserify "3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-bucket-endpoint@3.587.0": + version "3.587.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.587.0.tgz" + integrity sha512-HkFXLPl8pr6BH/Q0JpOESqEKL0ZK3sk7aSZ1S6GE4RXET7H5R94THULXqQFZzD48gZcyFooO/yNKZTqrZFaWKg== + dependencies: + "@aws-sdk/types" "3.577.0" + "@aws-sdk/util-arn-parser" "3.568.0" + "@smithy/node-config-provider" "^3.1.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/types" "^3.0.0" + "@smithy/util-config-provider" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-expect-continue@3.577.0": + version "3.577.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.577.0.tgz" + integrity sha512-6dPp8Tv4F0of4un5IAyG6q++GrRrNQQ4P2NAMB1W0VO4JoEu1C8GievbbDLi88TFIFmtKpnHB0ODCzwnoe8JsA== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-flexible-checksums@3.587.0": + version "3.587.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.587.0.tgz" + integrity sha512-URMwp/budDvKhIvZ4a6zIBfFTun/iDlPWXqsGKYjEtHt8jz27OSjCZtDtIeqW4WTBdKL8KZgQcl+DdaE5M1qiQ== + dependencies: + "@aws-crypto/crc32" "3.0.0" + "@aws-crypto/crc32c" "3.0.0" + "@aws-sdk/types" "3.577.0" + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/types" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-host-header@3.577.0": + version "3.577.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.577.0.tgz" + integrity sha512-9ca5MJz455CODIVXs0/sWmJm7t3QO4EUa1zf8pE8grLpzf0J94bz/skDWm37Pli13T3WaAQBHCTiH2gUVfCsWg== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-location-constraint@3.577.0": + version "3.577.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.577.0.tgz" + integrity sha512-DKPTD2D2s+t2QUo/IXYtVa/6Un8GZ+phSTBkyBNx2kfZz4Kwavhl/JJzSqTV3GfCXkVdFu7CrjoX7BZ6qWeTUA== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-logger@3.577.0": + version "3.577.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.577.0.tgz" + integrity sha512-aPFGpGjTZcJYk+24bg7jT4XdIp42mFXSuPt49lw5KygefLyJM/sB0bKKqPYYivW0rcuZ9brQ58eZUNthrzYAvg== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-recursion-detection@3.577.0": + version "3.577.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.577.0.tgz" + integrity sha512-pn3ZVEd2iobKJlR3H+bDilHjgRnNrQ6HMmK9ZzZw89Ckn3Dcbv48xOv4RJvu0aU8SDLl/SNCxppKjeLDTPGBNA== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-sdk-s3@3.587.0": + version "3.587.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.587.0.tgz" + integrity sha512-vtXTGEiw1E9Fax4LmcU2Z208gbrC8ShrdsSLmGcRPpu5NPOGBFBSDG5sy5EDNClrFxIl/Le8coQnD0EDBtx+uQ== + dependencies: + "@aws-sdk/types" "3.577.0" + "@aws-sdk/util-arn-parser" "3.568.0" + "@smithy/node-config-provider" "^3.1.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/signature-v4" "^3.0.0" + "@smithy/smithy-client" "^3.1.1" + "@smithy/types" "^3.0.0" + "@smithy/util-config-provider" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-signing@3.587.0": + version "3.587.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.587.0.tgz" + integrity sha512-tiZaTDj4RvhXGRAlncFn7CSEfL3iNPO67WSaxAq+Ls5j1VgczPhu5262cWONNoMgth3nXR1hhLC4ITSl/a6AzA== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/property-provider" "^3.1.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/signature-v4" "^3.0.0" + "@smithy/types" "^3.0.0" + "@smithy/util-middleware" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-ssec@3.577.0": + version "3.577.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.577.0.tgz" + integrity sha512-i2BPJR+rp8xmRVIGc0h1kDRFcM2J9GnClqqpc+NLSjmYadlcg4mPklisz9HzwFVcRPJ5XcGf3U4BYs5G8+iTyg== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-user-agent@3.587.0": + version "3.587.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.587.0.tgz" + integrity sha512-SyDomN+IOrygLucziG7/nOHkjUXES5oH5T7p8AboO8oakMQJdnudNXiYWTicQWO52R51U6CR27rcMPTGeMedYA== + dependencies: + "@aws-sdk/types" "3.577.0" + "@aws-sdk/util-endpoints" "3.587.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/region-config-resolver@3.587.0": + version "3.587.0" + resolved "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.587.0.tgz" + integrity sha512-93I7IPZtulZQoRK+O20IJ4a1syWwYPzoO2gc3v+/GNZflZPV3QJXuVbIm0pxBsu0n/mzKGUKqSOLPIaN098HcQ== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/node-config-provider" "^3.1.0" + "@smithy/types" "^3.0.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/signature-v4-multi-region@3.587.0": + version "3.587.0" + resolved "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.587.0.tgz" + integrity sha512-TR9+ZSjdXvXUz54ayHcCihhcvxI9W7102J1OK6MrLgBlPE7uRhAx42BR9L5lLJ86Xj3LuqPWf//o9d/zR9WVIg== + dependencies: + "@aws-sdk/middleware-sdk-s3" "3.587.0" + "@aws-sdk/types" "3.577.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/signature-v4" "^3.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/token-providers@3.587.0": + version "3.587.0" + resolved "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.587.0.tgz" + integrity sha512-ULqhbnLy1hmJNRcukANBWJmum3BbjXnurLPSFXoGdV0llXYlG55SzIla2VYqdveQEEjmsBuTZdFvXAtNpmS5Zg== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/property-provider" "^3.1.0" + "@smithy/shared-ini-file-loader" "^3.1.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/types@^3.222.0", "@aws-sdk/types@3.577.0": + version "3.577.0" + resolved "https://registry.npmjs.org/@aws-sdk/types/-/types-3.577.0.tgz" + integrity sha512-FT2JZES3wBKN/alfmhlo+3ZOq/XJ0C7QOZcDNrpKjB0kqYoKjhVKZ/Hx6ArR0czkKfHzBBEs6y40ebIHx2nSmA== + dependencies: + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/util-arn-parser@3.568.0": + version "3.568.0" + resolved "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz" + integrity sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-endpoints@3.587.0": + version "3.587.0" + resolved "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.587.0.tgz" + integrity sha512-8I1HG6Em8wQWqKcRW6m358mqebRVNpL8XrrEoT4In7xqkKkmYtHRNVYP6lcmiQh5pZ/c/FXu8dSchuFIWyEtqQ== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/types" "^3.0.0" + "@smithy/util-endpoints" "^2.0.1" + tslib "^2.6.2" + +"@aws-sdk/util-locate-window@^3.0.0": + version "3.568.0" + resolved "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz" + integrity sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-browser@3.577.0": + version "3.577.0" + resolved "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.577.0.tgz" + integrity sha512-zEAzHgR6HWpZOH7xFgeJLc6/CzMcx4nxeQolZxVZoB5pPaJd3CjyRhZN0xXeZB0XIRCWmb4yJBgyiugXLNMkLA== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/types" "^3.0.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-node@3.587.0": + version "3.587.0" + resolved "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.587.0.tgz" + integrity sha512-Pnl+DUe/bvnbEEDHP3iVJrOtE3HbFJBPgsD6vJ+ml/+IYk1Eq49jEG+EHZdNTPz3SDG0kbp2+7u41MKYJHR/iQ== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/node-config-provider" "^3.1.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/util-utf8-browser@^3.0.0": + version "3.259.0" + resolved "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz" + integrity sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw== + dependencies: + tslib "^2.3.1" + +"@aws-sdk/xml-builder@3.575.0": + version "3.575.0" + resolved "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.575.0.tgz" + integrity sha512-cWgAwmbFYNCFzPwxL705+lWps0F3ZvOckufd2KKoEZUmtpVw9/txUXNrPySUXSmRTSRhoatIMABNfStWR043bQ== + dependencies: + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.6": version "7.24.6" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz" @@ -1393,6 +2015,470 @@ dependencies: "@sinonjs/commons" "^3.0.0" +"@smithy/abort-controller@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.0.0.tgz" + integrity sha512-p6GlFGBt9K4MYLu72YuJ523NVR4A8oHlC5M2JO6OmQqN8kAc/uh1JqLE+FizTokrSJGg0CSvC+BrsmGzKtsZKA== + dependencies: + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader-native@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz" + integrity sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg== + dependencies: + "@smithy/util-base64" "^3.0.0" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-3.0.0.tgz" + integrity sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA== + dependencies: + tslib "^2.6.2" + +"@smithy/config-resolver@^3.0.1": + version "3.0.1" + resolved "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.1.tgz" + integrity sha512-hbkYJc20SBDz2qqLzttjI/EqXemtmWk0ooRznLsiXp3066KQRTvuKHa7U4jCZCJq6Dozqvy0R1/vNESC9inPJg== + dependencies: + "@smithy/node-config-provider" "^3.1.0" + "@smithy/types" "^3.0.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.0" + tslib "^2.6.2" + +"@smithy/core@^2.1.1": + version "2.2.0" + resolved "https://registry.npmjs.org/@smithy/core/-/core-2.2.0.tgz" + integrity sha512-ygLZSSKgt9bR8HAxR9mK+U5obvAJBr6zlQuhN5soYWx/amjDoQN4dTkydTypgKe6rIbUjTILyLU+W5XFwXr4kg== + dependencies: + "@smithy/middleware-endpoint" "^3.0.1" + "@smithy/middleware-retry" "^3.0.3" + "@smithy/middleware-serde" "^3.0.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/smithy-client" "^3.1.1" + "@smithy/types" "^3.0.0" + "@smithy/util-middleware" "^3.0.0" + tslib "^2.6.2" + +"@smithy/credential-provider-imds@^3.1.0": + version "3.1.0" + resolved "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.1.0.tgz" + integrity sha512-q4A4d38v8pYYmseu/jTS3Z5I3zXlEOe5Obi+EJreVKgSVyWUHOd7/yaVCinC60QG4MRyCs98tcxBH1IMC0bu7Q== + dependencies: + "@smithy/node-config-provider" "^3.1.0" + "@smithy/property-provider" "^3.1.0" + "@smithy/types" "^3.0.0" + "@smithy/url-parser" "^3.0.0" + tslib "^2.6.2" + +"@smithy/eventstream-codec@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.0.0.tgz" + integrity sha512-PUtyEA0Oik50SaEFCZ0WPVtF9tz/teze2fDptW6WRXl+RrEenH8UbEjudOz8iakiMl3lE3lCVqYf2Y+znL8QFQ== + dependencies: + "@aws-crypto/crc32" "3.0.0" + "@smithy/types" "^3.0.0" + "@smithy/util-hex-encoding" "^3.0.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-browser@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.0.tgz" + integrity sha512-NB7AFiPN4NxP/YCAnrvYR18z2/ZsiHiF7VtG30gshO9GbFrIb1rC8ep4NGpJSWrz6P64uhPXeo4M0UsCLnZKqw== + dependencies: + "@smithy/eventstream-serde-universal" "^3.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-config-resolver@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.0.tgz" + integrity sha512-RUQG3vQ3LX7peqqHAbmayhgrF5aTilPnazinaSGF1P0+tgM3vvIRWPHmlLIz2qFqB9LqFIxditxc8O2Z6psrRw== + dependencies: + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-node@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.0.tgz" + integrity sha512-baRPdMBDMBExZXIUAoPGm/hntixjt/VFpU6+VmCyiYJYzRHRxoaI1MN+5XE+hIS8AJ2GCHLMFEIOLzq9xx1EgQ== + dependencies: + "@smithy/eventstream-serde-universal" "^3.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-universal@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.0.tgz" + integrity sha512-HNFfShmotWGeAoW4ujP8meV9BZavcpmerDbPIjkJbxKbN8RsUcpRQ/2OyIxWNxXNH2GWCAxuSB7ynmIGJlQ3Dw== + dependencies: + "@smithy/eventstream-codec" "^3.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/fetch-http-handler@^3.0.1": + version "3.0.1" + resolved "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.0.1.tgz" + integrity sha512-uaH74i5BDj+rBwoQaXioKpI0SHBJFtOVwzrCpxZxphOW0ki5jhj7dXvDMYM2IJem8TpdFvS2iC08sjOblfFGFg== + dependencies: + "@smithy/protocol-http" "^4.0.0" + "@smithy/querystring-builder" "^3.0.0" + "@smithy/types" "^3.0.0" + "@smithy/util-base64" "^3.0.0" + tslib "^2.6.2" + +"@smithy/hash-blob-browser@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-3.0.0.tgz" + integrity sha512-/Wbpdg+bwJvW7lxR/zpWAc1/x/YkcqguuF2bAzkJrvXriZu1vm8r+PUdE4syiVwQg7PPR2dXpi3CLBb9qRDaVQ== + dependencies: + "@smithy/chunked-blob-reader" "^3.0.0" + "@smithy/chunked-blob-reader-native" "^3.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/hash-node@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.0.tgz" + integrity sha512-84qXstNemP3XS5jcof0el6+bDfjzuvhJPQTEfro3lgtbCtKgzPm3MgiS6ehXVPjeQ5+JS0HqmTz8f/RYfzHVxw== + dependencies: + "@smithy/types" "^3.0.0" + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/hash-stream-node@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-3.0.0.tgz" + integrity sha512-J0i7de+EgXDEGITD4fxzmMX8CyCNETTIRXlxjMiNUvvu76Xn3GJ31wQR85ynlPk2wI1lqoknAFJaD1fiNDlbIA== + dependencies: + "@smithy/types" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/invalid-dependency@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.0.tgz" + integrity sha512-F6wBBaEFgJzj0s4KUlliIGPmqXemwP6EavgvDqYwCH40O5Xr2iMHvS8todmGVZtuJCorBkXsYLyTu4PuizVq5g== + dependencies: + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/is-array-buffer@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz" + integrity sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ== + dependencies: + tslib "^2.6.2" + +"@smithy/md5-js@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-3.0.0.tgz" + integrity sha512-Tm0vrrVzjlD+6RCQTx7D3Ls58S3FUH1ZCtU1MIh/qQmaOo1H9lMN2as6CikcEwgattnA9SURSdoJJ27xMcEfMA== + dependencies: + "@smithy/types" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/middleware-content-length@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.0.tgz" + integrity sha512-3C4s4d/iGobgCtk2tnWW6+zSTOBg1PRAm2vtWZLdriwTroFbbWNSr3lcyzHdrQHnEXYCC5K52EbpfodaIUY8sg== + dependencies: + "@smithy/protocol-http" "^4.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/middleware-endpoint@^3.0.1": + version "3.0.1" + resolved "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.0.1.tgz" + integrity sha512-lQ/UOdGD4KM5kLZiAl0q8Qy3dPbynvAXKAdXnYlrA1OpaUwr+neSsVokDZpY6ZVb5Yx8jnus29uv6XWpM9P4SQ== + dependencies: + "@smithy/middleware-serde" "^3.0.0" + "@smithy/node-config-provider" "^3.1.0" + "@smithy/shared-ini-file-loader" "^3.1.0" + "@smithy/types" "^3.0.0" + "@smithy/url-parser" "^3.0.0" + "@smithy/util-middleware" "^3.0.0" + tslib "^2.6.2" + +"@smithy/middleware-retry@^3.0.3": + version "3.0.3" + resolved "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.3.tgz" + integrity sha512-Wve1qzJb83VEU/6q+/I0cQdAkDnuzELC6IvIBwDzUEiGpKqXgX1v10FUuZGbRS6Ov/P+HHthcAoHOJZQvZNAkA== + dependencies: + "@smithy/node-config-provider" "^3.1.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/service-error-classification" "^3.0.0" + "@smithy/smithy-client" "^3.1.1" + "@smithy/types" "^3.0.0" + "@smithy/util-middleware" "^3.0.0" + "@smithy/util-retry" "^3.0.0" + tslib "^2.6.2" + uuid "^9.0.1" + +"@smithy/middleware-serde@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.0.tgz" + integrity sha512-I1vKG1foI+oPgG9r7IMY1S+xBnmAn1ISqployvqkwHoSb8VPsngHDTOgYGYBonuOKndaWRUGJZrKYYLB+Ane6w== + dependencies: + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/middleware-stack@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.0.tgz" + integrity sha512-+H0jmyfAyHRFXm6wunskuNAqtj7yfmwFB6Fp37enytp2q047/Od9xetEaUbluyImOlGnGpaVGaVfjwawSr+i6Q== + dependencies: + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/node-config-provider@^3.1.0": + version "3.1.0" + resolved "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.0.tgz" + integrity sha512-ngfB8QItUfTFTfHMvKuc2g1W60V1urIgZHqD1JNFZC2tTWXahqf2XvKXqcBS7yZqR7GqkQQZy11y/lNOUWzq7Q== + dependencies: + "@smithy/property-provider" "^3.1.0" + "@smithy/shared-ini-file-loader" "^3.1.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/node-http-handler@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.0.0.tgz" + integrity sha512-3trD4r7NOMygwLbUJo4eodyQuypAWr7uvPnebNJ9a70dQhVn+US8j/lCnvoJS6BXfZeF7PkkkI0DemVJw+n+eQ== + dependencies: + "@smithy/abort-controller" "^3.0.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/querystring-builder" "^3.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/property-provider@^3.1.0": + version "3.1.0" + resolved "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.0.tgz" + integrity sha512-Tj3+oVhqdZgemjCiWjFlADfhvLF4C/uKDuKo7/tlEsRQ9+3emCreR2xndj970QSRSsiCEU8hZW3/8JQu+n5w4Q== + dependencies: + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/protocol-http@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.0.0.tgz" + integrity sha512-qOQZOEI2XLWRWBO9AgIYuHuqjZ2csyr8/IlgFDHDNuIgLAMRx2Bl8ck5U5D6Vh9DPdoaVpuzwWMa0xcdL4O/AQ== + dependencies: + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/querystring-builder@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.0.tgz" + integrity sha512-bW8Fi0NzyfkE0TmQphDXr1AmBDbK01cA4C1Z7ggwMAU5RDz5AAv/KmoRwzQAS0kxXNf/D2ALTEgwK0U2c4LtRg== + dependencies: + "@smithy/types" "^3.0.0" + "@smithy/util-uri-escape" "^3.0.0" + tslib "^2.6.2" + +"@smithy/querystring-parser@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.0.tgz" + integrity sha512-UzHwthk0UEccV4dHzPySnBy34AWw3V9lIqUTxmozQ+wPDAO9csCWMfOLe7V9A2agNYy7xE+Pb0S6K/J23JSzfQ== + dependencies: + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/service-error-classification@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.0.tgz" + integrity sha512-3BsBtOUt2Gsnc3X23ew+r2M71WwtpHfEDGhHYHSDg6q1t8FrWh15jT25DLajFV1H+PpxAJ6gqe9yYeRUsmSdFA== + dependencies: + "@smithy/types" "^3.0.0" + +"@smithy/shared-ini-file-loader@^3.1.0": + version "3.1.0" + resolved "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.0.tgz" + integrity sha512-dAM7wSX0NR3qTNyGVN/nwwpEDzfV9T/3AN2eABExWmda5VqZKSsjlINqomO5hjQWGv+IIkoXfs3u2vGSNz8+Rg== + dependencies: + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/signature-v4@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-3.0.0.tgz" + integrity sha512-kXFOkNX+BQHe2qnLxpMEaCRGap9J6tUGLzc3A9jdn+nD4JdMwCKTJ+zFwQ20GkY+mAXGatyTw3HcoUlR39HwmA== + dependencies: + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/types" "^3.0.0" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-middleware" "^3.0.0" + "@smithy/util-uri-escape" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/smithy-client@^3.1.1": + version "3.1.1" + resolved "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.1.tgz" + integrity sha512-tj4Ku7MpzZR8cmVuPcSbrLFVxmptWktmJMwST/uIEq4sarabEdF8CbmQdYB7uJ/X51Qq2EYwnRsoS7hdR4B7rA== + dependencies: + "@smithy/middleware-endpoint" "^3.0.1" + "@smithy/middleware-stack" "^3.0.0" + "@smithy/protocol-http" "^4.0.0" + "@smithy/types" "^3.0.0" + "@smithy/util-stream" "^3.0.1" + tslib "^2.6.2" + +"@smithy/types@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/types/-/types-3.0.0.tgz" + integrity sha512-VvWuQk2RKFuOr98gFhjca7fkBS+xLLURT8bUjk5XQoV0ZLm7WPwWPPY3/AwzTLuUBDeoKDCthfe1AsTUWaSEhw== + dependencies: + tslib "^2.6.2" + +"@smithy/url-parser@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.0.tgz" + integrity sha512-2XLazFgUu+YOGHtWihB3FSLAfCUajVfNBXGGYjOaVKjLAuAxx3pSBY3hBgLzIgB17haf59gOG3imKqTy8mcrjw== + dependencies: + "@smithy/querystring-parser" "^3.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-base64@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz" + integrity sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ== + dependencies: + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-body-length-browser@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz" + integrity sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-body-length-node@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz" + integrity sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA== + dependencies: + tslib "^2.6.2" + +"@smithy/util-buffer-from@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz" + integrity sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA== + dependencies: + "@smithy/is-array-buffer" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-config-provider@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz" + integrity sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-defaults-mode-browser@^3.0.3": + version "3.0.3" + resolved "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.3.tgz" + integrity sha512-3DFON2bvXJAukJe+qFgPV/rorG7ZD3m4gjCXHD1V5z/tgKQp5MCTCLntrd686tX6tj8Uli3lefWXJudNg5WmCA== + dependencies: + "@smithy/property-provider" "^3.1.0" + "@smithy/smithy-client" "^3.1.1" + "@smithy/types" "^3.0.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@smithy/util-defaults-mode-node@^3.0.3": + version "3.0.3" + resolved "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.3.tgz" + integrity sha512-D0b8GJXecT00baoSQ3Iieu3k3mZ7GY8w1zmg8pdogYrGvWJeLcIclqk2gbkG4K0DaBGWrO6v6r20iwIFfDYrmA== + dependencies: + "@smithy/config-resolver" "^3.0.1" + "@smithy/credential-provider-imds" "^3.1.0" + "@smithy/node-config-provider" "^3.1.0" + "@smithy/property-provider" "^3.1.0" + "@smithy/smithy-client" "^3.1.1" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-endpoints@^2.0.1": + version "2.0.1" + resolved "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.0.1.tgz" + integrity sha512-ZRT0VCOnKlVohfoABMc8lWeQo/JEFuPWctfNRXgTHbyOVssMOLYFUNWukxxiHRGVAhV+n3c0kPW+zUqckjVPEA== + dependencies: + "@smithy/node-config-provider" "^3.1.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-hex-encoding@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz" + integrity sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-middleware@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.0.tgz" + integrity sha512-q5ITdOnV2pXHSVDnKWrwgSNTDBAMHLptFE07ua/5Ty5WJ11bvr0vk2a7agu7qRhrCFRQlno5u3CneU5EELK+DQ== + dependencies: + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-retry@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.0.tgz" + integrity sha512-nK99bvJiziGv/UOKJlDvFF45F00WgPLKVIGUfAK+mDhzVN2hb/S33uW2Tlhg5PVBoqY7tDVqL0zmu4OxAHgo9g== + dependencies: + "@smithy/service-error-classification" "^3.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-stream@^3.0.1": + version "3.0.1" + resolved "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.0.1.tgz" + integrity sha512-7F7VNNhAsfMRA8I986YdOY5fE0/T1/ZjFF6OLsqkvQVNP3vZ/szYDfGCyphb7ioA09r32K/0qbSFfNFU68aSzA== + dependencies: + "@smithy/fetch-http-handler" "^3.0.1" + "@smithy/node-http-handler" "^3.0.0" + "@smithy/types" "^3.0.0" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-uri-escape@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz" + integrity sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg== + dependencies: + tslib "^2.6.2" + +"@smithy/util-utf8@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz" + integrity sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA== + dependencies: + "@smithy/util-buffer-from" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-waiter@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-3.0.0.tgz" + integrity sha512-+fEXJxGDLCoqRKVSmo0auGxaqbiCo+8oph+4auefYjaNxjOLKSY2MxVQfRzo65PaZv4fr+5lWg+au7vSuJJ/zw== + dependencies: + "@smithy/abort-controller" "^3.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + "@tsconfig/node10@^1.0.7": version "1.0.11" resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz" @@ -1562,7 +2648,16 @@ dependencies: "@types/node" "*" -"@types/multer@^1.4.11": +"@types/multer-s3@^3.0.3": + version "3.0.3" + resolved "https://registry.npmjs.org/@types/multer-s3/-/multer-s3-3.0.3.tgz" + integrity sha512-VgWygI9UwyS7loLithUUi0qAMIDWdNrERS2Sb06UuPYiLzKuIFn2NgL7satyl4v8sh/LLoU7DiPanvbQaRg9Yg== + dependencies: + "@aws-sdk/client-s3" "^3.0.0" + "@types/multer" "*" + "@types/node" "*" + +"@types/multer@*", "@types/multer@^1.4.11": version "1.4.11" resolved "https://registry.npmjs.org/@types/multer/-/multer-1.4.11.tgz" integrity sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w== @@ -1774,6 +2869,29 @@ array-flatten@1.1.1: resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + +aws-sdk@^2.1634.0: + version "2.1634.0" + resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1634.0.tgz" + integrity sha512-uSEjzAyGIbfpALzxPYES+hsBK1zuUY/8wSv2mAwijAcQfTMV89jQ4VHI/5KsyyZhDSeS/rV9cn6376KO+HDU2w== + dependencies: + buffer "4.9.2" + events "1.1.1" + ieee754 "1.1.13" + jmespath "0.16.0" + querystring "0.2.0" + sax "1.2.1" + url "0.10.3" + util "^0.12.4" + uuid "8.0.0" + xml2js "0.6.2" + babel-jest@^29.0.0, babel-jest@^29.7.0: version "29.7.0" resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz" @@ -1863,6 +2981,11 @@ balanced-match@^1.0.0: resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-js@^1.0.2: + version "1.5.1" + resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + base64url@3.x.x: version "3.0.1" resolved "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz" @@ -1906,6 +3029,11 @@ body-parser@1.20.2: type-is "~1.6.18" unpipe "1.0.0" +bowser@^2.11.0: + version "2.11.0" + resolved "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" @@ -1955,6 +3083,23 @@ buffer-from@^1.0.0: resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer@4.9.2: + version "4.9.2" + resolved "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +buffer@5.6.0: + version "5.6.0" + resolved "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz" + integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + busboy@^1.0.0: version "1.6.0" resolved "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz" @@ -1967,7 +3112,7 @@ bytes@3.1.2: resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -call-bind@^1.0.7: +call-bind@^1.0.2, call-bind@^1.0.7: version "1.0.7" resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz" integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== @@ -2440,6 +3585,16 @@ etag@~1.8.1: resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +events@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/events/-/events-1.1.1.tgz" + integrity sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw== + +events@3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + execa@^5.0.0: version "5.1.1" resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" @@ -2527,6 +3682,13 @@ fast-json-stable-stringify@^2.1.0, fast-json-stable-stringify@2.x: resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-xml-parser@4.2.5: + version "4.2.5" + resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz" + integrity sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g== + dependencies: + strnum "^1.0.5" + fb-watchman@^2.0.0: version "2.0.2" resolved "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz" @@ -2534,6 +3696,11 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +file-type@^3.3.0: + version "3.9.0" + resolved "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz" + integrity sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA== + fill-range@^7.1.1: version "7.1.1" resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" @@ -2562,6 +3729,13 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" @@ -2722,6 +3896,13 @@ has-symbols@^1.0.3: resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== +has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" @@ -2734,6 +3915,11 @@ hasown@^2.0.0: dependencies: function-bind "^1.1.2" +html-comment-regex@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz" + integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" @@ -2770,6 +3956,11 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +ieee754@^1.1.4, ieee754@1.1.13: + version "1.1.13" + resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz" + integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== + ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz" @@ -2796,7 +3987,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@^2.0.3, inherits@~2.0.3, inherits@2, inherits@2.0.4: +inherits@^2.0.3, inherits@~2.0.3, inherits@~2.0.4, inherits@2, inherits@2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -2806,6 +3997,14 @@ ipaddr.js@1.9.1: resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" @@ -2818,6 +4017,11 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-callable@^1.1.3: + version "1.2.7" + resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + is-core-module@^2.13.0: version "2.13.1" resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz" @@ -2845,6 +4049,13 @@ is-generator-fn@^2.0.0: resolved "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" @@ -2862,12 +4073,19 @@ is-stream@^2.0.0: resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== +is-typed-array@^1.1.3: + version "1.1.13" + resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz" + integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== + dependencies: + which-typed-array "^1.1.14" + is-uuid@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/is-uuid/-/is-uuid-1.0.2.tgz" integrity sha512-tCByphFcJgf2qmiMo5hMCgNAquNSagOetVetDvBXswGkNfoyEMvGH1yDlF8cbZbKnbVBr4Y5/rlpMz9umxyBkQ== -isarray@~1.0.0: +isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== @@ -3295,6 +4513,11 @@ jest-worker@^29.7.0: import-local "^3.0.2" jest-cli "^29.7.0" +jmespath@0.16.0: + version "0.16.0" + resolved "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz" + integrity sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" @@ -3620,6 +4843,16 @@ ms@2.1.3: resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +multer-s3@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/multer-s3/-/multer-s3-3.0.1.tgz" + integrity sha512-BFwSO80a5EW4GJRBdUuSHblz2jhVSAze33ZbnGpcfEicoT0iRolx4kWR+AJV07THFRCQ78g+kelKFdjkCCaXeQ== + dependencies: + "@aws-sdk/lib-storage" "^3.46.0" + file-type "^3.3.0" + html-comment-regex "^1.1.2" + run-parallel "^1.1.6" + multer@^1.4.5-lts.1: version "1.4.5-lts.1" resolved "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz" @@ -3906,6 +5139,11 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +possible-typed-array-names@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz" + integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== + pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz" @@ -3948,6 +5186,11 @@ pstree.remy@^1.1.8: resolved "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz" integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== + pure-rand@^6.0.0: version "6.1.0" resolved "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz" @@ -3960,6 +5203,16 @@ qs@6.11.0: dependencies: side-channel "^1.0.4" +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" + integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + random-bytes@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz" @@ -3998,6 +5251,15 @@ readable-stream@^2.2.2: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^3.5.0: + version "3.6.2" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" @@ -4100,6 +5362,13 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +run-parallel@^1.1.6: + version "1.2.0" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + safe-buffer@^5.0.1, safe-buffer@5.2.1: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" @@ -4125,6 +5394,11 @@ safe-buffer@5.1.2: resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sax@>=0.6.0, sax@1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz" + integrity sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA== + semver@^6.0.0: version "6.3.1" resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" @@ -4270,6 +5544,14 @@ statuses@2.0.1: resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== +stream-browserify@3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz" + integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== + dependencies: + inherits "~2.0.4" + readable-stream "^3.5.0" + streamsearch@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz" @@ -4321,6 +5603,11 @@ strip-json-comments@^3.1.1: resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + superstruct@^1.0.3: version "1.0.4" resolved "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz" @@ -4474,6 +5761,16 @@ ts-node@^10.9.2, ts-node@>=9.0.0: v8-compile-cache-lib "^3.0.1" yn "3.1.1" +tslib@^1.11.1: + version "1.14.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.3.1, tslib@^2.6.2: + version "2.6.3" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== + tsx@^4.11.0: version "4.11.0" resolved "https://registry.npmjs.org/tsx/-/tsx-4.11.0.tgz" @@ -4570,16 +5867,45 @@ update-browserslist-db@^1.0.13: escalade "^3.1.2" picocolors "^1.0.1" +url@0.10.3: + version "0.10.3" + resolved "https://registry.npmjs.org/url/-/url-0.10.3.tgz" + integrity sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ== + dependencies: + punycode "1.3.2" + querystring "0.2.0" + util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +util@^0.12.4: + version "0.12.5" + resolved "https://registry.npmjs.org/util/-/util-0.12.5.tgz" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + utils-merge@^1.0.1, utils-merge@1.0.1, utils-merge@1.x.x: version "1.0.1" resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + +uuid@8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz" + integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" @@ -4624,6 +5950,17 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" +which-typed-array@^1.1.14, which-typed-array@^1.1.2: + version "1.1.15" + resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz" + integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.2" + which@^2.0.1: version "2.0.2" resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" @@ -4660,6 +5997,19 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" +xml2js@0.6.2: + version "0.6.2" + resolved "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz" + integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + xtend@^4.0.0: version "4.0.2" resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" From 0d19009ff826b05e2b65b42c71e37472a738135a Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 6 Jun 2024 07:17:10 +0900 Subject: [PATCH 48/60] =?UTF-8?q?[#M12]=20:=20feat=20:=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C=20=EB=B0=8F=20=EB=B0=B0=ED=8F=AC=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EA=B5=AC=EB=B6=84,=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=EB=B3=80=EC=88=98=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=B4=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 7 ++++++- src/app.ts | 10 +++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 989cf15..019e02e 100644 --- a/.gitignore +++ b/.gitignore @@ -131,4 +131,9 @@ dist # env .env -env.js \ No newline at end of file +.env.production +env.js + +#misc +*.DS_Store +*.pem \ No newline at end of file diff --git a/src/app.ts b/src/app.ts index 4ca2971..76d0083 100644 --- a/src/app.ts +++ b/src/app.ts @@ -17,12 +17,16 @@ import imagesRouter from "./routes/imageRoutes"; import productsRouter from "./routes/productRoutes"; import swaggerOptions from "./swagger/swaggerOptions"; dotenv.config(); - -const JWT_SECRET = process.env.JWT_SECRET || "kingPanda"; - const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); +if (process.env.NODE_ENV !== "production") { + dotenv.config({ path: path.resolve(__dirname, "../.env") }); +} else { + dotenv.config({ path: path.resolve(__dirname, "../.env.production") }); +} +const JWT_SECRET = process.env.JWT_SECRET || "kingPanda"; + const app = express(); const specs = swaggerJsdoc(swaggerOptions); From 96a2d76627b7e8560a6033a39517fc67e901a6c5 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 6 Jun 2024 07:18:55 +0900 Subject: [PATCH 49/60] =?UTF-8?q?[#M12]=20feat=20:=20Presigned=20URL=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=EC=9C=BC=EB=A1=9C=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=97=85=EB=A1=9C=EB=93=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 19464 ++++++++++++++------------- package.json | 124 +- src/controllers/imageController.ts | 6 +- src/routes/imageRoutes.ts | 3 +- src/services/imageService.ts | 46 +- test.html | 38 +- yarn.lock | 33 +- 7 files changed, 9896 insertions(+), 9818 deletions(-) diff --git a/package-lock.json b/package-lock.json index 256a95c..9596111 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9712 +1,9756 @@ { - "name": "QA-sprint-mission", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "dependencies": { - "@aws-sdk/client-s3": "^3.590.0", - "@prisma/client": "^5.4.2", - "aws-sdk": "^2.1634.0", - "bcrypt": "^5.1.1", - "dotenv": "^16.3.1", - "express": "^4.18.2", - "is-email": "^1.0.2", - "is-uuid": "^1.0.2", - "jest-mock-extended": "^3.0.7", - "jsonwebtoken": "^9.0.2", - "moment-timezone": "^0.5.45", - "multer": "^1.4.5-lts.1", - "multer-s3": "^3.0.1", - "passport": "^0.7.0", - "passport-google-oauth20": "^2.0.0", - "prisma": "^5.4.2", - "superstruct": "^1.0.3", - "swagger-jsdoc": "^6.2.8", - "swagger-ui-express": "^5.0.0" - }, - "devDependencies": { - "@babel/preset-env": "^7.24.6", - "@babel/preset-typescript": "^7.24.6", - "@jest/globals": "^29.7.0", - "@types/bcrypt": "^5.0.2", - "@types/cors": "^2.8.17", - "@types/express": "^4.17.21", - "@types/express-session": "^1.18.0", - "@types/is-email": "^1.0.0", - "@types/jsonwebtoken": "^9.0.6", - "@types/morgan": "^1.9.9", - "@types/multer": "^1.4.11", - "@types/multer-s3": "^3.0.3", - "@types/node": "^20.12.13", - "@types/passport": "^1.0.16", - "@types/passport-google-oauth20": "^2.0.16", - "@types/swagger-jsdoc": "^6.0.4", - "@types/swagger-ui-express": "^4.1.6", - "babel-jest": "^29.7.0", - "cors": "^2.8.5", - "express-session": "^1.18.0", - "jest": "^29.7.0", - "morgan": "^1.10.0", - "node-mocks-http": "^1.14.1", - "nodemon": "^3.1.2", - "ts-jest": "^29.1.4", - "ts-node": "^10.9.2", - "tsx": "^4.11.0", - "typescript": "^5.4.5" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@ampproject/remapping/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@apidevtools/json-schema-ref-parser": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", - "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", - "dependencies": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" - } - }, - "node_modules/@apidevtools/openapi-schemas": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", - "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/@apidevtools/swagger-methods": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", - "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==" - }, - "node_modules/@apidevtools/swagger-parser": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", - "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", - "dependencies": { - "@apidevtools/json-schema-ref-parser": "^9.0.6", - "@apidevtools/openapi-schemas": "^2.0.4", - "@apidevtools/swagger-methods": "^3.0.2", - "@jsdevtools/ono": "^7.1.3", - "call-me-maybe": "^1.0.1", - "z-schema": "^5.0.1" - }, - "peerDependencies": { - "openapi-types": ">=7" - } - }, - "node_modules/@aws-crypto/crc32": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", - "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", - "dependencies": { - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/crc32/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/crc32c": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz", - "integrity": "sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==", - "dependencies": { - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/crc32c/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/ie11-detection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", - "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", - "dependencies": { - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/sha1-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz", - "integrity": "sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==", - "dependencies": { - "@aws-crypto/ie11-detection": "^3.0.0", - "@aws-crypto/supports-web-crypto": "^3.0.0", - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/sha1-browser/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/sha256-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", - "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", - "dependencies": { - "@aws-crypto/ie11-detection": "^3.0.0", - "@aws-crypto/sha256-js": "^3.0.0", - "@aws-crypto/supports-web-crypto": "^3.0.0", - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/sha256-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", - "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", - "dependencies": { - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/supports-web-crypto": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", - "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", - "dependencies": { - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/util": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", - "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", - "dependencies": { - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/util/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-sdk/client-s3": { - "version": "3.590.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.590.0.tgz", - "integrity": "sha512-so+pNua0ihsHaSdskw8HCwruoYTAfYSEs3ix4GD1++83C96KaJp3udAutYiCA+84JXg9zitFa7eK7ORJAVZmTw==", - "dependencies": { - "@aws-crypto/sha1-browser": "3.0.0", - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sso-oidc": "3.590.0", - "@aws-sdk/client-sts": "3.590.0", - "@aws-sdk/core": "3.588.0", - "@aws-sdk/credential-provider-node": "3.590.0", - "@aws-sdk/middleware-bucket-endpoint": "3.587.0", - "@aws-sdk/middleware-expect-continue": "3.577.0", - "@aws-sdk/middleware-flexible-checksums": "3.587.0", - "@aws-sdk/middleware-host-header": "3.577.0", - "@aws-sdk/middleware-location-constraint": "3.577.0", - "@aws-sdk/middleware-logger": "3.577.0", - "@aws-sdk/middleware-recursion-detection": "3.577.0", - "@aws-sdk/middleware-sdk-s3": "3.587.0", - "@aws-sdk/middleware-signing": "3.587.0", - "@aws-sdk/middleware-ssec": "3.577.0", - "@aws-sdk/middleware-user-agent": "3.587.0", - "@aws-sdk/region-config-resolver": "3.587.0", - "@aws-sdk/signature-v4-multi-region": "3.587.0", - "@aws-sdk/types": "3.577.0", - "@aws-sdk/util-endpoints": "3.587.0", - "@aws-sdk/util-user-agent-browser": "3.577.0", - "@aws-sdk/util-user-agent-node": "3.587.0", - "@aws-sdk/xml-builder": "3.575.0", - "@smithy/config-resolver": "^3.0.1", - "@smithy/core": "^2.1.1", - "@smithy/eventstream-serde-browser": "^3.0.0", - "@smithy/eventstream-serde-config-resolver": "^3.0.0", - "@smithy/eventstream-serde-node": "^3.0.0", - "@smithy/fetch-http-handler": "^3.0.1", - "@smithy/hash-blob-browser": "^3.0.0", - "@smithy/hash-node": "^3.0.0", - "@smithy/hash-stream-node": "^3.0.0", - "@smithy/invalid-dependency": "^3.0.0", - "@smithy/md5-js": "^3.0.0", - "@smithy/middleware-content-length": "^3.0.0", - "@smithy/middleware-endpoint": "^3.0.1", - "@smithy/middleware-retry": "^3.0.3", - "@smithy/middleware-serde": "^3.0.0", - "@smithy/middleware-stack": "^3.0.0", - "@smithy/node-config-provider": "^3.1.0", - "@smithy/node-http-handler": "^3.0.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/smithy-client": "^3.1.1", - "@smithy/types": "^3.0.0", - "@smithy/url-parser": "^3.0.0", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.3", - "@smithy/util-defaults-mode-node": "^3.0.3", - "@smithy/util-endpoints": "^2.0.1", - "@smithy/util-retry": "^3.0.0", - "@smithy/util-stream": "^3.0.1", - "@smithy/util-utf8": "^3.0.0", - "@smithy/util-waiter": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.590.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.590.0.tgz", - "integrity": "sha512-6xbC6oQVJKBRTyXyR3C15ksUsPOyW4p+uCj7dlKYWGJvh4vGTV8KhZKS53oPG8t4f1+OMJWjr5wKuXRoaFsmhQ==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.588.0", - "@aws-sdk/middleware-host-header": "3.577.0", - "@aws-sdk/middleware-logger": "3.577.0", - "@aws-sdk/middleware-recursion-detection": "3.577.0", - "@aws-sdk/middleware-user-agent": "3.587.0", - "@aws-sdk/region-config-resolver": "3.587.0", - "@aws-sdk/types": "3.577.0", - "@aws-sdk/util-endpoints": "3.587.0", - "@aws-sdk/util-user-agent-browser": "3.577.0", - "@aws-sdk/util-user-agent-node": "3.587.0", - "@smithy/config-resolver": "^3.0.1", - "@smithy/core": "^2.1.1", - "@smithy/fetch-http-handler": "^3.0.1", - "@smithy/hash-node": "^3.0.0", - "@smithy/invalid-dependency": "^3.0.0", - "@smithy/middleware-content-length": "^3.0.0", - "@smithy/middleware-endpoint": "^3.0.1", - "@smithy/middleware-retry": "^3.0.3", - "@smithy/middleware-serde": "^3.0.0", - "@smithy/middleware-stack": "^3.0.0", - "@smithy/node-config-provider": "^3.1.0", - "@smithy/node-http-handler": "^3.0.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/smithy-client": "^3.1.1", - "@smithy/types": "^3.0.0", - "@smithy/url-parser": "^3.0.0", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.3", - "@smithy/util-defaults-mode-node": "^3.0.3", - "@smithy/util-endpoints": "^2.0.1", - "@smithy/util-middleware": "^3.0.0", - "@smithy/util-retry": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.590.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.590.0.tgz", - "integrity": "sha512-3yCLPjq6WFfDpdUJKk/gSz4eAPDTjVknXaveMPi2QoVBCshneOnJsV16uNKlpVF1frTHrrDRfKYmbaVh6nFBvQ==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.590.0", - "@aws-sdk/core": "3.588.0", - "@aws-sdk/credential-provider-node": "3.590.0", - "@aws-sdk/middleware-host-header": "3.577.0", - "@aws-sdk/middleware-logger": "3.577.0", - "@aws-sdk/middleware-recursion-detection": "3.577.0", - "@aws-sdk/middleware-user-agent": "3.587.0", - "@aws-sdk/region-config-resolver": "3.587.0", - "@aws-sdk/types": "3.577.0", - "@aws-sdk/util-endpoints": "3.587.0", - "@aws-sdk/util-user-agent-browser": "3.577.0", - "@aws-sdk/util-user-agent-node": "3.587.0", - "@smithy/config-resolver": "^3.0.1", - "@smithy/core": "^2.1.1", - "@smithy/fetch-http-handler": "^3.0.1", - "@smithy/hash-node": "^3.0.0", - "@smithy/invalid-dependency": "^3.0.0", - "@smithy/middleware-content-length": "^3.0.0", - "@smithy/middleware-endpoint": "^3.0.1", - "@smithy/middleware-retry": "^3.0.3", - "@smithy/middleware-serde": "^3.0.0", - "@smithy/middleware-stack": "^3.0.0", - "@smithy/node-config-provider": "^3.1.0", - "@smithy/node-http-handler": "^3.0.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/smithy-client": "^3.1.1", - "@smithy/types": "^3.0.0", - "@smithy/url-parser": "^3.0.0", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.3", - "@smithy/util-defaults-mode-node": "^3.0.3", - "@smithy/util-endpoints": "^2.0.1", - "@smithy/util-middleware": "^3.0.0", - "@smithy/util-retry": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-sts": { - "version": "3.590.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.590.0.tgz", - "integrity": "sha512-f4R1v1LSn4uLYZ5qj4DyL6gp7PXXzJeJsm2seheiJX+53LSF5L7XSDnQVtX1p9Tevv0hp2YUWUTg6QYwIVSuGg==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sso-oidc": "3.590.0", - "@aws-sdk/core": "3.588.0", - "@aws-sdk/credential-provider-node": "3.590.0", - "@aws-sdk/middleware-host-header": "3.577.0", - "@aws-sdk/middleware-logger": "3.577.0", - "@aws-sdk/middleware-recursion-detection": "3.577.0", - "@aws-sdk/middleware-user-agent": "3.587.0", - "@aws-sdk/region-config-resolver": "3.587.0", - "@aws-sdk/types": "3.577.0", - "@aws-sdk/util-endpoints": "3.587.0", - "@aws-sdk/util-user-agent-browser": "3.577.0", - "@aws-sdk/util-user-agent-node": "3.587.0", - "@smithy/config-resolver": "^3.0.1", - "@smithy/core": "^2.1.1", - "@smithy/fetch-http-handler": "^3.0.1", - "@smithy/hash-node": "^3.0.0", - "@smithy/invalid-dependency": "^3.0.0", - "@smithy/middleware-content-length": "^3.0.0", - "@smithy/middleware-endpoint": "^3.0.1", - "@smithy/middleware-retry": "^3.0.3", - "@smithy/middleware-serde": "^3.0.0", - "@smithy/middleware-stack": "^3.0.0", - "@smithy/node-config-provider": "^3.1.0", - "@smithy/node-http-handler": "^3.0.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/smithy-client": "^3.1.1", - "@smithy/types": "^3.0.0", - "@smithy/url-parser": "^3.0.0", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.3", - "@smithy/util-defaults-mode-node": "^3.0.3", - "@smithy/util-endpoints": "^2.0.1", - "@smithy/util-middleware": "^3.0.0", - "@smithy/util-retry": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/core": { - "version": "3.588.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.588.0.tgz", - "integrity": "sha512-O1c2+9ce46Z+iiid+W3iC1IvPbfIo5ev9CBi54GdNB9SaI8/3+f8MJcux0D6c9toCF0ArMersN/gp8ek57e9uQ==", - "dependencies": { - "@smithy/core": "^2.1.1", - "@smithy/protocol-http": "^4.0.0", - "@smithy/signature-v4": "^3.0.0", - "@smithy/smithy-client": "^3.1.1", - "@smithy/types": "^3.0.0", - "fast-xml-parser": "4.2.5", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.587.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.587.0.tgz", - "integrity": "sha512-Hyg/5KFECIk2k5o8wnVEiniV86yVkhn5kzITUydmNGCkXdBFHMHRx6hleQ1bqwJHbBskyu8nbYamzcwymmGwmw==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/property-provider": "^3.1.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.587.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.587.0.tgz", - "integrity": "sha512-Su1SRWVRCuR1e32oxX3C1V4c5hpPN20WYcRfdcr2wXwHqSvys5DrnmuCC+JoEnS/zt3adUJhPliTqpfKgSdMrA==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/fetch-http-handler": "^3.0.1", - "@smithy/node-http-handler": "^3.0.0", - "@smithy/property-provider": "^3.1.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/smithy-client": "^3.1.1", - "@smithy/types": "^3.0.0", - "@smithy/util-stream": "^3.0.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.590.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.590.0.tgz", - "integrity": "sha512-Y5cFciAK38VIvRgZeND7HvFNR32thGtQb8Xop6cMn33FC78uwcRIu9Hc9699XTclCZqz4+Xl1WU+dZ+rnFn2AA==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.587.0", - "@aws-sdk/credential-provider-http": "3.587.0", - "@aws-sdk/credential-provider-process": "3.587.0", - "@aws-sdk/credential-provider-sso": "3.590.0", - "@aws-sdk/credential-provider-web-identity": "3.587.0", - "@aws-sdk/types": "3.577.0", - "@smithy/credential-provider-imds": "^3.1.0", - "@smithy/property-provider": "^3.1.0", - "@smithy/shared-ini-file-loader": "^3.1.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.590.0" - } - }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.590.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.590.0.tgz", - "integrity": "sha512-Ky38mNFoXobGrDQ11P3dU1e+q1nRJ7eZl8l15KUpvZCe/hOudbxQi/epQrCazD/gRYV2fTyczdLlZzB5ZZ8DhQ==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.587.0", - "@aws-sdk/credential-provider-http": "3.587.0", - "@aws-sdk/credential-provider-ini": "3.590.0", - "@aws-sdk/credential-provider-process": "3.587.0", - "@aws-sdk/credential-provider-sso": "3.590.0", - "@aws-sdk/credential-provider-web-identity": "3.587.0", - "@aws-sdk/types": "3.577.0", - "@smithy/credential-provider-imds": "^3.1.0", - "@smithy/property-provider": "^3.1.0", - "@smithy/shared-ini-file-loader": "^3.1.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.587.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.587.0.tgz", - "integrity": "sha512-V4xT3iCqkF8uL6QC4gqBJg/2asd/damswP1h9HCfqTllmPWzImS+8WD3VjgTLw5b0KbTy+ZdUhKc0wDnyzkzxg==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/property-provider": "^3.1.0", - "@smithy/shared-ini-file-loader": "^3.1.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.590.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.590.0.tgz", - "integrity": "sha512-v+0j/I+je9okfwXsgmLppmwIE+TuMp5WqLz7r7PHz9KjzLyKaKTDvfllFD+8oPpBqnmOWiJ9qTGPkrfhB7a/fQ==", - "dependencies": { - "@aws-sdk/client-sso": "3.590.0", - "@aws-sdk/token-providers": "3.587.0", - "@aws-sdk/types": "3.577.0", - "@smithy/property-provider": "^3.1.0", - "@smithy/shared-ini-file-loader": "^3.1.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.587.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.587.0.tgz", - "integrity": "sha512-XqIx/I2PG7kyuw3WjAP9wKlxy8IvFJwB8asOFT1xPFoVfZYKIogjG9oLP5YiRtfvDkWIztHmg5MlVv3HdJDGRw==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/property-provider": "^3.1.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.587.0" - } - }, - "node_modules/@aws-sdk/lib-storage": { - "version": "3.590.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.590.0.tgz", - "integrity": "sha512-GPR9Kg8N/wM3BCtsj/Bk8k9OIshGMdMmTWgVg+fdLnP5KHH+OMNfvF9aw7JHWjY5c9sM4wKYceBGWNLVSw+lPQ==", - "dependencies": { - "@smithy/abort-controller": "^3.0.0", - "@smithy/middleware-endpoint": "^3.0.1", - "@smithy/smithy-client": "^3.1.1", - "buffer": "5.6.0", - "events": "3.3.0", - "stream-browserify": "3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-s3": "^3.590.0" - } - }, - "node_modules/@aws-sdk/lib-storage/node_modules/buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "node_modules/@aws-sdk/lib-storage/node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/@aws-sdk/middleware-bucket-endpoint": { - "version": "3.587.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.587.0.tgz", - "integrity": "sha512-HkFXLPl8pr6BH/Q0JpOESqEKL0ZK3sk7aSZ1S6GE4RXET7H5R94THULXqQFZzD48gZcyFooO/yNKZTqrZFaWKg==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@aws-sdk/util-arn-parser": "3.568.0", - "@smithy/node-config-provider": "^3.1.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/types": "^3.0.0", - "@smithy/util-config-provider": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/middleware-expect-continue": { - "version": "3.577.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.577.0.tgz", - "integrity": "sha512-6dPp8Tv4F0of4un5IAyG6q++GrRrNQQ4P2NAMB1W0VO4JoEu1C8GievbbDLi88TFIFmtKpnHB0ODCzwnoe8JsA==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.587.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.587.0.tgz", - "integrity": "sha512-URMwp/budDvKhIvZ4a6zIBfFTun/iDlPWXqsGKYjEtHt8jz27OSjCZtDtIeqW4WTBdKL8KZgQcl+DdaE5M1qiQ==", - "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@aws-crypto/crc32c": "3.0.0", - "@aws-sdk/types": "3.577.0", - "@smithy/is-array-buffer": "^3.0.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/types": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.577.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.577.0.tgz", - "integrity": "sha512-9ca5MJz455CODIVXs0/sWmJm7t3QO4EUa1zf8pE8grLpzf0J94bz/skDWm37Pli13T3WaAQBHCTiH2gUVfCsWg==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/middleware-location-constraint": { - "version": "3.577.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.577.0.tgz", - "integrity": "sha512-DKPTD2D2s+t2QUo/IXYtVa/6Un8GZ+phSTBkyBNx2kfZz4Kwavhl/JJzSqTV3GfCXkVdFu7CrjoX7BZ6qWeTUA==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.577.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.577.0.tgz", - "integrity": "sha512-aPFGpGjTZcJYk+24bg7jT4XdIp42mFXSuPt49lw5KygefLyJM/sB0bKKqPYYivW0rcuZ9brQ58eZUNthrzYAvg==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.577.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.577.0.tgz", - "integrity": "sha512-pn3ZVEd2iobKJlR3H+bDilHjgRnNrQ6HMmK9ZzZw89Ckn3Dcbv48xOv4RJvu0aU8SDLl/SNCxppKjeLDTPGBNA==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.587.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.587.0.tgz", - "integrity": "sha512-vtXTGEiw1E9Fax4LmcU2Z208gbrC8ShrdsSLmGcRPpu5NPOGBFBSDG5sy5EDNClrFxIl/Le8coQnD0EDBtx+uQ==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@aws-sdk/util-arn-parser": "3.568.0", - "@smithy/node-config-provider": "^3.1.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/signature-v4": "^3.0.0", - "@smithy/smithy-client": "^3.1.1", - "@smithy/types": "^3.0.0", - "@smithy/util-config-provider": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/middleware-signing": { - "version": "3.587.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.587.0.tgz", - "integrity": "sha512-tiZaTDj4RvhXGRAlncFn7CSEfL3iNPO67WSaxAq+Ls5j1VgczPhu5262cWONNoMgth3nXR1hhLC4ITSl/a6AzA==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/property-provider": "^3.1.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/signature-v4": "^3.0.0", - "@smithy/types": "^3.0.0", - "@smithy/util-middleware": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/middleware-ssec": { - "version": "3.577.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.577.0.tgz", - "integrity": "sha512-i2BPJR+rp8xmRVIGc0h1kDRFcM2J9GnClqqpc+NLSjmYadlcg4mPklisz9HzwFVcRPJ5XcGf3U4BYs5G8+iTyg==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.587.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.587.0.tgz", - "integrity": "sha512-SyDomN+IOrygLucziG7/nOHkjUXES5oH5T7p8AboO8oakMQJdnudNXiYWTicQWO52R51U6CR27rcMPTGeMedYA==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@aws-sdk/util-endpoints": "3.587.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.587.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.587.0.tgz", - "integrity": "sha512-93I7IPZtulZQoRK+O20IJ4a1syWwYPzoO2gc3v+/GNZflZPV3QJXuVbIm0pxBsu0n/mzKGUKqSOLPIaN098HcQ==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/node-config-provider": "^3.1.0", - "@smithy/types": "^3.0.0", - "@smithy/util-config-provider": "^3.0.0", - "@smithy/util-middleware": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.587.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.587.0.tgz", - "integrity": "sha512-TR9+ZSjdXvXUz54ayHcCihhcvxI9W7102J1OK6MrLgBlPE7uRhAx42BR9L5lLJ86Xj3LuqPWf//o9d/zR9WVIg==", - "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.587.0", - "@aws-sdk/types": "3.577.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/signature-v4": "^3.0.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.587.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.587.0.tgz", - "integrity": "sha512-ULqhbnLy1hmJNRcukANBWJmum3BbjXnurLPSFXoGdV0llXYlG55SzIla2VYqdveQEEjmsBuTZdFvXAtNpmS5Zg==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/property-provider": "^3.1.0", - "@smithy/shared-ini-file-loader": "^3.1.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sso-oidc": "^3.587.0" - } - }, - "node_modules/@aws-sdk/types": { - "version": "3.577.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.577.0.tgz", - "integrity": "sha512-FT2JZES3wBKN/alfmhlo+3ZOq/XJ0C7QOZcDNrpKjB0kqYoKjhVKZ/Hx6ArR0czkKfHzBBEs6y40ebIHx2nSmA==", - "dependencies": { - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/util-arn-parser": { - "version": "3.568.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz", - "integrity": "sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.587.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.587.0.tgz", - "integrity": "sha512-8I1HG6Em8wQWqKcRW6m358mqebRVNpL8XrrEoT4In7xqkKkmYtHRNVYP6lcmiQh5pZ/c/FXu8dSchuFIWyEtqQ==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/types": "^3.0.0", - "@smithy/util-endpoints": "^2.0.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/util-locate-window": { - "version": "3.568.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz", - "integrity": "sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.577.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.577.0.tgz", - "integrity": "sha512-zEAzHgR6HWpZOH7xFgeJLc6/CzMcx4nxeQolZxVZoB5pPaJd3CjyRhZN0xXeZB0XIRCWmb4yJBgyiugXLNMkLA==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/types": "^3.0.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.587.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.587.0.tgz", - "integrity": "sha512-Pnl+DUe/bvnbEEDHP3iVJrOtE3HbFJBPgsD6vJ+ml/+IYk1Eq49jEG+EHZdNTPz3SDG0kbp2+7u41MKYJHR/iQ==", - "dependencies": { - "@aws-sdk/types": "3.577.0", - "@smithy/node-config-provider": "^3.1.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } - } - }, - "node_modules/@aws-sdk/util-utf8-browser": { - "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", - "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", - "dependencies": { - "tslib": "^2.3.1" - } - }, - "node_modules/@aws-sdk/xml-builder": { - "version": "3.575.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.575.0.tgz", - "integrity": "sha512-cWgAwmbFYNCFzPwxL705+lWps0F3ZvOckufd2KKoEZUmtpVw9/txUXNrPySUXSmRTSRhoatIMABNfStWR043bQ==", - "dependencies": { - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz", - "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==", - "dependencies": { - "@babel/highlight": "^7.24.6", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.6.tgz", - "integrity": "sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.6.tgz", - "integrity": "sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ==", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.6", - "@babel/generator": "^7.24.6", - "@babel/helper-compilation-targets": "^7.24.6", - "@babel/helper-module-transforms": "^7.24.6", - "@babel/helpers": "^7.24.6", - "@babel/parser": "^7.24.6", - "@babel/template": "^7.24.6", - "@babel/traverse": "^7.24.6", - "@babel/types": "^7.24.6", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/core/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.6.tgz", - "integrity": "sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==", - "dependencies": { - "@babel/types": "^7.24.6", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz", - "integrity": "sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.6.tgz", - "integrity": "sha512-+wnfqc5uHiMYtvRX7qu80Toef8BXeh4HHR1SPeonGb1SKPniNEd4a/nlaJJMv/OIEYvIVavvo0yR7u10Gqz0Iw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz", - "integrity": "sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==", - "dependencies": { - "@babel/compat-data": "^7.24.6", - "@babel/helper-validator-option": "^7.24.6", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.6.tgz", - "integrity": "sha512-djsosdPJVZE6Vsw3kk7IPRWethP94WHGOhQTc67SNXE0ZzMhHgALw8iGmYS0TD1bbMM0VDROy43od7/hN6WYcA==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.6", - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-function-name": "^7.24.6", - "@babel/helper-member-expression-to-functions": "^7.24.6", - "@babel/helper-optimise-call-expression": "^7.24.6", - "@babel/helper-replace-supers": "^7.24.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.6.tgz", - "integrity": "sha512-C875lFBIWWwyv6MHZUG9HmRrlTDgOsLWZfYR0nW69gaKJNe0/Mpxx5r0EID2ZdHQkdUmQo2t0uNckTL08/1BgA==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.6", - "regexpu-core": "^5.3.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz", - "integrity": "sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz", - "integrity": "sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==", - "dependencies": { - "@babel/template": "^7.24.6", - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz", - "integrity": "sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==", - "dependencies": { - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.6.tgz", - "integrity": "sha512-OTsCufZTxDUsv2/eDXanw/mUZHWOxSbEmC3pP8cgjcy5rgeVPWWMStnv274DV60JtHxTk0adT0QrCzC4M9NWGg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz", - "integrity": "sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==", - "dependencies": { - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz", - "integrity": "sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-module-imports": "^7.24.6", - "@babel/helper-simple-access": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", - "@babel/helper-validator-identifier": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.6.tgz", - "integrity": "sha512-3SFDJRbx7KuPRl8XDUr8O7GAEB8iGyWPjLKJh/ywP/Iy9WOmEfMrsWbaZpvBu2HSYn4KQygIsz0O7m8y10ncMA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.6.tgz", - "integrity": "sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.6.tgz", - "integrity": "sha512-1Qursq9ArRZPAMOZf/nuzVW8HgJLkTB9y9LfP4lW2MVp4e9WkLJDovfKBxoDcCk6VuzIxyqWHyBoaCtSRP10yg==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.6", - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-wrap-function": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.6.tgz", - "integrity": "sha512-mRhfPwDqDpba8o1F8ESxsEkJMQkUF8ZIWrAc0FtWhxnjfextxMWxr22RtFizxxSYLjVHDeMgVsRq8BBZR2ikJQ==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-member-expression-to-functions": "^7.24.6", - "@babel/helper-optimise-call-expression": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz", - "integrity": "sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==", - "dependencies": { - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.6.tgz", - "integrity": "sha512-jhbbkK3IUKc4T43WadP96a27oYti9gEf1LdyGSP2rHGH77kwLwfhO7TgwnWvxxQVmke0ImmCSS47vcuxEMGD3Q==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", - "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", - "dependencies": { - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz", - "integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz", - "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz", - "integrity": "sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.6.tgz", - "integrity": "sha512-f1JLrlw/jbiNfxvdrfBgio/gRBk3yTAEJWirpAkiJG2Hb22E7cEYKHWo0dFPTv/niPovzIdPdEDetrv6tC6gPQ==", - "dev": true, - "dependencies": { - "@babel/helper-function-name": "^7.24.6", - "@babel/template": "^7.24.6", - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.6.tgz", - "integrity": "sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==", - "dependencies": { - "@babel/template": "^7.24.6", - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz", - "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.6", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", - "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.6.tgz", - "integrity": "sha512-bYndrJ6Ph6Ar+GaB5VAc0JPoP80bQCm4qon6JEzXfRl5QZyQ8Ur1K6k7htxWmPA5z+k7JQvaMUrtXlqclWYzKw==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.6.tgz", - "integrity": "sha512-iVuhb6poq5ikqRq2XWU6OQ+R5o9wF+r/or9CeUyovgptz0UlnK4/seOQ1Istu/XybYjAhQv1FRSSfHHufIku5Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.6.tgz", - "integrity": "sha512-c8TER5xMDYzzFcGqOEp9l4hvB7dcbhcGjcLVwxWfe4P5DOafdwjsBJZKsmv+o3aXh7NhopvayQIovHrh2zSRUQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", - "@babel/plugin-transform-optional-chaining": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.6.tgz", - "integrity": "sha512-z8zEjYmwBUHN/pCF3NuWBhHQjJCrd33qAi8MgANfMrAvn72k2cImT8VjK9LJFu4ysOLJqhfkYYb3MvwANRUNZQ==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.6.tgz", - "integrity": "sha512-BE6o2BogJKJImTmGpkmOic4V0hlRRxVtzqxiSPa8TIFxyhi4EFjHm08nq1M4STK4RytuLMgnSz0/wfflvGFNOg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.6.tgz", - "integrity": "sha512-D+CfsVZousPXIdudSII7RGy52+dYRtbyKAZcvtQKq/NpsivyMVduepzcLqG5pMBugtMdedxdC8Ramdpcne9ZWQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.6.tgz", - "integrity": "sha512-lWfvAIFNWMlCsU0DRUun2GpFwZdGTukLaHJqRh1JRb80NdAP5Sb1HDHB5X9P9OtgZHQl089UzQkpYlBq2VTPRw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.6.tgz", - "integrity": "sha512-TzCtxGgVTEJWWwcYwQhCIQ6WaKlo80/B+Onsk4RRCcYqpYGFcG9etPW94VToGte5AAcxRrhjPUFvUS3Y2qKi4A==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.6.tgz", - "integrity": "sha512-jSSSDt4ZidNMggcLx8SaKsbGNEfIl0PHx/4mFEulorE7bpYLbN0d3pDW3eJ7Y5Z3yPhy3L3NaPCYyTUY7TuugQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.6.tgz", - "integrity": "sha512-VEP2o4iR2DqQU6KPgizTW2mnMx6BG5b5O9iQdrW9HesLkv8GIA8x2daXBQxw1MrsIkFQGA/iJ204CKoQ8UcnAA==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-remap-async-to-generator": "^7.24.6", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.6.tgz", - "integrity": "sha512-NTBA2SioI3OsHeIn6sQmhvXleSl9T70YY/hostQLveWs0ic+qvbA3fa0kwAwQ0OA/XGaAerNZRQGJyRfhbJK4g==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-remap-async-to-generator": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.6.tgz", - "integrity": "sha512-XNW7jolYHW9CwORrZgA/97tL/k05qe/HL0z/qqJq1mdWhwwCM6D4BJBV7wAz9HgFziN5dTOG31znkVIzwxv+vw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.6.tgz", - "integrity": "sha512-S/t1Xh4ehW7sGA7c1j/hiOBLnEYCp/c2sEG4ZkL8kI1xX9tW2pqJTCHKtdhe/jHKt8nG0pFCrDHUXd4DvjHS9w==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.6.tgz", - "integrity": "sha512-j6dZ0Z2Z2slWLR3kt9aOmSIrBvnntWjMDN/TVcMPxhXMLmJVqX605CBRlcGI4b32GMbfifTEsdEjGjiE+j/c3A==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.6.tgz", - "integrity": "sha512-1QSRfoPI9RoLRa8Mnakc6v3e0gJxiZQTYrMfLn+mD0sz5+ndSzwymp2hDcYJTyT0MOn0yuWzj8phlIvO72gTHA==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.6.tgz", - "integrity": "sha512-+fN+NO2gh8JtRmDSOB6gaCVo36ha8kfCW1nMq2Gc0DABln0VcHN4PrALDvF5/diLzIRKptC7z/d7Lp64zk92Fg==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.6", - "@babel/helper-compilation-targets": "^7.24.6", - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-function-name": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-replace-supers": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.6.tgz", - "integrity": "sha512-cRzPobcfRP0ZtuIEkA8QzghoUpSB3X3qSH5W2+FzG+VjWbJXExtx0nbRqwumdBN1x/ot2SlTNQLfBCnPdzp6kg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/template": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.6.tgz", - "integrity": "sha512-YLW6AE5LQpk5npNXL7i/O+U9CE4XsBCuRPgyjl1EICZYKmcitV+ayuuUGMJm2lC1WWjXYszeTnIxF/dq/GhIZQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.6.tgz", - "integrity": "sha512-rCXPnSEKvkm/EjzOtLoGvKseK+dS4kZwx1HexO3BtRtgL0fQ34awHn34aeSHuXtZY2F8a1X8xqBBPRtOxDVmcA==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.6.tgz", - "integrity": "sha512-/8Odwp/aVkZwPFJMllSbawhDAO3UJi65foB00HYnK/uXvvCPm0TAXSByjz1mpRmp0q6oX2SIxpkUOpPFHk7FLA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.6.tgz", - "integrity": "sha512-vpq8SSLRTBLOHUZHSnBqVo0AKX3PBaoPs2vVzYVWslXDTDIpwAcCDtfhUcHSQQoYoUvcFPTdC8TZYXu9ZnLT/w==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.6.tgz", - "integrity": "sha512-EemYpHtmz0lHE7hxxxYEuTYOOBZ43WkDgZ4arQ4r+VX9QHuNZC+WH3wUWmRNvR8ECpTRne29aZV6XO22qpOtdA==", - "dev": true, - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.6.tgz", - "integrity": "sha512-inXaTM1SVrIxCkIJ5gqWiozHfFMStuGbGJAxZFBoHcRRdDP0ySLb3jH6JOwmfiinPwyMZqMBX+7NBDCO4z0NSA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.6.tgz", - "integrity": "sha512-n3Sf72TnqK4nw/jziSqEl1qaWPbCRw2CziHH+jdRYvw4J6yeCzsj4jdw8hIntOEeDGTmHVe2w4MVL44PN0GMzg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.6.tgz", - "integrity": "sha512-sOajCu6V0P1KPljWHKiDq6ymgqB+vfo3isUS4McqW1DZtvSVU2v/wuMhmRmkg3sFoq6GMaUUf8W4WtoSLkOV/Q==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.24.6", - "@babel/helper-function-name": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.6.tgz", - "integrity": "sha512-Uvgd9p2gUnzYJxVdBLcU0KurF8aVhkmVyMKW4MIY1/BByvs3EBpv45q01o7pRTVmTvtQq5zDlytP3dcUgm7v9w==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.6.tgz", - "integrity": "sha512-f2wHfR2HF6yMj+y+/y07+SLqnOSwRp8KYLpQKOzS58XLVlULhXbiYcygfXQxJlMbhII9+yXDwOUFLf60/TL5tw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.6.tgz", - "integrity": "sha512-EKaWvnezBCMkRIHxMJSIIylzhqK09YpiJtDbr2wsXTwnO0TxyjMUkaw4RlFIZMIS0iDj0KyIg7H7XCguHu/YDA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.6.tgz", - "integrity": "sha512-9g8iV146szUo5GWgXpRbq/GALTnY+WnNuRTuRHWWFfWGbP9ukRL0aO/jpu9dmOPikclkxnNsjY8/gsWl6bmZJQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.6.tgz", - "integrity": "sha512-eAGogjZgcwqAxhyFgqghvoHRr+EYRQPFjUXrTYKBRb5qPnAVxOOglaxc4/byHqjvq/bqO2F3/CGwTHsgKJYHhQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.6.tgz", - "integrity": "sha512-JEV8l3MHdmmdb7S7Cmx6rbNEjRCgTQMZxllveHO0mx6uiclB0NflCawlQQ6+o5ZrwjUBYPzHm2XoK4wqGVUFuw==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-simple-access": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.6.tgz", - "integrity": "sha512-xg1Z0J5JVYxtpX954XqaaAT6NpAY6LtZXvYFCJmGFJWwtlz2EmJoR8LycFRGNE8dBKizGWkGQZGegtkV8y8s+w==", - "dev": true, - "dependencies": { - "@babel/helper-hoist-variables": "^7.24.6", - "@babel/helper-module-transforms": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-validator-identifier": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.6.tgz", - "integrity": "sha512-esRCC/KsSEUvrSjv5rFYnjZI6qv4R1e/iHQrqwbZIoRJqk7xCvEUiN7L1XrmW5QSmQe3n1XD88wbgDTWLbVSyg==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.6.tgz", - "integrity": "sha512-6DneiCiu91wm3YiNIGDWZsl6GfTTbspuj/toTEqLh9d4cx50UIzSdg+T96p8DuT7aJOBRhFyaE9ZvTHkXrXr6Q==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.6.tgz", - "integrity": "sha512-f8liz9JG2Va8A4J5ZBuaSdwfPqN6axfWRK+y66fjKYbwf9VBLuq4WxtinhJhvp1w6lamKUwLG0slK2RxqFgvHA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.6.tgz", - "integrity": "sha512-+QlAiZBMsBK5NqrBWFXCYeXyiU1y7BQ/OYaiPAcQJMomn5Tyg+r5WuVtyEuvTbpV7L25ZSLfE+2E9ywj4FD48A==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.6.tgz", - "integrity": "sha512-6voawq8T25Jvvnc4/rXcWZQKKxUNZcKMS8ZNrjxQqoRFernJJKjE3s18Qo6VFaatG5aiX5JV1oPD7DbJhn0a4Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.6.tgz", - "integrity": "sha512-OKmi5wiMoRW5Smttne7BwHM8s/fb5JFs+bVGNSeHWzwZkWXWValR1M30jyXo1s/RaqgwwhEC62u4rFH/FBcBPg==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.6.tgz", - "integrity": "sha512-N/C76ihFKlZgKfdkEYKtaRUtXZAgK7sOY4h2qrbVbVTXPrKGIi8aww5WGe/+Wmg8onn8sr2ut6FXlsbu/j6JHg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-replace-supers": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.6.tgz", - "integrity": "sha512-L5pZ+b3O1mSzJ71HmxSCmTVd03VOT2GXOigug6vDYJzE5awLI7P1g0wFcdmGuwSDSrQ0L2rDOe/hHws8J1rv3w==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.6.tgz", - "integrity": "sha512-cHbqF6l1QP11OkYTYQ+hhVx1E017O5ZcSPXk9oODpqhcAD1htsWG2NpHrrhthEO2qZomLK0FXS+u7NfrkF5aOQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.6.tgz", - "integrity": "sha512-ST7guE8vLV+vI70wmAxuZpIKzVjvFX9Qs8bl5w6tN/6gOypPWUmMQL2p7LJz5E63vEGrDhAiYetniJFyBH1RkA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.6.tgz", - "integrity": "sha512-T9LtDI0BgwXOzyXrvgLTT8DFjCC/XgWLjflczTLXyvxbnSR/gpv0hbmzlHE/kmh9nOvlygbamLKRo6Op4yB6aw==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.6.tgz", - "integrity": "sha512-Qu/ypFxCY5NkAnEhCF86Mvg3NSabKsh/TPpBVswEdkGl7+FbsYHy1ziRqJpwGH4thBdQHh8zx+z7vMYmcJ7iaQ==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.6", - "@babel/helper-create-class-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.6.tgz", - "integrity": "sha512-oARaglxhRsN18OYsnPTpb8TcKQWDYNsPNmTnx5++WOAsUJ0cSC/FZVlIJCKvPbU4yn/UXsS0551CFKJhN0CaMw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.6.tgz", - "integrity": "sha512-SMDxO95I8WXRtXhTAc8t/NFQUT7VYbIWwJCJgEli9ml4MhqUMh4S6hxgH6SmAC3eAQNWCDJFxcFeEt9w2sDdXg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "regenerator-transform": "^0.15.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.6.tgz", - "integrity": "sha512-DcrgFXRRlK64dGE0ZFBPD5egM2uM8mgfrvTMOSB2yKzOtjpGegVYkzh3s1zZg1bBck3nkXiaOamJUqK3Syk+4A==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.6.tgz", - "integrity": "sha512-xnEUvHSMr9eOWS5Al2YPfc32ten7CXdH7Zwyyk7IqITg4nX61oHj+GxpNvl+y5JHjfN3KXE2IV55wAWowBYMVw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.6.tgz", - "integrity": "sha512-h/2j7oIUDjS+ULsIrNZ6/TKG97FgmEk1PXryk/HQq6op4XUUUwif2f69fJrzK0wza2zjCS1xhXmouACaWV5uPA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.6.tgz", - "integrity": "sha512-fN8OcTLfGmYv7FnDrsjodYBo1DhPL3Pze/9mIIE2MGCT1KgADYIOD7rEglpLHZj8PZlC/JFX5WcD+85FLAQusw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.6.tgz", - "integrity": "sha512-BJbEqJIcKwrqUP+KfUIkxz3q8VzXe2R8Wv8TaNgO1cx+nNavxn/2+H8kp9tgFSOL6wYPPEgFvU6IKS4qoGqhmg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.6.tgz", - "integrity": "sha512-IshCXQ+G9JIFJI7bUpxTE/oA2lgVLAIK8q1KdJNoPXOpvRaNjMySGuvLfBw/Xi2/1lLo953uE8hyYSDW3TSYig==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.6.tgz", - "integrity": "sha512-H0i+hDLmaYYSt6KU9cZE0gb3Cbssa/oxWis7PX4ofQzbvsfix9Lbh8SRk7LCPDlLWJHUiFeHU0qRRpF/4Zv7mQ==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.6", - "@babel/helper-create-class-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/plugin-syntax-typescript": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.6.tgz", - "integrity": "sha512-bKl3xxcPbkQQo5eX9LjjDpU2xYHeEeNQbOhj0iPvetSzA+Tu9q/o5lujF4Sek60CM6MgYvOS/DJuwGbiEYAnLw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.6.tgz", - "integrity": "sha512-8EIgImzVUxy15cZiPii9GvLZwsy7Vxc+8meSlR3cXFmBIl5W5Tn9LGBf7CDKkHj4uVfNXCJB8RsVfnmY61iedA==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.6.tgz", - "integrity": "sha512-pssN6ExsvxaKU638qcWb81RrvvgZom3jDgU/r5xFZ7TONkZGFf4MhI2ltMb8OcQWhHyxgIavEU+hgqtbKOmsPA==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.6.tgz", - "integrity": "sha512-quiMsb28oXWIDK0gXLALOJRXLgICLiulqdZGOaPPd0vRT7fQp74NtdADAVu+D8s00C+0Xs0MxVP0VKF/sZEUgw==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.6.tgz", - "integrity": "sha512-CrxEAvN7VxfjOG8JNF2Y/eMqMJbZPZ185amwGUBp8D9USK90xQmv7dLdFSa+VbD7fdIqcy/Mfv7WtzG8+/qxKg==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.24.6", - "@babel/helper-compilation-targets": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-validator-option": "^7.24.6", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.6", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.6", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.6", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.24.6", - "@babel/plugin-syntax-import-attributes": "^7.24.6", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.24.6", - "@babel/plugin-transform-async-generator-functions": "^7.24.6", - "@babel/plugin-transform-async-to-generator": "^7.24.6", - "@babel/plugin-transform-block-scoped-functions": "^7.24.6", - "@babel/plugin-transform-block-scoping": "^7.24.6", - "@babel/plugin-transform-class-properties": "^7.24.6", - "@babel/plugin-transform-class-static-block": "^7.24.6", - "@babel/plugin-transform-classes": "^7.24.6", - "@babel/plugin-transform-computed-properties": "^7.24.6", - "@babel/plugin-transform-destructuring": "^7.24.6", - "@babel/plugin-transform-dotall-regex": "^7.24.6", - "@babel/plugin-transform-duplicate-keys": "^7.24.6", - "@babel/plugin-transform-dynamic-import": "^7.24.6", - "@babel/plugin-transform-exponentiation-operator": "^7.24.6", - "@babel/plugin-transform-export-namespace-from": "^7.24.6", - "@babel/plugin-transform-for-of": "^7.24.6", - "@babel/plugin-transform-function-name": "^7.24.6", - "@babel/plugin-transform-json-strings": "^7.24.6", - "@babel/plugin-transform-literals": "^7.24.6", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.6", - "@babel/plugin-transform-member-expression-literals": "^7.24.6", - "@babel/plugin-transform-modules-amd": "^7.24.6", - "@babel/plugin-transform-modules-commonjs": "^7.24.6", - "@babel/plugin-transform-modules-systemjs": "^7.24.6", - "@babel/plugin-transform-modules-umd": "^7.24.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.6", - "@babel/plugin-transform-new-target": "^7.24.6", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.6", - "@babel/plugin-transform-numeric-separator": "^7.24.6", - "@babel/plugin-transform-object-rest-spread": "^7.24.6", - "@babel/plugin-transform-object-super": "^7.24.6", - "@babel/plugin-transform-optional-catch-binding": "^7.24.6", - "@babel/plugin-transform-optional-chaining": "^7.24.6", - "@babel/plugin-transform-parameters": "^7.24.6", - "@babel/plugin-transform-private-methods": "^7.24.6", - "@babel/plugin-transform-private-property-in-object": "^7.24.6", - "@babel/plugin-transform-property-literals": "^7.24.6", - "@babel/plugin-transform-regenerator": "^7.24.6", - "@babel/plugin-transform-reserved-words": "^7.24.6", - "@babel/plugin-transform-shorthand-properties": "^7.24.6", - "@babel/plugin-transform-spread": "^7.24.6", - "@babel/plugin-transform-sticky-regex": "^7.24.6", - "@babel/plugin-transform-template-literals": "^7.24.6", - "@babel/plugin-transform-typeof-symbol": "^7.24.6", - "@babel/plugin-transform-unicode-escapes": "^7.24.6", - "@babel/plugin-transform-unicode-property-regex": "^7.24.6", - "@babel/plugin-transform-unicode-regex": "^7.24.6", - "@babel/plugin-transform-unicode-sets-regex": "^7.24.6", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.4", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.31.0", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-typescript": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.6.tgz", - "integrity": "sha512-U10aHPDnokCFRXgyT/MaIRTivUu2K/mu0vJlwRS9LxJmJet+PFQNKpggPyFCUtC6zWSBPjvxjnpNkAn3Uw2m5w==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-validator-option": "^7.24.6", - "@babel/plugin-syntax-jsx": "^7.24.6", - "@babel/plugin-transform-modules-commonjs": "^7.24.6", - "@babel/plugin-transform-typescript": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true - }, - "node_modules/@babel/runtime": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.6.tgz", - "integrity": "sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.6.tgz", - "integrity": "sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==", - "dependencies": { - "@babel/code-frame": "^7.24.6", - "@babel/parser": "^7.24.6", - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.6.tgz", - "integrity": "sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==", - "dependencies": { - "@babel/code-frame": "^7.24.6", - "@babel/generator": "^7.24.6", - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-function-name": "^7.24.6", - "@babel/helper-hoist-variables": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", - "@babel/parser": "^7.24.6", - "@babel/types": "^7.24.6", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/traverse/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/@babel/types": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz", - "integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==", - "dependencies": { - "@babel/helper-string-parser": "^7.24.6", - "@babel/helper-validator-identifier": "^7.24.6", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "devOptional": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", - "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "devOptional": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@jsdevtools/ono": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" - }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", - "dependencies": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@prisma/client": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.14.0.tgz", - "integrity": "sha512-akMSuyvLKeoU4LeyBAUdThP/uhVP3GuLygFE3MlYzaCb3/J8SfsYBE5PkaFuLuVpLyA6sFoW+16z/aPhNAESqg==", - "hasInstallScript": true, - "engines": { - "node": ">=16.13" - }, - "peerDependencies": { - "prisma": "*" - }, - "peerDependenciesMeta": { - "prisma": { - "optional": true - } - } - }, - "node_modules/@prisma/debug": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.14.0.tgz", - "integrity": "sha512-iq56qBZuFfX3fCxoxT8gBX33lQzomBU0qIUaEj1RebsKVz1ob/BVH1XSBwwwvRVtZEV1b7Fxx2eVu34Ge/mg3w==" - }, - "node_modules/@prisma/engines": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.14.0.tgz", - "integrity": "sha512-lgxkKZ6IEygVcw6IZZUlPIfLQ9hjSYAtHjZ5r64sCLDgVzsPFCi2XBBJgzPMkOQ5RHzUD4E/dVdpn9+ez8tk1A==", - "hasInstallScript": true, - "dependencies": { - "@prisma/debug": "5.14.0", - "@prisma/engines-version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", - "@prisma/fetch-engine": "5.14.0", - "@prisma/get-platform": "5.14.0" - } - }, - "node_modules/@prisma/engines-version": { - "version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48.tgz", - "integrity": "sha512-ip6pNkRo1UxWv+6toxNcYvItNYaqQjXdFNGJ+Nuk2eYtRoEdoF13wxo7/jsClJFFenMPVNVqXQDV0oveXnR1cA==" - }, - "node_modules/@prisma/fetch-engine": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.14.0.tgz", - "integrity": "sha512-VrheA9y9DMURK5vu8OJoOgQpxOhas3qF0IBHJ8G/0X44k82kc8E0w98HCn2nhnbOOMwbWsJWXfLC2/F8n5u0gQ==", - "dependencies": { - "@prisma/debug": "5.14.0", - "@prisma/engines-version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", - "@prisma/get-platform": "5.14.0" - } - }, - "node_modules/@prisma/get-platform": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.14.0.tgz", - "integrity": "sha512-/yAyBvcEjRv41ynZrhdrPtHgk47xLRRq/o5eWGcUpBJ1YrUZTYB8EoPiopnP7iQrMATK8stXQdPOoVlrzuTQZw==", - "dependencies": { - "@prisma/debug": "5.14.0" - } - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@smithy/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-p6GlFGBt9K4MYLu72YuJ523NVR4A8oHlC5M2JO6OmQqN8kAc/uh1JqLE+FizTokrSJGg0CSvC+BrsmGzKtsZKA==", - "dependencies": { - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/chunked-blob-reader": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-3.0.0.tgz", - "integrity": "sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA==", - "dependencies": { - "tslib": "^2.6.2" - } - }, - "node_modules/@smithy/chunked-blob-reader-native": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz", - "integrity": "sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg==", - "dependencies": { - "@smithy/util-base64": "^3.0.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@smithy/config-resolver": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.1.tgz", - "integrity": "sha512-hbkYJc20SBDz2qqLzttjI/EqXemtmWk0ooRznLsiXp3066KQRTvuKHa7U4jCZCJq6Dozqvy0R1/vNESC9inPJg==", - "dependencies": { - "@smithy/node-config-provider": "^3.1.0", - "@smithy/types": "^3.0.0", - "@smithy/util-config-provider": "^3.0.0", - "@smithy/util-middleware": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/core": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.2.0.tgz", - "integrity": "sha512-ygLZSSKgt9bR8HAxR9mK+U5obvAJBr6zlQuhN5soYWx/amjDoQN4dTkydTypgKe6rIbUjTILyLU+W5XFwXr4kg==", - "dependencies": { - "@smithy/middleware-endpoint": "^3.0.1", - "@smithy/middleware-retry": "^3.0.3", - "@smithy/middleware-serde": "^3.0.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/smithy-client": "^3.1.1", - "@smithy/types": "^3.0.0", - "@smithy/util-middleware": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.1.0.tgz", - "integrity": "sha512-q4A4d38v8pYYmseu/jTS3Z5I3zXlEOe5Obi+EJreVKgSVyWUHOd7/yaVCinC60QG4MRyCs98tcxBH1IMC0bu7Q==", - "dependencies": { - "@smithy/node-config-provider": "^3.1.0", - "@smithy/property-provider": "^3.1.0", - "@smithy/types": "^3.0.0", - "@smithy/url-parser": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/eventstream-codec": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.0.0.tgz", - "integrity": "sha512-PUtyEA0Oik50SaEFCZ0WPVtF9tz/teze2fDptW6WRXl+RrEenH8UbEjudOz8iakiMl3lE3lCVqYf2Y+znL8QFQ==", - "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^3.0.0", - "@smithy/util-hex-encoding": "^3.0.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@smithy/eventstream-serde-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.0.tgz", - "integrity": "sha512-NB7AFiPN4NxP/YCAnrvYR18z2/ZsiHiF7VtG30gshO9GbFrIb1rC8ep4NGpJSWrz6P64uhPXeo4M0UsCLnZKqw==", - "dependencies": { - "@smithy/eventstream-serde-universal": "^3.0.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.0.tgz", - "integrity": "sha512-RUQG3vQ3LX7peqqHAbmayhgrF5aTilPnazinaSGF1P0+tgM3vvIRWPHmlLIz2qFqB9LqFIxditxc8O2Z6psrRw==", - "dependencies": { - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-node": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.0.tgz", - "integrity": "sha512-baRPdMBDMBExZXIUAoPGm/hntixjt/VFpU6+VmCyiYJYzRHRxoaI1MN+5XE+hIS8AJ2GCHLMFEIOLzq9xx1EgQ==", - "dependencies": { - "@smithy/eventstream-serde-universal": "^3.0.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-universal": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.0.tgz", - "integrity": "sha512-HNFfShmotWGeAoW4ujP8meV9BZavcpmerDbPIjkJbxKbN8RsUcpRQ/2OyIxWNxXNH2GWCAxuSB7ynmIGJlQ3Dw==", - "dependencies": { - "@smithy/eventstream-codec": "^3.0.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/fetch-http-handler": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.0.1.tgz", - "integrity": "sha512-uaH74i5BDj+rBwoQaXioKpI0SHBJFtOVwzrCpxZxphOW0ki5jhj7dXvDMYM2IJem8TpdFvS2iC08sjOblfFGFg==", - "dependencies": { - "@smithy/protocol-http": "^4.0.0", - "@smithy/querystring-builder": "^3.0.0", - "@smithy/types": "^3.0.0", - "@smithy/util-base64": "^3.0.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@smithy/hash-blob-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-3.0.0.tgz", - "integrity": "sha512-/Wbpdg+bwJvW7lxR/zpWAc1/x/YkcqguuF2bAzkJrvXriZu1vm8r+PUdE4syiVwQg7PPR2dXpi3CLBb9qRDaVQ==", - "dependencies": { - "@smithy/chunked-blob-reader": "^3.0.0", - "@smithy/chunked-blob-reader-native": "^3.0.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@smithy/hash-node": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.0.tgz", - "integrity": "sha512-84qXstNemP3XS5jcof0el6+bDfjzuvhJPQTEfro3lgtbCtKgzPm3MgiS6ehXVPjeQ5+JS0HqmTz8f/RYfzHVxw==", - "dependencies": { - "@smithy/types": "^3.0.0", - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/hash-stream-node": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-3.0.0.tgz", - "integrity": "sha512-J0i7de+EgXDEGITD4fxzmMX8CyCNETTIRXlxjMiNUvvu76Xn3GJ31wQR85ynlPk2wI1lqoknAFJaD1fiNDlbIA==", - "dependencies": { - "@smithy/types": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/invalid-dependency": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.0.tgz", - "integrity": "sha512-F6wBBaEFgJzj0s4KUlliIGPmqXemwP6EavgvDqYwCH40O5Xr2iMHvS8todmGVZtuJCorBkXsYLyTu4PuizVq5g==", - "dependencies": { - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@smithy/is-array-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", - "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/md5-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-3.0.0.tgz", - "integrity": "sha512-Tm0vrrVzjlD+6RCQTx7D3Ls58S3FUH1ZCtU1MIh/qQmaOo1H9lMN2as6CikcEwgattnA9SURSdoJJ27xMcEfMA==", - "dependencies": { - "@smithy/types": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@smithy/middleware-content-length": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.0.tgz", - "integrity": "sha512-3C4s4d/iGobgCtk2tnWW6+zSTOBg1PRAm2vtWZLdriwTroFbbWNSr3lcyzHdrQHnEXYCC5K52EbpfodaIUY8sg==", - "dependencies": { - "@smithy/protocol-http": "^4.0.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/middleware-endpoint": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.0.1.tgz", - "integrity": "sha512-lQ/UOdGD4KM5kLZiAl0q8Qy3dPbynvAXKAdXnYlrA1OpaUwr+neSsVokDZpY6ZVb5Yx8jnus29uv6XWpM9P4SQ==", - "dependencies": { - "@smithy/middleware-serde": "^3.0.0", - "@smithy/node-config-provider": "^3.1.0", - "@smithy/shared-ini-file-loader": "^3.1.0", - "@smithy/types": "^3.0.0", - "@smithy/url-parser": "^3.0.0", - "@smithy/util-middleware": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/middleware-retry": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.3.tgz", - "integrity": "sha512-Wve1qzJb83VEU/6q+/I0cQdAkDnuzELC6IvIBwDzUEiGpKqXgX1v10FUuZGbRS6Ov/P+HHthcAoHOJZQvZNAkA==", - "dependencies": { - "@smithy/node-config-provider": "^3.1.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/service-error-classification": "^3.0.0", - "@smithy/smithy-client": "^3.1.1", - "@smithy/types": "^3.0.0", - "@smithy/util-middleware": "^3.0.0", - "@smithy/util-retry": "^3.0.0", - "tslib": "^2.6.2", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/middleware-serde": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.0.tgz", - "integrity": "sha512-I1vKG1foI+oPgG9r7IMY1S+xBnmAn1ISqployvqkwHoSb8VPsngHDTOgYGYBonuOKndaWRUGJZrKYYLB+Ane6w==", - "dependencies": { - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/middleware-stack": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.0.tgz", - "integrity": "sha512-+H0jmyfAyHRFXm6wunskuNAqtj7yfmwFB6Fp37enytp2q047/Od9xetEaUbluyImOlGnGpaVGaVfjwawSr+i6Q==", - "dependencies": { - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/node-config-provider": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.0.tgz", - "integrity": "sha512-ngfB8QItUfTFTfHMvKuc2g1W60V1urIgZHqD1JNFZC2tTWXahqf2XvKXqcBS7yZqR7GqkQQZy11y/lNOUWzq7Q==", - "dependencies": { - "@smithy/property-provider": "^3.1.0", - "@smithy/shared-ini-file-loader": "^3.1.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/node-http-handler": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.0.0.tgz", - "integrity": "sha512-3trD4r7NOMygwLbUJo4eodyQuypAWr7uvPnebNJ9a70dQhVn+US8j/lCnvoJS6BXfZeF7PkkkI0DemVJw+n+eQ==", - "dependencies": { - "@smithy/abort-controller": "^3.0.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/querystring-builder": "^3.0.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/property-provider": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.0.tgz", - "integrity": "sha512-Tj3+oVhqdZgemjCiWjFlADfhvLF4C/uKDuKo7/tlEsRQ9+3emCreR2xndj970QSRSsiCEU8hZW3/8JQu+n5w4Q==", - "dependencies": { - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/protocol-http": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.0.0.tgz", - "integrity": "sha512-qOQZOEI2XLWRWBO9AgIYuHuqjZ2csyr8/IlgFDHDNuIgLAMRx2Bl8ck5U5D6Vh9DPdoaVpuzwWMa0xcdL4O/AQ==", - "dependencies": { - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/querystring-builder": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.0.tgz", - "integrity": "sha512-bW8Fi0NzyfkE0TmQphDXr1AmBDbK01cA4C1Z7ggwMAU5RDz5AAv/KmoRwzQAS0kxXNf/D2ALTEgwK0U2c4LtRg==", - "dependencies": { - "@smithy/types": "^3.0.0", - "@smithy/util-uri-escape": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/querystring-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.0.tgz", - "integrity": "sha512-UzHwthk0UEccV4dHzPySnBy34AWw3V9lIqUTxmozQ+wPDAO9csCWMfOLe7V9A2agNYy7xE+Pb0S6K/J23JSzfQ==", - "dependencies": { - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/service-error-classification": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.0.tgz", - "integrity": "sha512-3BsBtOUt2Gsnc3X23ew+r2M71WwtpHfEDGhHYHSDg6q1t8FrWh15jT25DLajFV1H+PpxAJ6gqe9yYeRUsmSdFA==", - "dependencies": { - "@smithy/types": "^3.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/shared-ini-file-loader": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.0.tgz", - "integrity": "sha512-dAM7wSX0NR3qTNyGVN/nwwpEDzfV9T/3AN2eABExWmda5VqZKSsjlINqomO5hjQWGv+IIkoXfs3u2vGSNz8+Rg==", - "dependencies": { - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/signature-v4": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-3.0.0.tgz", - "integrity": "sha512-kXFOkNX+BQHe2qnLxpMEaCRGap9J6tUGLzc3A9jdn+nD4JdMwCKTJ+zFwQ20GkY+mAXGatyTw3HcoUlR39HwmA==", - "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "@smithy/types": "^3.0.0", - "@smithy/util-hex-encoding": "^3.0.0", - "@smithy/util-middleware": "^3.0.0", - "@smithy/util-uri-escape": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/smithy-client": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.1.tgz", - "integrity": "sha512-tj4Ku7MpzZR8cmVuPcSbrLFVxmptWktmJMwST/uIEq4sarabEdF8CbmQdYB7uJ/X51Qq2EYwnRsoS7hdR4B7rA==", - "dependencies": { - "@smithy/middleware-endpoint": "^3.0.1", - "@smithy/middleware-stack": "^3.0.0", - "@smithy/protocol-http": "^4.0.0", - "@smithy/types": "^3.0.0", - "@smithy/util-stream": "^3.0.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/types": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.0.0.tgz", - "integrity": "sha512-VvWuQk2RKFuOr98gFhjca7fkBS+xLLURT8bUjk5XQoV0ZLm7WPwWPPY3/AwzTLuUBDeoKDCthfe1AsTUWaSEhw==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/url-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.0.tgz", - "integrity": "sha512-2XLazFgUu+YOGHtWihB3FSLAfCUajVfNBXGGYjOaVKjLAuAxx3pSBY3hBgLzIgB17haf59gOG3imKqTy8mcrjw==", - "dependencies": { - "@smithy/querystring-parser": "^3.0.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@smithy/util-base64": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", - "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", - "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-body-length-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", - "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", - "dependencies": { - "tslib": "^2.6.2" - } - }, - "node_modules/@smithy/util-body-length-node": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", - "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-buffer-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", - "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", - "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-config-provider": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", - "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.3.tgz", - "integrity": "sha512-3DFON2bvXJAukJe+qFgPV/rorG7ZD3m4gjCXHD1V5z/tgKQp5MCTCLntrd686tX6tj8Uli3lefWXJudNg5WmCA==", - "dependencies": { - "@smithy/property-provider": "^3.1.0", - "@smithy/smithy-client": "^3.1.1", - "@smithy/types": "^3.0.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.3.tgz", - "integrity": "sha512-D0b8GJXecT00baoSQ3Iieu3k3mZ7GY8w1zmg8pdogYrGvWJeLcIclqk2gbkG4K0DaBGWrO6v6r20iwIFfDYrmA==", - "dependencies": { - "@smithy/config-resolver": "^3.0.1", - "@smithy/credential-provider-imds": "^3.1.0", - "@smithy/node-config-provider": "^3.1.0", - "@smithy/property-provider": "^3.1.0", - "@smithy/smithy-client": "^3.1.1", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@smithy/util-endpoints": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.0.1.tgz", - "integrity": "sha512-ZRT0VCOnKlVohfoABMc8lWeQo/JEFuPWctfNRXgTHbyOVssMOLYFUNWukxxiHRGVAhV+n3c0kPW+zUqckjVPEA==", - "dependencies": { - "@smithy/node-config-provider": "^3.1.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-hex-encoding": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", - "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-middleware": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.0.tgz", - "integrity": "sha512-q5ITdOnV2pXHSVDnKWrwgSNTDBAMHLptFE07ua/5Ty5WJ11bvr0vk2a7agu7qRhrCFRQlno5u3CneU5EELK+DQ==", - "dependencies": { - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-retry": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.0.tgz", - "integrity": "sha512-nK99bvJiziGv/UOKJlDvFF45F00WgPLKVIGUfAK+mDhzVN2hb/S33uW2Tlhg5PVBoqY7tDVqL0zmu4OxAHgo9g==", - "dependencies": { - "@smithy/service-error-classification": "^3.0.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-stream": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.0.1.tgz", - "integrity": "sha512-7F7VNNhAsfMRA8I986YdOY5fE0/T1/ZjFF6OLsqkvQVNP3vZ/szYDfGCyphb7ioA09r32K/0qbSFfNFU68aSzA==", - "dependencies": { - "@smithy/fetch-http-handler": "^3.0.1", - "@smithy/node-http-handler": "^3.0.0", - "@smithy/types": "^3.0.0", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-hex-encoding": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-uri-escape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", - "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", - "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", - "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-waiter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-3.0.0.tgz", - "integrity": "sha512-+fEXJxGDLCoqRKVSmo0auGxaqbiCo+8oph+4auefYjaNxjOLKSY2MxVQfRzo65PaZv4fr+5lWg+au7vSuJJ/zw==", - "dependencies": { - "@smithy/abort-controller": "^3.0.0", - "@smithy/types": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "devOptional": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "devOptional": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "devOptional": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "devOptional": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/bcrypt": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", - "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/cors": { - "version": "2.8.17", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", - "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.2.tgz", - "integrity": "sha512-dPSEQElyVJ97BuGduAqQjpBocZWAs0GR94z+ptL7JXQJeJdHw2WBG3EWdFrK36b8Q6j8P4cXOMhgUoi0IIfIsg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/express-session": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.18.0.tgz", - "integrity": "sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA==", - "dev": true, - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true - }, - "node_modules/@types/is-email": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/is-email/-/is-email-1.0.0.tgz", - "integrity": "sha512-b/76ooKpYY/b+oPrOuc/pmM5eag+ZlzctPsKcRCIKs+TFzh0FL58OeXtSPkbXt3uKNK84YCKHmjnoREtwve5Kg==", - "dev": true - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" - }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", - "integrity": "sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true - }, - "node_modules/@types/morgan": { - "version": "1.9.9", - "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.9.tgz", - "integrity": "sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/multer": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.11.tgz", - "integrity": "sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==", - "dev": true, - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/multer-s3": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/multer-s3/-/multer-s3-3.0.3.tgz", - "integrity": "sha512-VgWygI9UwyS7loLithUUi0qAMIDWdNrERS2Sb06UuPYiLzKuIFn2NgL7satyl4v8sh/LLoU7DiPanvbQaRg9Yg==", - "dev": true, - "dependencies": { - "@aws-sdk/client-s3": "^3.0.0", - "@types/multer": "*", - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "20.12.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.13.tgz", - "integrity": "sha512-gBGeanV41c1L171rR7wjbMiEpEI/l5XFQdLLfhr/REwpgDy/4U8y89+i8kRiLzDyZdOkXh+cRaTetUnCYutoXA==", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/oauth": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.5.tgz", - "integrity": "sha512-+oQ3C2Zx6ambINOcdIARF5Z3Tu3x//HipE889/fqo3sgpQZbe9c6ExdQFtN6qlhpR7p83lTZfPJt0tCAW29dog==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/passport": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.16.tgz", - "integrity": "sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A==", - "dev": true, - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/passport-google-oauth20": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.16.tgz", - "integrity": "sha512-ayXK2CJ7uVieqhYOc6k/pIr5pcQxOLB6kBev+QUGS7oEZeTgIs1odDobXRqgfBPvXzl0wXCQHftV5220czZCPA==", - "dev": true, - "dependencies": { - "@types/express": "*", - "@types/passport": "*", - "@types/passport-oauth2": "*" - } - }, - "node_modules/@types/passport-oauth2": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.4.17.tgz", - "integrity": "sha512-ODiAHvso6JcWJ6ZkHHroVp05EHGhqQN533PtFNBkg8Fy5mERDqsr030AX81M0D69ZcaMvhF92SRckEk2B0HYYg==", - "dev": true, - "dependencies": { - "@types/express": "*", - "@types/oauth": "*", - "@types/passport": "*" - } - }, - "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true - }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dev": true, - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" - }, - "node_modules/@types/swagger-jsdoc": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz", - "integrity": "sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ==", - "dev": true - }, - "node_modules/@types/swagger-ui-express": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz", - "integrity": "sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==", - "dev": true, - "dependencies": { - "@types/express": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "devOptional": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", - "devOptional": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agent-base/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/agent-base/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" - }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" - }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "deprecated": "This package is no longer supported.", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "devOptional": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/aws-sdk": { - "version": "2.1634.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1634.0.tgz", - "integrity": "sha512-uSEjzAyGIbfpALzxPYES+hsBK1zuUY/8wSv2mAwijAcQfTMV89jQ4VHI/5KsyyZhDSeS/rV9cn6376KO+HDU2w==", - "hasInstallScript": true, - "dependencies": { - "buffer": "4.9.2", - "events": "1.1.1", - "ieee754": "1.1.13", - "jmespath": "0.16.0", - "querystring": "0.2.0", - "sax": "1.2.1", - "url": "0.10.3", - "util": "^0.12.4", - "uuid": "8.0.0", - "xml2js": "0.6.2" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/aws-sdk/node_modules/uuid": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", - "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", - "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.1", - "core-js-compat": "^3.36.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", - "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/base64url": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", - "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "dev": true, - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/basic-auth/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/bcrypt": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", - "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", - "hasInstallScript": true, - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.11", - "node-addon-api": "^5.0.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/bowser": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001625", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001625.tgz", - "integrity": "sha512-4KE9N2gcRH+HQhpeiRZXd+1niLB/XNLAhSy4z7fI8EzcbcPoAqjNInxVHTiTwWfTIV4w096XG8OtCOCQQKPv3w==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "engines": { - "node": ">=10" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", - "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==" - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/commander": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", - "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" - }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/core-js-compat": { - "version": "3.37.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", - "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", - "dev": true, - "dependencies": { - "browserslist": "^4.23.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "devOptional": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "devOptional": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/electron-to-chromium": { - "version": "1.4.787", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.787.tgz", - "integrity": "sha512-d0EFmtLPjctczO3LogReyM2pbBiiZbnsKnGF+cdZhsYzHm/A0GV7W94kqzLD8SN4O3f3iHlgLUChqghgyznvCQ==" - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express-session": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz", - "integrity": "sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ==", - "dev": true, - "dependencies": { - "cookie": "0.6.0", - "cookie-signature": "1.0.7", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-headers": "~1.0.2", - "parseurl": "~1.3.3", - "safe-buffer": "5.2.1", - "uid-safe": "~2.1.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/express-session/node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-xml-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", - "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", - "funding": [ - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" - }, - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "dependencies": { - "strnum": "^1.0.5" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/file-type": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "deprecated": "This package is no longer supported.", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-tsconfig": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", - "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", - "dev": true, - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/html-comment-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", - "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==" - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/https-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" - }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true - }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dependencies": { - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-email": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-email/-/is-email-1.0.2.tgz", - "integrity": "sha512-UojUgD2EhDTBQ2SGKwrK9edce5phRzgLsP+V5+Uu2Swi+uvjVXgH3zduM3HhT9iaC/9Kq19/TYUbP0jPoi6ioA==" - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dependencies": { - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-uuid": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-uuid/-/is-uuid-1.0.2.tgz", - "integrity": "sha512-tCByphFcJgf2qmiMo5hMCgNAquNSagOetVetDvBXswGkNfoyEMvGH1yDlF8cbZbKnbVBr4Y5/rlpMz9umxyBkQ==" - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", - "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-mock-extended": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/jest-mock-extended/-/jest-mock-extended-3.0.7.tgz", - "integrity": "sha512-7lsKdLFcW9B9l5NzZ66S/yTQ9k8rFtnwYdCNuRU/81fqDWicNDVhitTSPnrGmNeNm0xyw0JHexEOShrIKRCIRQ==", - "dependencies": { - "ts-essentials": "^10.0.0" - }, - "peerDependencies": { - "jest": "^24.0.0 || ^25.0.0 || ^26.0.0 || ^27.0.0 || ^28.0.0 || ^29.0.0", - "typescript": "^3.0.0 || ^4.0.0 || ^5.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", - "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", - "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jmespath": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", - "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/jsonwebtoken/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "engines": { - "node": ">=6" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" - }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "node_modules/lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==" - }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lru-cache/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "devOptional": true - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/moment": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.5.45", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", - "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", - "dependencies": { - "moment": "^2.29.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/morgan": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", - "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", - "dev": true, - "dependencies": { - "basic-auth": "~2.0.1", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-finished": "~2.3.0", - "on-headers": "~1.0.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/morgan/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/multer": { - "version": "1.4.5-lts.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", - "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", - "dependencies": { - "append-field": "^1.0.0", - "busboy": "^1.0.0", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", - "object-assign": "^4.1.1", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/multer-s3": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/multer-s3/-/multer-s3-3.0.1.tgz", - "integrity": "sha512-BFwSO80a5EW4GJRBdUuSHblz2jhVSAze33ZbnGpcfEicoT0iRolx4kWR+AJV07THFRCQ78g+kelKFdjkCCaXeQ==", - "dependencies": { - "@aws-sdk/lib-storage": "^3.46.0", - "file-type": "^3.3.0", - "html-comment-regex": "^1.1.2", - "run-parallel": "^1.1.6" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-s3": "^3.0.0" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" - }, - "node_modules/node-mocks-http": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.14.1.tgz", - "integrity": "sha512-mfXuCGonz0A7uG1FEjnypjm34xegeN5+HI6xeGhYKecfgaZhjsmYoLE9LEFmT+53G1n8IuagPZmVnEL/xNsFaA==", - "dev": true, - "dependencies": { - "@types/express": "^4.17.21", - "@types/node": "^20.10.6", - "accepts": "^1.3.7", - "content-disposition": "^0.5.3", - "depd": "^1.1.0", - "fresh": "^0.5.2", - "merge-descriptors": "^1.0.1", - "methods": "^1.1.2", - "mime": "^1.3.4", - "parseurl": "^1.3.3", - "range-parser": "^1.2.0", - "type-is": "^1.6.18" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/node-mocks-http/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" - }, - "node_modules/nodemon": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.2.tgz", - "integrity": "sha512-/Ib/kloefDy+N0iRTxIUzyGcdW9lzlnca2Jsa5w73bs3npXjg+WInmiX6VY13mIb6SykkthYX/U5t0ukryGqBw==", - "dev": true, - "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": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/nodemon/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/nodemon/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "deprecated": "This package is no longer supported.", - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "node_modules/oauth": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.10.0.tgz", - "integrity": "sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q==" - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/openapi-types": { - "version": "12.1.3", - "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", - "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", - "peer": true - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/passport": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", - "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", - "dependencies": { - "passport-strategy": "1.x.x", - "pause": "0.0.1", - "utils-merge": "^1.0.1" - }, - "engines": { - "node": ">= 0.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jaredhanson" - } - }, - "node_modules/passport-google-oauth20": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", - "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", - "dependencies": { - "passport-oauth2": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passport-oauth2": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.8.0.tgz", - "integrity": "sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA==", - "dependencies": { - "base64url": "3.x.x", - "oauth": "0.10.x", - "passport-strategy": "1.x.x", - "uid2": "0.0.x", - "utils-merge": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jaredhanson" - } - }, - "node_modules/passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "node_modules/pause": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" - }, - "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/prisma": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.14.0.tgz", - "integrity": "sha512-gCNZco7y5XtjrnQYeDJTiVZmT/ncqCr5RY1/Cf8X2wgLRmyh9ayPAGBNziI4qEE4S6SxCH5omQLVo9lmURaJ/Q==", - "hasInstallScript": true, - "dependencies": { - "@prisma/engines": "5.14.0" - }, - "bin": { - "prisma": "build/index.js" - }, - "engines": { - "node": ">=16.13" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" - }, - "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ] - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dev": true, - "dependencies": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "engines": { - "node": ">=10" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" - }, - "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dependencies": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - } - }, - "node_modules/stream-browserify/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" - }, - "node_modules/superstruct": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", - "integrity": "sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/swagger-jsdoc": { - "version": "6.2.8", - "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", - "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", - "dependencies": { - "commander": "6.2.0", - "doctrine": "3.0.0", - "glob": "7.1.6", - "lodash.mergewith": "^4.6.2", - "swagger-parser": "^10.0.3", - "yaml": "2.0.0-1" - }, - "bin": { - "swagger-jsdoc": "bin/swagger-jsdoc.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/swagger-jsdoc/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/swagger-parser": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", - "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", - "dependencies": { - "@apidevtools/swagger-parser": "10.0.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/swagger-ui-dist": { - "version": "5.17.14", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz", - "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==" - }, - "node_modules/swagger-ui-express": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz", - "integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==", - "dependencies": { - "swagger-ui-dist": ">=5.0.0" - }, - "engines": { - "node": ">= v0.10.32" - }, - "peerDependencies": { - "express": ">=4.0.0 || >=5.0.0-beta" - } - }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/touch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", - "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", - "dev": true, - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/ts-essentials": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-10.0.0.tgz", - "integrity": "sha512-77FHNJEyysF9+1s4G6eejuA1lxw7uMchT3ZPy3CIbh7GIunffpshtM8pTe5G6N5dpOzNevqRHew859ceLWVBfw==", - "peerDependencies": { - "typescript": ">=4.5.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/ts-jest": { - "version": "29.1.4", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.4.tgz", - "integrity": "sha512-YiHwDhSvCiItoAgsKtoLFCuakDzDsJ1DLDnSouTaTmdOcOwIkSzbLXduaQ6M5DRVhuZC/NYaaZ/mtHbWMv/S6Q==", - "dev": true, - "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" - }, - "bin": { - "ts-jest": "cli.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/transform": "^29.0.0", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", - "typescript": ">=4.3 <6" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/transform": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } - } - }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "devOptional": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" - }, - "node_modules/tsx": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.11.0.tgz", - "integrity": "sha512-vzGGELOgAupsNVssAmZjbUDfdm/pWP4R+Kg8TVdsonxbXk0bEpE1qh0yV6/QxUVXaVlNemgcPajGdJJ82n3stg==", - "dev": true, - "dependencies": { - "esbuild": "~0.20.2", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" - }, - "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "dev": true, - "dependencies": { - "random-bytes": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/uid2": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", - "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" - }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", - "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "devOptional": true - }, - "node_modules/v8-to-istanbul": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", - "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/validator": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", - "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/xml2js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", - "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yaml": { - "version": "2.0.0-1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", - "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "engines": { - "node": ">=12" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "devOptional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/z-schema": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", - "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", - "dependencies": { - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "validator": "^13.7.0" - }, - "bin": { - "z-schema": "bin/z-schema" - }, - "engines": { - "node": ">=8.0.0" - }, - "optionalDependencies": { - "commander": "^9.4.1" - } - }, - "node_modules/z-schema/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "optional": true, - "engines": { - "node": "^12.20.0 || >=14" - } - } - } + "name": "QA-sprint-mission", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@aws-sdk/client-s3": "^3.590.0", + "@aws-sdk/s3-request-presigner": "^3.591.0", + "@prisma/client": "^5.4.2", + "aws-sdk": "^2.1634.0", + "bcrypt": "^5.1.1", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "is-email": "^1.0.2", + "is-uuid": "^1.0.2", + "jest-mock-extended": "^3.0.7", + "jsonwebtoken": "^9.0.2", + "moment-timezone": "^0.5.45", + "multer": "^1.4.5-lts.1", + "multer-s3": "^3.0.1", + "passport": "^0.7.0", + "passport-google-oauth20": "^2.0.0", + "prisma": "^5.4.2", + "superstruct": "^1.0.3", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.0" + }, + "devDependencies": { + "@babel/preset-env": "^7.24.6", + "@babel/preset-typescript": "^7.24.6", + "@jest/globals": "^29.7.0", + "@types/aws-sdk": "^2.7.0", + "@types/bcrypt": "^5.0.2", + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/express-session": "^1.18.0", + "@types/is-email": "^1.0.0", + "@types/jsonwebtoken": "^9.0.6", + "@types/morgan": "^1.9.9", + "@types/multer": "^1.4.11", + "@types/multer-s3": "^3.0.3", + "@types/node": "^20.12.13", + "@types/passport": "^1.0.16", + "@types/passport-google-oauth20": "^2.0.16", + "@types/swagger-jsdoc": "^6.0.4", + "@types/swagger-ui-express": "^4.1.6", + "babel-jest": "^29.7.0", + "cors": "^2.8.5", + "express-session": "^1.18.0", + "jest": "^29.7.0", + "morgan": "^1.10.0", + "node-mocks-http": "^1.14.1", + "nodemon": "^3.1.2", + "ts-jest": "^29.1.4", + "ts-node": "^10.9.2", + "tsx": "^4.11.0", + "typescript": "^5.4.5" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@ampproject/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", + "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "node_modules/@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==" + }, + "node_modules/@apidevtools/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^9.0.6", + "@apidevtools/openapi-schemas": "^2.0.4", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "call-me-maybe": "^1.0.1", + "z-schema": "^5.0.1" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/crc32/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/crc32c": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz", + "integrity": "sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/crc32c/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/ie11-detection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/sha1-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz", + "integrity": "sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==", + "dependencies": { + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "dependencies": { + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/util/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.590.0.tgz", + "integrity": "sha512-so+pNua0ihsHaSdskw8HCwruoYTAfYSEs3ix4GD1++83C96KaJp3udAutYiCA+84JXg9zitFa7eK7ORJAVZmTw==", + "dependencies": { + "@aws-crypto/sha1-browser": "3.0.0", + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sso-oidc": "3.590.0", + "@aws-sdk/client-sts": "3.590.0", + "@aws-sdk/core": "3.588.0", + "@aws-sdk/credential-provider-node": "3.590.0", + "@aws-sdk/middleware-bucket-endpoint": "3.587.0", + "@aws-sdk/middleware-expect-continue": "3.577.0", + "@aws-sdk/middleware-flexible-checksums": "3.587.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-location-constraint": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-sdk-s3": "3.587.0", + "@aws-sdk/middleware-signing": "3.587.0", + "@aws-sdk/middleware-ssec": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/signature-v4-multi-region": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@aws-sdk/xml-builder": "3.575.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.1.1", + "@smithy/eventstream-serde-browser": "^3.0.0", + "@smithy/eventstream-serde-config-resolver": "^3.0.0", + "@smithy/eventstream-serde-node": "^3.0.0", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-blob-browser": "^3.0.0", + "@smithy/hash-node": "^3.0.0", + "@smithy/hash-stream-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/md5-js": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-stream": "^3.0.1", + "@smithy/util-utf8": "^3.0.0", + "@smithy/util-waiter": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.590.0.tgz", + "integrity": "sha512-6xbC6oQVJKBRTyXyR3C15ksUsPOyW4p+uCj7dlKYWGJvh4vGTV8KhZKS53oPG8t4f1+OMJWjr5wKuXRoaFsmhQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.588.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.1.1", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.590.0.tgz", + "integrity": "sha512-3yCLPjq6WFfDpdUJKk/gSz4eAPDTjVknXaveMPi2QoVBCshneOnJsV16uNKlpVF1frTHrrDRfKYmbaVh6nFBvQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.590.0", + "@aws-sdk/core": "3.588.0", + "@aws-sdk/credential-provider-node": "3.590.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.1.1", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.590.0.tgz", + "integrity": "sha512-f4R1v1LSn4uLYZ5qj4DyL6gp7PXXzJeJsm2seheiJX+53LSF5L7XSDnQVtX1p9Tevv0hp2YUWUTg6QYwIVSuGg==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sso-oidc": "3.590.0", + "@aws-sdk/core": "3.588.0", + "@aws-sdk/credential-provider-node": "3.590.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.1.1", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.588.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.588.0.tgz", + "integrity": "sha512-O1c2+9ce46Z+iiid+W3iC1IvPbfIo5ev9CBi54GdNB9SaI8/3+f8MJcux0D6c9toCF0ArMersN/gp8ek57e9uQ==", + "dependencies": { + "@smithy/core": "^2.1.1", + "@smithy/protocol-http": "^4.0.0", + "@smithy/signature-v4": "^3.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.587.0.tgz", + "integrity": "sha512-Hyg/5KFECIk2k5o8wnVEiniV86yVkhn5kzITUydmNGCkXdBFHMHRx6hleQ1bqwJHbBskyu8nbYamzcwymmGwmw==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.587.0.tgz", + "integrity": "sha512-Su1SRWVRCuR1e32oxX3C1V4c5hpPN20WYcRfdcr2wXwHqSvys5DrnmuCC+JoEnS/zt3adUJhPliTqpfKgSdMrA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/util-stream": "^3.0.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.590.0.tgz", + "integrity": "sha512-Y5cFciAK38VIvRgZeND7HvFNR32thGtQb8Xop6cMn33FC78uwcRIu9Hc9699XTclCZqz4+Xl1WU+dZ+rnFn2AA==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.587.0", + "@aws-sdk/credential-provider-http": "3.587.0", + "@aws-sdk/credential-provider-process": "3.587.0", + "@aws-sdk/credential-provider-sso": "3.590.0", + "@aws-sdk/credential-provider-web-identity": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@smithy/credential-provider-imds": "^3.1.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.590.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.590.0.tgz", + "integrity": "sha512-Ky38mNFoXobGrDQ11P3dU1e+q1nRJ7eZl8l15KUpvZCe/hOudbxQi/epQrCazD/gRYV2fTyczdLlZzB5ZZ8DhQ==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.587.0", + "@aws-sdk/credential-provider-http": "3.587.0", + "@aws-sdk/credential-provider-ini": "3.590.0", + "@aws-sdk/credential-provider-process": "3.587.0", + "@aws-sdk/credential-provider-sso": "3.590.0", + "@aws-sdk/credential-provider-web-identity": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@smithy/credential-provider-imds": "^3.1.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.587.0.tgz", + "integrity": "sha512-V4xT3iCqkF8uL6QC4gqBJg/2asd/damswP1h9HCfqTllmPWzImS+8WD3VjgTLw5b0KbTy+ZdUhKc0wDnyzkzxg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.590.0.tgz", + "integrity": "sha512-v+0j/I+je9okfwXsgmLppmwIE+TuMp5WqLz7r7PHz9KjzLyKaKTDvfllFD+8oPpBqnmOWiJ9qTGPkrfhB7a/fQ==", + "dependencies": { + "@aws-sdk/client-sso": "3.590.0", + "@aws-sdk/token-providers": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.587.0.tgz", + "integrity": "sha512-XqIx/I2PG7kyuw3WjAP9wKlxy8IvFJwB8asOFT1xPFoVfZYKIogjG9oLP5YiRtfvDkWIztHmg5MlVv3HdJDGRw==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.587.0" + } + }, + "node_modules/@aws-sdk/lib-storage": { + "version": "3.590.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.590.0.tgz", + "integrity": "sha512-GPR9Kg8N/wM3BCtsj/Bk8k9OIshGMdMmTWgVg+fdLnP5KHH+OMNfvF9aw7JHWjY5c9sM4wKYceBGWNLVSw+lPQ==", + "dependencies": { + "@smithy/abort-controller": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/smithy-client": "^3.1.1", + "buffer": "5.6.0", + "events": "3.3.0", + "stream-browserify": "3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-s3": "^3.590.0" + } + }, + "node_modules/@aws-sdk/lib-storage/node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/@aws-sdk/lib-storage/node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.587.0.tgz", + "integrity": "sha512-HkFXLPl8pr6BH/Q0JpOESqEKL0ZK3sk7aSZ1S6GE4RXET7H5R94THULXqQFZzD48gZcyFooO/yNKZTqrZFaWKg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-config-provider": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.577.0.tgz", + "integrity": "sha512-6dPp8Tv4F0of4un5IAyG6q++GrRrNQQ4P2NAMB1W0VO4JoEu1C8GievbbDLi88TFIFmtKpnHB0ODCzwnoe8JsA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.587.0.tgz", + "integrity": "sha512-URMwp/budDvKhIvZ4a6zIBfFTun/iDlPWXqsGKYjEtHt8jz27OSjCZtDtIeqW4WTBdKL8KZgQcl+DdaE5M1qiQ==", + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@aws-crypto/crc32c": "3.0.0", + "@aws-sdk/types": "3.577.0", + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.577.0.tgz", + "integrity": "sha512-9ca5MJz455CODIVXs0/sWmJm7t3QO4EUa1zf8pE8grLpzf0J94bz/skDWm37Pli13T3WaAQBHCTiH2gUVfCsWg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.577.0.tgz", + "integrity": "sha512-DKPTD2D2s+t2QUo/IXYtVa/6Un8GZ+phSTBkyBNx2kfZz4Kwavhl/JJzSqTV3GfCXkVdFu7CrjoX7BZ6qWeTUA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.577.0.tgz", + "integrity": "sha512-aPFGpGjTZcJYk+24bg7jT4XdIp42mFXSuPt49lw5KygefLyJM/sB0bKKqPYYivW0rcuZ9brQ58eZUNthrzYAvg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.577.0.tgz", + "integrity": "sha512-pn3ZVEd2iobKJlR3H+bDilHjgRnNrQ6HMmK9ZzZw89Ckn3Dcbv48xOv4RJvu0aU8SDLl/SNCxppKjeLDTPGBNA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.587.0.tgz", + "integrity": "sha512-vtXTGEiw1E9Fax4LmcU2Z208gbrC8ShrdsSLmGcRPpu5NPOGBFBSDG5sy5EDNClrFxIl/Le8coQnD0EDBtx+uQ==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/signature-v4": "^3.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/util-config-provider": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.587.0.tgz", + "integrity": "sha512-tiZaTDj4RvhXGRAlncFn7CSEfL3iNPO67WSaxAq+Ls5j1VgczPhu5262cWONNoMgth3nXR1hhLC4ITSl/a6AzA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/signature-v4": "^3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.577.0.tgz", + "integrity": "sha512-i2BPJR+rp8xmRVIGc0h1kDRFcM2J9GnClqqpc+NLSjmYadlcg4mPklisz9HzwFVcRPJ5XcGf3U4BYs5G8+iTyg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.587.0.tgz", + "integrity": "sha512-SyDomN+IOrygLucziG7/nOHkjUXES5oH5T7p8AboO8oakMQJdnudNXiYWTicQWO52R51U6CR27rcMPTGeMedYA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.587.0.tgz", + "integrity": "sha512-93I7IPZtulZQoRK+O20IJ4a1syWwYPzoO2gc3v+/GNZflZPV3QJXuVbIm0pxBsu0n/mzKGUKqSOLPIaN098HcQ==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner": { + "version": "3.591.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.591.0.tgz", + "integrity": "sha512-MDkPKrVC63XxED/vaWa2xkBfUPwKXqP/nVg4TUdjlUCIlP+xSouAYxkQ1aclinCbx8+E932C9kf4kNRQIxhafA==", + "dependencies": { + "@aws-sdk/signature-v4-multi-region": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-format-url": "3.577.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.587.0.tgz", + "integrity": "sha512-TR9+ZSjdXvXUz54ayHcCihhcvxI9W7102J1OK6MrLgBlPE7uRhAx42BR9L5lLJ86Xj3LuqPWf//o9d/zR9WVIg==", + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/signature-v4": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.587.0.tgz", + "integrity": "sha512-ULqhbnLy1hmJNRcukANBWJmum3BbjXnurLPSFXoGdV0llXYlG55SzIla2VYqdveQEEjmsBuTZdFvXAtNpmS5Zg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sso-oidc": "^3.587.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.577.0.tgz", + "integrity": "sha512-FT2JZES3wBKN/alfmhlo+3ZOq/XJ0C7QOZcDNrpKjB0kqYoKjhVKZ/Hx6ArR0czkKfHzBBEs6y40ebIHx2nSmA==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz", + "integrity": "sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.587.0.tgz", + "integrity": "sha512-8I1HG6Em8wQWqKcRW6m358mqebRVNpL8XrrEoT4In7xqkKkmYtHRNVYP6lcmiQh5pZ/c/FXu8dSchuFIWyEtqQ==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "@smithy/util-endpoints": "^2.0.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-format-url": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.577.0.tgz", + "integrity": "sha512-SyEGC2J+y/krFRuPgiF02FmMYhqbiIkOjDE6k4nYLJQRyS6XEAGxZoG+OHeOVEM+bsDgbxokXZiM3XKGu6qFIg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/querystring-builder": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz", + "integrity": "sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.577.0.tgz", + "integrity": "sha512-zEAzHgR6HWpZOH7xFgeJLc6/CzMcx4nxeQolZxVZoB5pPaJd3CjyRhZN0xXeZB0XIRCWmb4yJBgyiugXLNMkLA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.587.0.tgz", + "integrity": "sha512-Pnl+DUe/bvnbEEDHP3iVJrOtE3HbFJBPgsD6vJ+ml/+IYk1Eq49jEG+EHZdNTPz3SDG0kbp2+7u41MKYJHR/iQ==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.575.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.575.0.tgz", + "integrity": "sha512-cWgAwmbFYNCFzPwxL705+lWps0F3ZvOckufd2KKoEZUmtpVw9/txUXNrPySUXSmRTSRhoatIMABNfStWR043bQ==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz", + "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==", + "dependencies": { + "@babel/highlight": "^7.24.6", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.6.tgz", + "integrity": "sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.6.tgz", + "integrity": "sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.6", + "@babel/generator": "^7.24.6", + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helpers": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/template": "^7.24.6", + "@babel/traverse": "^7.24.6", + "@babel/types": "^7.24.6", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.6.tgz", + "integrity": "sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==", + "dependencies": { + "@babel/types": "^7.24.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz", + "integrity": "sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.6.tgz", + "integrity": "sha512-+wnfqc5uHiMYtvRX7qu80Toef8BXeh4HHR1SPeonGb1SKPniNEd4a/nlaJJMv/OIEYvIVavvo0yR7u10Gqz0Iw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz", + "integrity": "sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==", + "dependencies": { + "@babel/compat-data": "^7.24.6", + "@babel/helper-validator-option": "^7.24.6", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.6.tgz", + "integrity": "sha512-djsosdPJVZE6Vsw3kk7IPRWethP94WHGOhQTc67SNXE0ZzMhHgALw8iGmYS0TD1bbMM0VDROy43od7/hN6WYcA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-member-expression-to-functions": "^7.24.6", + "@babel/helper-optimise-call-expression": "^7.24.6", + "@babel/helper-replace-supers": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.6.tgz", + "integrity": "sha512-C875lFBIWWwyv6MHZUG9HmRrlTDgOsLWZfYR0nW69gaKJNe0/Mpxx5r0EID2ZdHQkdUmQo2t0uNckTL08/1BgA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz", + "integrity": "sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz", + "integrity": "sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==", + "dependencies": { + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz", + "integrity": "sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==", + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.6.tgz", + "integrity": "sha512-OTsCufZTxDUsv2/eDXanw/mUZHWOxSbEmC3pP8cgjcy5rgeVPWWMStnv274DV60JtHxTk0adT0QrCzC4M9NWGg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz", + "integrity": "sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==", + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz", + "integrity": "sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-module-imports": "^7.24.6", + "@babel/helper-simple-access": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.6.tgz", + "integrity": "sha512-3SFDJRbx7KuPRl8XDUr8O7GAEB8iGyWPjLKJh/ywP/Iy9WOmEfMrsWbaZpvBu2HSYn4KQygIsz0O7m8y10ncMA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.6.tgz", + "integrity": "sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.6.tgz", + "integrity": "sha512-1Qursq9ArRZPAMOZf/nuzVW8HgJLkTB9y9LfP4lW2MVp4e9WkLJDovfKBxoDcCk6VuzIxyqWHyBoaCtSRP10yg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-wrap-function": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.6.tgz", + "integrity": "sha512-mRhfPwDqDpba8o1F8ESxsEkJMQkUF8ZIWrAc0FtWhxnjfextxMWxr22RtFizxxSYLjVHDeMgVsRq8BBZR2ikJQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-member-expression-to-functions": "^7.24.6", + "@babel/helper-optimise-call-expression": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz", + "integrity": "sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==", + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.6.tgz", + "integrity": "sha512-jhbbkK3IUKc4T43WadP96a27oYti9gEf1LdyGSP2rHGH77kwLwfhO7TgwnWvxxQVmke0ImmCSS47vcuxEMGD3Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", + "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz", + "integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz", + "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz", + "integrity": "sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.6.tgz", + "integrity": "sha512-f1JLrlw/jbiNfxvdrfBgio/gRBk3yTAEJWirpAkiJG2Hb22E7cEYKHWo0dFPTv/niPovzIdPdEDetrv6tC6gPQ==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.24.6", + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.6.tgz", + "integrity": "sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==", + "dependencies": { + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz", + "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.6", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", + "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.6.tgz", + "integrity": "sha512-bYndrJ6Ph6Ar+GaB5VAc0JPoP80bQCm4qon6JEzXfRl5QZyQ8Ur1K6k7htxWmPA5z+k7JQvaMUrtXlqclWYzKw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.6.tgz", + "integrity": "sha512-iVuhb6poq5ikqRq2XWU6OQ+R5o9wF+r/or9CeUyovgptz0UlnK4/seOQ1Istu/XybYjAhQv1FRSSfHHufIku5Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.6.tgz", + "integrity": "sha512-c8TER5xMDYzzFcGqOEp9l4hvB7dcbhcGjcLVwxWfe4P5DOafdwjsBJZKsmv+o3aXh7NhopvayQIovHrh2zSRUQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", + "@babel/plugin-transform-optional-chaining": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.6.tgz", + "integrity": "sha512-z8zEjYmwBUHN/pCF3NuWBhHQjJCrd33qAi8MgANfMrAvn72k2cImT8VjK9LJFu4ysOLJqhfkYYb3MvwANRUNZQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.6.tgz", + "integrity": "sha512-BE6o2BogJKJImTmGpkmOic4V0hlRRxVtzqxiSPa8TIFxyhi4EFjHm08nq1M4STK4RytuLMgnSz0/wfflvGFNOg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.6.tgz", + "integrity": "sha512-D+CfsVZousPXIdudSII7RGy52+dYRtbyKAZcvtQKq/NpsivyMVduepzcLqG5pMBugtMdedxdC8Ramdpcne9ZWQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.6.tgz", + "integrity": "sha512-lWfvAIFNWMlCsU0DRUun2GpFwZdGTukLaHJqRh1JRb80NdAP5Sb1HDHB5X9P9OtgZHQl089UzQkpYlBq2VTPRw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.6.tgz", + "integrity": "sha512-TzCtxGgVTEJWWwcYwQhCIQ6WaKlo80/B+Onsk4RRCcYqpYGFcG9etPW94VToGte5AAcxRrhjPUFvUS3Y2qKi4A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.6.tgz", + "integrity": "sha512-jSSSDt4ZidNMggcLx8SaKsbGNEfIl0PHx/4mFEulorE7bpYLbN0d3pDW3eJ7Y5Z3yPhy3L3NaPCYyTUY7TuugQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.6.tgz", + "integrity": "sha512-VEP2o4iR2DqQU6KPgizTW2mnMx6BG5b5O9iQdrW9HesLkv8GIA8x2daXBQxw1MrsIkFQGA/iJ204CKoQ8UcnAA==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-remap-async-to-generator": "^7.24.6", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.6.tgz", + "integrity": "sha512-NTBA2SioI3OsHeIn6sQmhvXleSl9T70YY/hostQLveWs0ic+qvbA3fa0kwAwQ0OA/XGaAerNZRQGJyRfhbJK4g==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-remap-async-to-generator": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.6.tgz", + "integrity": "sha512-XNW7jolYHW9CwORrZgA/97tL/k05qe/HL0z/qqJq1mdWhwwCM6D4BJBV7wAz9HgFziN5dTOG31znkVIzwxv+vw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.6.tgz", + "integrity": "sha512-S/t1Xh4ehW7sGA7c1j/hiOBLnEYCp/c2sEG4ZkL8kI1xX9tW2pqJTCHKtdhe/jHKt8nG0pFCrDHUXd4DvjHS9w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.6.tgz", + "integrity": "sha512-j6dZ0Z2Z2slWLR3kt9aOmSIrBvnntWjMDN/TVcMPxhXMLmJVqX605CBRlcGI4b32GMbfifTEsdEjGjiE+j/c3A==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.6.tgz", + "integrity": "sha512-1QSRfoPI9RoLRa8Mnakc6v3e0gJxiZQTYrMfLn+mD0sz5+ndSzwymp2hDcYJTyT0MOn0yuWzj8phlIvO72gTHA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.6.tgz", + "integrity": "sha512-+fN+NO2gh8JtRmDSOB6gaCVo36ha8kfCW1nMq2Gc0DABln0VcHN4PrALDvF5/diLzIRKptC7z/d7Lp64zk92Fg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-replace-supers": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.6.tgz", + "integrity": "sha512-cRzPobcfRP0ZtuIEkA8QzghoUpSB3X3qSH5W2+FzG+VjWbJXExtx0nbRqwumdBN1x/ot2SlTNQLfBCnPdzp6kg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/template": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.6.tgz", + "integrity": "sha512-YLW6AE5LQpk5npNXL7i/O+U9CE4XsBCuRPgyjl1EICZYKmcitV+ayuuUGMJm2lC1WWjXYszeTnIxF/dq/GhIZQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.6.tgz", + "integrity": "sha512-rCXPnSEKvkm/EjzOtLoGvKseK+dS4kZwx1HexO3BtRtgL0fQ34awHn34aeSHuXtZY2F8a1X8xqBBPRtOxDVmcA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.6.tgz", + "integrity": "sha512-/8Odwp/aVkZwPFJMllSbawhDAO3UJi65foB00HYnK/uXvvCPm0TAXSByjz1mpRmp0q6oX2SIxpkUOpPFHk7FLA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.6.tgz", + "integrity": "sha512-vpq8SSLRTBLOHUZHSnBqVo0AKX3PBaoPs2vVzYVWslXDTDIpwAcCDtfhUcHSQQoYoUvcFPTdC8TZYXu9ZnLT/w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.6.tgz", + "integrity": "sha512-EemYpHtmz0lHE7hxxxYEuTYOOBZ43WkDgZ4arQ4r+VX9QHuNZC+WH3wUWmRNvR8ECpTRne29aZV6XO22qpOtdA==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.6.tgz", + "integrity": "sha512-inXaTM1SVrIxCkIJ5gqWiozHfFMStuGbGJAxZFBoHcRRdDP0ySLb3jH6JOwmfiinPwyMZqMBX+7NBDCO4z0NSA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.6.tgz", + "integrity": "sha512-n3Sf72TnqK4nw/jziSqEl1qaWPbCRw2CziHH+jdRYvw4J6yeCzsj4jdw8hIntOEeDGTmHVe2w4MVL44PN0GMzg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.6.tgz", + "integrity": "sha512-sOajCu6V0P1KPljWHKiDq6ymgqB+vfo3isUS4McqW1DZtvSVU2v/wuMhmRmkg3sFoq6GMaUUf8W4WtoSLkOV/Q==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.6.tgz", + "integrity": "sha512-Uvgd9p2gUnzYJxVdBLcU0KurF8aVhkmVyMKW4MIY1/BByvs3EBpv45q01o7pRTVmTvtQq5zDlytP3dcUgm7v9w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.6.tgz", + "integrity": "sha512-f2wHfR2HF6yMj+y+/y07+SLqnOSwRp8KYLpQKOzS58XLVlULhXbiYcygfXQxJlMbhII9+yXDwOUFLf60/TL5tw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.6.tgz", + "integrity": "sha512-EKaWvnezBCMkRIHxMJSIIylzhqK09YpiJtDbr2wsXTwnO0TxyjMUkaw4RlFIZMIS0iDj0KyIg7H7XCguHu/YDA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.6.tgz", + "integrity": "sha512-9g8iV146szUo5GWgXpRbq/GALTnY+WnNuRTuRHWWFfWGbP9ukRL0aO/jpu9dmOPikclkxnNsjY8/gsWl6bmZJQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.6.tgz", + "integrity": "sha512-eAGogjZgcwqAxhyFgqghvoHRr+EYRQPFjUXrTYKBRb5qPnAVxOOglaxc4/byHqjvq/bqO2F3/CGwTHsgKJYHhQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.6.tgz", + "integrity": "sha512-JEV8l3MHdmmdb7S7Cmx6rbNEjRCgTQMZxllveHO0mx6uiclB0NflCawlQQ6+o5ZrwjUBYPzHm2XoK4wqGVUFuw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-simple-access": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.6.tgz", + "integrity": "sha512-xg1Z0J5JVYxtpX954XqaaAT6NpAY6LtZXvYFCJmGFJWwtlz2EmJoR8LycFRGNE8dBKizGWkGQZGegtkV8y8s+w==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.24.6", + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.6.tgz", + "integrity": "sha512-esRCC/KsSEUvrSjv5rFYnjZI6qv4R1e/iHQrqwbZIoRJqk7xCvEUiN7L1XrmW5QSmQe3n1XD88wbgDTWLbVSyg==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.6.tgz", + "integrity": "sha512-6DneiCiu91wm3YiNIGDWZsl6GfTTbspuj/toTEqLh9d4cx50UIzSdg+T96p8DuT7aJOBRhFyaE9ZvTHkXrXr6Q==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.6.tgz", + "integrity": "sha512-f8liz9JG2Va8A4J5ZBuaSdwfPqN6axfWRK+y66fjKYbwf9VBLuq4WxtinhJhvp1w6lamKUwLG0slK2RxqFgvHA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.6.tgz", + "integrity": "sha512-+QlAiZBMsBK5NqrBWFXCYeXyiU1y7BQ/OYaiPAcQJMomn5Tyg+r5WuVtyEuvTbpV7L25ZSLfE+2E9ywj4FD48A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.6.tgz", + "integrity": "sha512-6voawq8T25Jvvnc4/rXcWZQKKxUNZcKMS8ZNrjxQqoRFernJJKjE3s18Qo6VFaatG5aiX5JV1oPD7DbJhn0a4Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.6.tgz", + "integrity": "sha512-OKmi5wiMoRW5Smttne7BwHM8s/fb5JFs+bVGNSeHWzwZkWXWValR1M30jyXo1s/RaqgwwhEC62u4rFH/FBcBPg==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.6.tgz", + "integrity": "sha512-N/C76ihFKlZgKfdkEYKtaRUtXZAgK7sOY4h2qrbVbVTXPrKGIi8aww5WGe/+Wmg8onn8sr2ut6FXlsbu/j6JHg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-replace-supers": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.6.tgz", + "integrity": "sha512-L5pZ+b3O1mSzJ71HmxSCmTVd03VOT2GXOigug6vDYJzE5awLI7P1g0wFcdmGuwSDSrQ0L2rDOe/hHws8J1rv3w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.6.tgz", + "integrity": "sha512-cHbqF6l1QP11OkYTYQ+hhVx1E017O5ZcSPXk9oODpqhcAD1htsWG2NpHrrhthEO2qZomLK0FXS+u7NfrkF5aOQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.6.tgz", + "integrity": "sha512-ST7guE8vLV+vI70wmAxuZpIKzVjvFX9Qs8bl5w6tN/6gOypPWUmMQL2p7LJz5E63vEGrDhAiYetniJFyBH1RkA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.6.tgz", + "integrity": "sha512-T9LtDI0BgwXOzyXrvgLTT8DFjCC/XgWLjflczTLXyvxbnSR/gpv0hbmzlHE/kmh9nOvlygbamLKRo6Op4yB6aw==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.6.tgz", + "integrity": "sha512-Qu/ypFxCY5NkAnEhCF86Mvg3NSabKsh/TPpBVswEdkGl7+FbsYHy1ziRqJpwGH4thBdQHh8zx+z7vMYmcJ7iaQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.6.tgz", + "integrity": "sha512-oARaglxhRsN18OYsnPTpb8TcKQWDYNsPNmTnx5++WOAsUJ0cSC/FZVlIJCKvPbU4yn/UXsS0551CFKJhN0CaMw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.6.tgz", + "integrity": "sha512-SMDxO95I8WXRtXhTAc8t/NFQUT7VYbIWwJCJgEli9ml4MhqUMh4S6hxgH6SmAC3eAQNWCDJFxcFeEt9w2sDdXg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.6.tgz", + "integrity": "sha512-DcrgFXRRlK64dGE0ZFBPD5egM2uM8mgfrvTMOSB2yKzOtjpGegVYkzh3s1zZg1bBck3nkXiaOamJUqK3Syk+4A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.6.tgz", + "integrity": "sha512-xnEUvHSMr9eOWS5Al2YPfc32ten7CXdH7Zwyyk7IqITg4nX61oHj+GxpNvl+y5JHjfN3KXE2IV55wAWowBYMVw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.6.tgz", + "integrity": "sha512-h/2j7oIUDjS+ULsIrNZ6/TKG97FgmEk1PXryk/HQq6op4XUUUwif2f69fJrzK0wza2zjCS1xhXmouACaWV5uPA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.6.tgz", + "integrity": "sha512-fN8OcTLfGmYv7FnDrsjodYBo1DhPL3Pze/9mIIE2MGCT1KgADYIOD7rEglpLHZj8PZlC/JFX5WcD+85FLAQusw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.6.tgz", + "integrity": "sha512-BJbEqJIcKwrqUP+KfUIkxz3q8VzXe2R8Wv8TaNgO1cx+nNavxn/2+H8kp9tgFSOL6wYPPEgFvU6IKS4qoGqhmg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.6.tgz", + "integrity": "sha512-IshCXQ+G9JIFJI7bUpxTE/oA2lgVLAIK8q1KdJNoPXOpvRaNjMySGuvLfBw/Xi2/1lLo953uE8hyYSDW3TSYig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.6.tgz", + "integrity": "sha512-H0i+hDLmaYYSt6KU9cZE0gb3Cbssa/oxWis7PX4ofQzbvsfix9Lbh8SRk7LCPDlLWJHUiFeHU0qRRpF/4Zv7mQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-typescript": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.6.tgz", + "integrity": "sha512-bKl3xxcPbkQQo5eX9LjjDpU2xYHeEeNQbOhj0iPvetSzA+Tu9q/o5lujF4Sek60CM6MgYvOS/DJuwGbiEYAnLw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.6.tgz", + "integrity": "sha512-8EIgImzVUxy15cZiPii9GvLZwsy7Vxc+8meSlR3cXFmBIl5W5Tn9LGBf7CDKkHj4uVfNXCJB8RsVfnmY61iedA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.6.tgz", + "integrity": "sha512-pssN6ExsvxaKU638qcWb81RrvvgZom3jDgU/r5xFZ7TONkZGFf4MhI2ltMb8OcQWhHyxgIavEU+hgqtbKOmsPA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.6.tgz", + "integrity": "sha512-quiMsb28oXWIDK0gXLALOJRXLgICLiulqdZGOaPPd0vRT7fQp74NtdADAVu+D8s00C+0Xs0MxVP0VKF/sZEUgw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.6.tgz", + "integrity": "sha512-CrxEAvN7VxfjOG8JNF2Y/eMqMJbZPZ185amwGUBp8D9USK90xQmv7dLdFSa+VbD7fdIqcy/Mfv7WtzG8+/qxKg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.24.6", + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-validator-option": "^7.24.6", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.6", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.6", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.6", + "@babel/plugin-syntax-import-attributes": "^7.24.6", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.6", + "@babel/plugin-transform-async-generator-functions": "^7.24.6", + "@babel/plugin-transform-async-to-generator": "^7.24.6", + "@babel/plugin-transform-block-scoped-functions": "^7.24.6", + "@babel/plugin-transform-block-scoping": "^7.24.6", + "@babel/plugin-transform-class-properties": "^7.24.6", + "@babel/plugin-transform-class-static-block": "^7.24.6", + "@babel/plugin-transform-classes": "^7.24.6", + "@babel/plugin-transform-computed-properties": "^7.24.6", + "@babel/plugin-transform-destructuring": "^7.24.6", + "@babel/plugin-transform-dotall-regex": "^7.24.6", + "@babel/plugin-transform-duplicate-keys": "^7.24.6", + "@babel/plugin-transform-dynamic-import": "^7.24.6", + "@babel/plugin-transform-exponentiation-operator": "^7.24.6", + "@babel/plugin-transform-export-namespace-from": "^7.24.6", + "@babel/plugin-transform-for-of": "^7.24.6", + "@babel/plugin-transform-function-name": "^7.24.6", + "@babel/plugin-transform-json-strings": "^7.24.6", + "@babel/plugin-transform-literals": "^7.24.6", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.6", + "@babel/plugin-transform-member-expression-literals": "^7.24.6", + "@babel/plugin-transform-modules-amd": "^7.24.6", + "@babel/plugin-transform-modules-commonjs": "^7.24.6", + "@babel/plugin-transform-modules-systemjs": "^7.24.6", + "@babel/plugin-transform-modules-umd": "^7.24.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.6", + "@babel/plugin-transform-new-target": "^7.24.6", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.6", + "@babel/plugin-transform-numeric-separator": "^7.24.6", + "@babel/plugin-transform-object-rest-spread": "^7.24.6", + "@babel/plugin-transform-object-super": "^7.24.6", + "@babel/plugin-transform-optional-catch-binding": "^7.24.6", + "@babel/plugin-transform-optional-chaining": "^7.24.6", + "@babel/plugin-transform-parameters": "^7.24.6", + "@babel/plugin-transform-private-methods": "^7.24.6", + "@babel/plugin-transform-private-property-in-object": "^7.24.6", + "@babel/plugin-transform-property-literals": "^7.24.6", + "@babel/plugin-transform-regenerator": "^7.24.6", + "@babel/plugin-transform-reserved-words": "^7.24.6", + "@babel/plugin-transform-shorthand-properties": "^7.24.6", + "@babel/plugin-transform-spread": "^7.24.6", + "@babel/plugin-transform-sticky-regex": "^7.24.6", + "@babel/plugin-transform-template-literals": "^7.24.6", + "@babel/plugin-transform-typeof-symbol": "^7.24.6", + "@babel/plugin-transform-unicode-escapes": "^7.24.6", + "@babel/plugin-transform-unicode-property-regex": "^7.24.6", + "@babel/plugin-transform-unicode-regex": "^7.24.6", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.6", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.6.tgz", + "integrity": "sha512-U10aHPDnokCFRXgyT/MaIRTivUu2K/mu0vJlwRS9LxJmJet+PFQNKpggPyFCUtC6zWSBPjvxjnpNkAn3Uw2m5w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-validator-option": "^7.24.6", + "@babel/plugin-syntax-jsx": "^7.24.6", + "@babel/plugin-transform-modules-commonjs": "^7.24.6", + "@babel/plugin-transform-typescript": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "node_modules/@babel/runtime": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.6.tgz", + "integrity": "sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.6.tgz", + "integrity": "sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==", + "dependencies": { + "@babel/code-frame": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.6.tgz", + "integrity": "sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==", + "dependencies": { + "@babel/code-frame": "^7.24.6", + "@babel/generator": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-hoist-variables": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/types": "^7.24.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@babel/types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz", + "integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==", + "dependencies": { + "@babel/helper-string-parser": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "devOptional": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "devOptional": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@prisma/client": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.14.0.tgz", + "integrity": "sha512-akMSuyvLKeoU4LeyBAUdThP/uhVP3GuLygFE3MlYzaCb3/J8SfsYBE5PkaFuLuVpLyA6sFoW+16z/aPhNAESqg==", + "hasInstallScript": true, + "engines": { + "node": ">=16.13" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/debug": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.14.0.tgz", + "integrity": "sha512-iq56qBZuFfX3fCxoxT8gBX33lQzomBU0qIUaEj1RebsKVz1ob/BVH1XSBwwwvRVtZEV1b7Fxx2eVu34Ge/mg3w==" + }, + "node_modules/@prisma/engines": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.14.0.tgz", + "integrity": "sha512-lgxkKZ6IEygVcw6IZZUlPIfLQ9hjSYAtHjZ5r64sCLDgVzsPFCi2XBBJgzPMkOQ5RHzUD4E/dVdpn9+ez8tk1A==", + "hasInstallScript": true, + "dependencies": { + "@prisma/debug": "5.14.0", + "@prisma/engines-version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", + "@prisma/fetch-engine": "5.14.0", + "@prisma/get-platform": "5.14.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48.tgz", + "integrity": "sha512-ip6pNkRo1UxWv+6toxNcYvItNYaqQjXdFNGJ+Nuk2eYtRoEdoF13wxo7/jsClJFFenMPVNVqXQDV0oveXnR1cA==" + }, + "node_modules/@prisma/fetch-engine": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.14.0.tgz", + "integrity": "sha512-VrheA9y9DMURK5vu8OJoOgQpxOhas3qF0IBHJ8G/0X44k82kc8E0w98HCn2nhnbOOMwbWsJWXfLC2/F8n5u0gQ==", + "dependencies": { + "@prisma/debug": "5.14.0", + "@prisma/engines-version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", + "@prisma/get-platform": "5.14.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.14.0.tgz", + "integrity": "sha512-/yAyBvcEjRv41ynZrhdrPtHgk47xLRRq/o5eWGcUpBJ1YrUZTYB8EoPiopnP7iQrMATK8stXQdPOoVlrzuTQZw==", + "dependencies": { + "@prisma/debug": "5.14.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-p6GlFGBt9K4MYLu72YuJ523NVR4A8oHlC5M2JO6OmQqN8kAc/uh1JqLE+FizTokrSJGg0CSvC+BrsmGzKtsZKA==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-3.0.0.tgz", + "integrity": "sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz", + "integrity": "sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg==", + "dependencies": { + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.1.tgz", + "integrity": "sha512-hbkYJc20SBDz2qqLzttjI/EqXemtmWk0ooRznLsiXp3066KQRTvuKHa7U4jCZCJq6Dozqvy0R1/vNESC9inPJg==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.2.0.tgz", + "integrity": "sha512-ygLZSSKgt9bR8HAxR9mK+U5obvAJBr6zlQuhN5soYWx/amjDoQN4dTkydTypgKe6rIbUjTILyLU+W5XFwXr4kg==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.1.0.tgz", + "integrity": "sha512-q4A4d38v8pYYmseu/jTS3Z5I3zXlEOe5Obi+EJreVKgSVyWUHOd7/yaVCinC60QG4MRyCs98tcxBH1IMC0bu7Q==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.0.0.tgz", + "integrity": "sha512-PUtyEA0Oik50SaEFCZ0WPVtF9tz/teze2fDptW6WRXl+RrEenH8UbEjudOz8iakiMl3lE3lCVqYf2Y+znL8QFQ==", + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.0.tgz", + "integrity": "sha512-NB7AFiPN4NxP/YCAnrvYR18z2/ZsiHiF7VtG30gshO9GbFrIb1rC8ep4NGpJSWrz6P64uhPXeo4M0UsCLnZKqw==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.0.tgz", + "integrity": "sha512-RUQG3vQ3LX7peqqHAbmayhgrF5aTilPnazinaSGF1P0+tgM3vvIRWPHmlLIz2qFqB9LqFIxditxc8O2Z6psrRw==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.0.tgz", + "integrity": "sha512-baRPdMBDMBExZXIUAoPGm/hntixjt/VFpU6+VmCyiYJYzRHRxoaI1MN+5XE+hIS8AJ2GCHLMFEIOLzq9xx1EgQ==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.0.tgz", + "integrity": "sha512-HNFfShmotWGeAoW4ujP8meV9BZavcpmerDbPIjkJbxKbN8RsUcpRQ/2OyIxWNxXNH2GWCAxuSB7ynmIGJlQ3Dw==", + "dependencies": { + "@smithy/eventstream-codec": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.0.1.tgz", + "integrity": "sha512-uaH74i5BDj+rBwoQaXioKpI0SHBJFtOVwzrCpxZxphOW0ki5jhj7dXvDMYM2IJem8TpdFvS2iC08sjOblfFGFg==", + "dependencies": { + "@smithy/protocol-http": "^4.0.0", + "@smithy/querystring-builder": "^3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/hash-blob-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-3.0.0.tgz", + "integrity": "sha512-/Wbpdg+bwJvW7lxR/zpWAc1/x/YkcqguuF2bAzkJrvXriZu1vm8r+PUdE4syiVwQg7PPR2dXpi3CLBb9qRDaVQ==", + "dependencies": { + "@smithy/chunked-blob-reader": "^3.0.0", + "@smithy/chunked-blob-reader-native": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/hash-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.0.tgz", + "integrity": "sha512-84qXstNemP3XS5jcof0el6+bDfjzuvhJPQTEfro3lgtbCtKgzPm3MgiS6ehXVPjeQ5+JS0HqmTz8f/RYfzHVxw==", + "dependencies": { + "@smithy/types": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/hash-stream-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-3.0.0.tgz", + "integrity": "sha512-J0i7de+EgXDEGITD4fxzmMX8CyCNETTIRXlxjMiNUvvu76Xn3GJ31wQR85ynlPk2wI1lqoknAFJaD1fiNDlbIA==", + "dependencies": { + "@smithy/types": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.0.tgz", + "integrity": "sha512-F6wBBaEFgJzj0s4KUlliIGPmqXemwP6EavgvDqYwCH40O5Xr2iMHvS8todmGVZtuJCorBkXsYLyTu4PuizVq5g==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/md5-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-3.0.0.tgz", + "integrity": "sha512-Tm0vrrVzjlD+6RCQTx7D3Ls58S3FUH1ZCtU1MIh/qQmaOo1H9lMN2as6CikcEwgattnA9SURSdoJJ27xMcEfMA==", + "dependencies": { + "@smithy/types": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.0.tgz", + "integrity": "sha512-3C4s4d/iGobgCtk2tnWW6+zSTOBg1PRAm2vtWZLdriwTroFbbWNSr3lcyzHdrQHnEXYCC5K52EbpfodaIUY8sg==", + "dependencies": { + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.0.1.tgz", + "integrity": "sha512-lQ/UOdGD4KM5kLZiAl0q8Qy3dPbynvAXKAdXnYlrA1OpaUwr+neSsVokDZpY6ZVb5Yx8jnus29uv6XWpM9P4SQ==", + "dependencies": { + "@smithy/middleware-serde": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.3.tgz", + "integrity": "sha512-Wve1qzJb83VEU/6q+/I0cQdAkDnuzELC6IvIBwDzUEiGpKqXgX1v10FUuZGbRS6Ov/P+HHthcAoHOJZQvZNAkA==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/service-error-classification": "^3.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.0.tgz", + "integrity": "sha512-I1vKG1foI+oPgG9r7IMY1S+xBnmAn1ISqployvqkwHoSb8VPsngHDTOgYGYBonuOKndaWRUGJZrKYYLB+Ane6w==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.0.tgz", + "integrity": "sha512-+H0jmyfAyHRFXm6wunskuNAqtj7yfmwFB6Fp37enytp2q047/Od9xetEaUbluyImOlGnGpaVGaVfjwawSr+i6Q==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.0.tgz", + "integrity": "sha512-ngfB8QItUfTFTfHMvKuc2g1W60V1urIgZHqD1JNFZC2tTWXahqf2XvKXqcBS7yZqR7GqkQQZy11y/lNOUWzq7Q==", + "dependencies": { + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.0.0.tgz", + "integrity": "sha512-3trD4r7NOMygwLbUJo4eodyQuypAWr7uvPnebNJ9a70dQhVn+US8j/lCnvoJS6BXfZeF7PkkkI0DemVJw+n+eQ==", + "dependencies": { + "@smithy/abort-controller": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/querystring-builder": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.0.tgz", + "integrity": "sha512-Tj3+oVhqdZgemjCiWjFlADfhvLF4C/uKDuKo7/tlEsRQ9+3emCreR2xndj970QSRSsiCEU8hZW3/8JQu+n5w4Q==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.0.0.tgz", + "integrity": "sha512-qOQZOEI2XLWRWBO9AgIYuHuqjZ2csyr8/IlgFDHDNuIgLAMRx2Bl8ck5U5D6Vh9DPdoaVpuzwWMa0xcdL4O/AQ==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.0.tgz", + "integrity": "sha512-bW8Fi0NzyfkE0TmQphDXr1AmBDbK01cA4C1Z7ggwMAU5RDz5AAv/KmoRwzQAS0kxXNf/D2ALTEgwK0U2c4LtRg==", + "dependencies": { + "@smithy/types": "^3.0.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.0.tgz", + "integrity": "sha512-UzHwthk0UEccV4dHzPySnBy34AWw3V9lIqUTxmozQ+wPDAO9csCWMfOLe7V9A2agNYy7xE+Pb0S6K/J23JSzfQ==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.0.tgz", + "integrity": "sha512-3BsBtOUt2Gsnc3X23ew+r2M71WwtpHfEDGhHYHSDg6q1t8FrWh15jT25DLajFV1H+PpxAJ6gqe9yYeRUsmSdFA==", + "dependencies": { + "@smithy/types": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.0.tgz", + "integrity": "sha512-dAM7wSX0NR3qTNyGVN/nwwpEDzfV9T/3AN2eABExWmda5VqZKSsjlINqomO5hjQWGv+IIkoXfs3u2vGSNz8+Rg==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-3.0.0.tgz", + "integrity": "sha512-kXFOkNX+BQHe2qnLxpMEaCRGap9J6tUGLzc3A9jdn+nD4JdMwCKTJ+zFwQ20GkY+mAXGatyTw3HcoUlR39HwmA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.1.tgz", + "integrity": "sha512-tj4Ku7MpzZR8cmVuPcSbrLFVxmptWktmJMwST/uIEq4sarabEdF8CbmQdYB7uJ/X51Qq2EYwnRsoS7hdR4B7rA==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-stream": "^3.0.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.0.0.tgz", + "integrity": "sha512-VvWuQk2RKFuOr98gFhjca7fkBS+xLLURT8bUjk5XQoV0ZLm7WPwWPPY3/AwzTLuUBDeoKDCthfe1AsTUWaSEhw==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.0.tgz", + "integrity": "sha512-2XLazFgUu+YOGHtWihB3FSLAfCUajVfNBXGGYjOaVKjLAuAxx3pSBY3hBgLzIgB17haf59gOG3imKqTy8mcrjw==", + "dependencies": { + "@smithy/querystring-parser": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.3.tgz", + "integrity": "sha512-3DFON2bvXJAukJe+qFgPV/rorG7ZD3m4gjCXHD1V5z/tgKQp5MCTCLntrd686tX6tj8Uli3lefWXJudNg5WmCA==", + "dependencies": { + "@smithy/property-provider": "^3.1.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.3.tgz", + "integrity": "sha512-D0b8GJXecT00baoSQ3Iieu3k3mZ7GY8w1zmg8pdogYrGvWJeLcIclqk2gbkG4K0DaBGWrO6v6r20iwIFfDYrmA==", + "dependencies": { + "@smithy/config-resolver": "^3.0.1", + "@smithy/credential-provider-imds": "^3.1.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.0.1.tgz", + "integrity": "sha512-ZRT0VCOnKlVohfoABMc8lWeQo/JEFuPWctfNRXgTHbyOVssMOLYFUNWukxxiHRGVAhV+n3c0kPW+zUqckjVPEA==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.0.tgz", + "integrity": "sha512-q5ITdOnV2pXHSVDnKWrwgSNTDBAMHLptFE07ua/5Ty5WJ11bvr0vk2a7agu7qRhrCFRQlno5u3CneU5EELK+DQ==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.0.tgz", + "integrity": "sha512-nK99bvJiziGv/UOKJlDvFF45F00WgPLKVIGUfAK+mDhzVN2hb/S33uW2Tlhg5PVBoqY7tDVqL0zmu4OxAHgo9g==", + "dependencies": { + "@smithy/service-error-classification": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.0.1.tgz", + "integrity": "sha512-7F7VNNhAsfMRA8I986YdOY5fE0/T1/ZjFF6OLsqkvQVNP3vZ/szYDfGCyphb7ioA09r32K/0qbSFfNFU68aSzA==", + "dependencies": { + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-waiter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-3.0.0.tgz", + "integrity": "sha512-+fEXJxGDLCoqRKVSmo0auGxaqbiCo+8oph+4auefYjaNxjOLKSY2MxVQfRzo65PaZv4fr+5lWg+au7vSuJJ/zw==", + "dependencies": { + "@smithy/abort-controller": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "devOptional": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "devOptional": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "devOptional": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "devOptional": true + }, + "node_modules/@types/aws-sdk": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@types/aws-sdk/-/aws-sdk-2.7.0.tgz", + "integrity": "sha512-bF6brnwPN9+kheqdKCpinMgCkj+sJIUEj+0v0LPug9OQwL5/1jy+kiJwl+Nkw4Kh+7oaL1phhC4gMz6Oq60jMg==", + "deprecated": "This is a stub types definition for aws-sdk (https://github.com/aws/aws-sdk-js). aws-sdk provides its own type definitions, so you don't need @types/aws-sdk installed!", + "dev": true, + "dependencies": { + "aws-sdk": "*" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/bcrypt": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", + "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.2.tgz", + "integrity": "sha512-dPSEQElyVJ97BuGduAqQjpBocZWAs0GR94z+ptL7JXQJeJdHw2WBG3EWdFrK36b8Q6j8P4cXOMhgUoi0IIfIsg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express-session": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.18.0.tgz", + "integrity": "sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/is-email": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/is-email/-/is-email-1.0.0.tgz", + "integrity": "sha512-b/76ooKpYY/b+oPrOuc/pmM5eag+ZlzctPsKcRCIKs+TFzh0FL58OeXtSPkbXt3uKNK84YCKHmjnoREtwve5Kg==", + "dev": true + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", + "integrity": "sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/morgan": { + "version": "1.9.9", + "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.9.tgz", + "integrity": "sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/multer": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.11.tgz", + "integrity": "sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/multer-s3": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/multer-s3/-/multer-s3-3.0.3.tgz", + "integrity": "sha512-VgWygI9UwyS7loLithUUi0qAMIDWdNrERS2Sb06UuPYiLzKuIFn2NgL7satyl4v8sh/LLoU7DiPanvbQaRg9Yg==", + "dev": true, + "dependencies": { + "@aws-sdk/client-s3": "^3.0.0", + "@types/multer": "*", + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.12.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.13.tgz", + "integrity": "sha512-gBGeanV41c1L171rR7wjbMiEpEI/l5XFQdLLfhr/REwpgDy/4U8y89+i8kRiLzDyZdOkXh+cRaTetUnCYutoXA==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/oauth": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.5.tgz", + "integrity": "sha512-+oQ3C2Zx6ambINOcdIARF5Z3Tu3x//HipE889/fqo3sgpQZbe9c6ExdQFtN6qlhpR7p83lTZfPJt0tCAW29dog==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/passport": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.16.tgz", + "integrity": "sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-google-oauth20": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.16.tgz", + "integrity": "sha512-ayXK2CJ7uVieqhYOc6k/pIr5pcQxOLB6kBev+QUGS7oEZeTgIs1odDobXRqgfBPvXzl0wXCQHftV5220czZCPA==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-oauth2": "*" + } + }, + "node_modules/@types/passport-oauth2": { + "version": "1.4.17", + "resolved": "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.4.17.tgz", + "integrity": "sha512-ODiAHvso6JcWJ6ZkHHroVp05EHGhqQN533PtFNBkg8Fy5mERDqsr030AX81M0D69ZcaMvhF92SRckEk2B0HYYg==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/oauth": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" + }, + "node_modules/@types/swagger-jsdoc": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz", + "integrity": "sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ==", + "dev": true + }, + "node_modules/@types/swagger-ui-express": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz", + "integrity": "sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "devOptional": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "devOptional": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "devOptional": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sdk": { + "version": "2.1634.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1634.0.tgz", + "integrity": "sha512-uSEjzAyGIbfpALzxPYES+hsBK1zuUY/8wSv2mAwijAcQfTMV89jQ4VHI/5KsyyZhDSeS/rV9cn6376KO+HDU2w==", + "hasInstallScript": true, + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "util": "^0.12.4", + "uuid": "8.0.0", + "xml2js": "0.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aws-sdk/node_modules/uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001625", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001625.tgz", + "integrity": "sha512-4KE9N2gcRH+HQhpeiRZXd+1niLB/XNLAhSy4z7fI8EzcbcPoAqjNInxVHTiTwWfTIV4w096XG8OtCOCQQKPv3w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/core-js-compat": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "devOptional": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "devOptional": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.787", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.787.tgz", + "integrity": "sha512-d0EFmtLPjctczO3LogReyM2pbBiiZbnsKnGF+cdZhsYzHm/A0GV7W94kqzLD8SN4O3f3iHlgLUChqghgyznvCQ==" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-session": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz", + "integrity": "sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ==", + "dev": true, + "dependencies": { + "cookie": "0.6.0", + "cookie-signature": "1.0.7", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-email": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-email/-/is-email-1.0.2.tgz", + "integrity": "sha512-UojUgD2EhDTBQ2SGKwrK9edce5phRzgLsP+V5+Uu2Swi+uvjVXgH3zduM3HhT9iaC/9Kq19/TYUbP0jPoi6ioA==" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-uuid": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-uuid/-/is-uuid-1.0.2.tgz", + "integrity": "sha512-tCByphFcJgf2qmiMo5hMCgNAquNSagOetVetDvBXswGkNfoyEMvGH1yDlF8cbZbKnbVBr4Y5/rlpMz9umxyBkQ==" + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock-extended": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/jest-mock-extended/-/jest-mock-extended-3.0.7.tgz", + "integrity": "sha512-7lsKdLFcW9B9l5NzZ66S/yTQ9k8rFtnwYdCNuRU/81fqDWicNDVhitTSPnrGmNeNm0xyw0JHexEOShrIKRCIRQ==", + "dependencies": { + "ts-essentials": "^10.0.0" + }, + "peerDependencies": { + "jest": "^24.0.0 || ^25.0.0 || ^26.0.0 || ^27.0.0 || ^28.0.0 || ^29.0.0", + "typescript": "^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lru-cache/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "devOptional": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dev": true, + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/multer-s3": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/multer-s3/-/multer-s3-3.0.1.tgz", + "integrity": "sha512-BFwSO80a5EW4GJRBdUuSHblz2jhVSAze33ZbnGpcfEicoT0iRolx4kWR+AJV07THFRCQ78g+kelKFdjkCCaXeQ==", + "dependencies": { + "@aws-sdk/lib-storage": "^3.46.0", + "file-type": "^3.3.0", + "html-comment-regex": "^1.1.2", + "run-parallel": "^1.1.6" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-s3": "^3.0.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + }, + "node_modules/node-mocks-http": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.14.1.tgz", + "integrity": "sha512-mfXuCGonz0A7uG1FEjnypjm34xegeN5+HI6xeGhYKecfgaZhjsmYoLE9LEFmT+53G1n8IuagPZmVnEL/xNsFaA==", + "dev": true, + "dependencies": { + "@types/express": "^4.17.21", + "@types/node": "^20.10.6", + "accepts": "^1.3.7", + "content-disposition": "^0.5.3", + "depd": "^1.1.0", + "fresh": "^0.5.2", + "merge-descriptors": "^1.0.1", + "methods": "^1.1.2", + "mime": "^1.3.4", + "parseurl": "^1.3.3", + "range-parser": "^1.2.0", + "type-is": "^1.6.18" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/node-mocks-http/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node_modules/nodemon": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.2.tgz", + "integrity": "sha512-/Ib/kloefDy+N0iRTxIUzyGcdW9lzlnca2Jsa5w73bs3npXjg+WInmiX6VY13mIb6SykkthYX/U5t0ukryGqBw==", + "dev": true, + "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": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/oauth": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.10.0.tgz", + "integrity": "sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q==" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "peer": true + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-google-oauth20": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", + "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", + "dependencies": { + "passport-oauth2": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-oauth2": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.8.0.tgz", + "integrity": "sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA==", + "dependencies": { + "base64url": "3.x.x", + "oauth": "0.10.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prisma": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.14.0.tgz", + "integrity": "sha512-gCNZco7y5XtjrnQYeDJTiVZmT/ncqCr5RY1/Cf8X2wgLRmyh9ayPAGBNziI4qEE4S6SxCH5omQLVo9lmURaJ/Q==", + "hasInstallScript": true, + "dependencies": { + "@prisma/engines": "5.14.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-browserify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, + "node_modules/superstruct": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", + "integrity": "sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swagger-jsdoc": { + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", + "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", + "dependencies": { + "commander": "6.2.0", + "doctrine": "3.0.0", + "glob": "7.1.6", + "lodash.mergewith": "^4.6.2", + "swagger-parser": "^10.0.3", + "yaml": "2.0.0-1" + }, + "bin": { + "swagger-jsdoc": "bin/swagger-jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/swagger-jsdoc/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", + "dependencies": { + "@apidevtools/swagger-parser": "10.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/swagger-ui-dist": { + "version": "5.17.14", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz", + "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==" + }, + "node_modules/swagger-ui-express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz", + "integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==", + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/ts-essentials": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-10.0.0.tgz", + "integrity": "sha512-77FHNJEyysF9+1s4G6eejuA1lxw7uMchT3ZPy3CIbh7GIunffpshtM8pTe5G6N5dpOzNevqRHew859ceLWVBfw==", + "peerDependencies": { + "typescript": ">=4.5.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ts-jest": { + "version": "29.1.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.4.tgz", + "integrity": "sha512-YiHwDhSvCiItoAgsKtoLFCuakDzDsJ1DLDnSouTaTmdOcOwIkSzbLXduaQ6M5DRVhuZC/NYaaZ/mtHbWMv/S6Q==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "devOptional": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "node_modules/tsx": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.11.0.tgz", + "integrity": "sha512-vzGGELOgAupsNVssAmZjbUDfdm/pWP4R+Kg8TVdsonxbXk0bEpE1qh0yV6/QxUVXaVlNemgcPajGdJJ82n3stg==", + "dev": true, + "dependencies": { + "esbuild": "~0.20.2", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dev": true, + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "devOptional": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yaml": { + "version": "2.0.0-1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", + "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/z-schema": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", + "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "commander": "^9.4.1" + } + }, + "node_modules/z-schema/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "optional": true, + "engines": { + "node": "^12.20.0 || >=14" + } + } + } } diff --git a/package.json b/package.json index 7f99b54..d521040 100644 --- a/package.json +++ b/package.json @@ -1,62 +1,66 @@ { - "dependencies": { - "@aws-sdk/client-s3": "^3.590.0", - "@prisma/client": "^5.4.2", - "aws-sdk": "^2.1634.0", - "bcrypt": "^5.1.1", - "dotenv": "^16.3.1", - "express": "^4.18.2", - "is-email": "^1.0.2", - "is-uuid": "^1.0.2", - "jest-mock-extended": "^3.0.7", - "jsonwebtoken": "^9.0.2", - "moment-timezone": "^0.5.45", - "multer": "^1.4.5-lts.1", - "multer-s3": "^3.0.1", - "passport": "^0.7.0", - "passport-google-oauth20": "^2.0.0", - "prisma": "^5.4.2", - "superstruct": "^1.0.3", - "swagger-jsdoc": "^6.2.8", - "swagger-ui-express": "^5.0.0" - }, - "devDependencies": { - "@babel/preset-env": "^7.24.6", - "@babel/preset-typescript": "^7.24.6", - "@jest/globals": "^29.7.0", - "@types/bcrypt": "^5.0.2", - "@types/cors": "^2.8.17", - "@types/express": "^4.17.21", - "@types/express-session": "^1.18.0", - "@types/is-email": "^1.0.0", - "@types/jsonwebtoken": "^9.0.6", - "@types/morgan": "^1.9.9", - "@types/multer": "^1.4.11", - "@types/multer-s3": "^3.0.3", - "@types/node": "^20.12.13", - "@types/passport": "^1.0.16", - "@types/passport-google-oauth20": "^2.0.16", - "@types/swagger-jsdoc": "^6.0.4", - "@types/swagger-ui-express": "^4.1.6", - "babel-jest": "^29.7.0", - "cors": "^2.8.5", - "express-session": "^1.18.0", - "jest": "^29.7.0", - "morgan": "^1.10.0", - "node-mocks-http": "^1.14.1", - "nodemon": "^3.1.2", - "ts-jest": "^29.1.4", - "ts-node": "^10.9.2", - "tsx": "^4.11.0", - "typescript": "^5.4.5" - }, - "type": "module", - "scripts": { - "start": "tsx --loader ts-node/esm src/app.ts", - "dev": "nodemon", - "test": "jest --coverage" - }, - "prisma": { - "seed": "tsx prisma/seed.ts" - } + "dependencies": { + "@aws-sdk/client-s3": "^3.590.0", + "@aws-sdk/s3-request-presigner": "^3.591.0", + "@prisma/client": "^5.4.2", + "aws-sdk": "^2.1634.0", + "bcrypt": "^5.1.1", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "is-email": "^1.0.2", + "is-uuid": "^1.0.2", + "jest-mock-extended": "^3.0.7", + "jsonwebtoken": "^9.0.2", + "moment-timezone": "^0.5.45", + "multer": "^1.4.5-lts.1", + "multer-s3": "^3.0.1", + "passport": "^0.7.0", + "passport-google-oauth20": "^2.0.0", + "prisma": "^5.4.2", + "superstruct": "^1.0.3", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.0" + }, + "devDependencies": { + "@babel/preset-env": "^7.24.6", + "@babel/preset-typescript": "^7.24.6", + "@jest/globals": "^29.7.0", + "@types/aws-sdk": "^2.7.0", + "@types/bcrypt": "^5.0.2", + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/express-session": "^1.18.0", + "@types/is-email": "^1.0.0", + "@types/jsonwebtoken": "^9.0.6", + "@types/morgan": "^1.9.9", + "@types/multer": "^1.4.11", + "@types/multer-s3": "^3.0.3", + "@types/node": "^20.12.13", + "@types/passport": "^1.0.16", + "@types/passport-google-oauth20": "^2.0.16", + "@types/swagger-jsdoc": "^6.0.4", + "@types/swagger-ui-express": "^4.1.6", + "babel-jest": "^29.7.0", + "cors": "^2.8.5", + "express-session": "^1.18.0", + "jest": "^29.7.0", + "morgan": "^1.10.0", + "node-mocks-http": "^1.14.1", + "nodemon": "^3.1.2", + "ts-jest": "^29.1.4", + "ts-node": "^10.9.2", + "tsx": "^4.11.0", + "typescript": "^5.4.5" + }, + "type": "module", + "scripts": { + "start": "tsx --loader ts-node/esm src/app.ts", + "start:dev": "NODE_ENV=development tsx src/app.ts", + "start:prod": "NODE_ENV=production tsx src/app.ts", + "dev": "nodemon", + "test": "jest --coverage" + }, + "prisma": { + "seed": "tsx prisma/seed.ts" + } } diff --git a/src/controllers/imageController.ts b/src/controllers/imageController.ts index 224da79..5b9c72d 100644 --- a/src/controllers/imageController.ts +++ b/src/controllers/imageController.ts @@ -1,10 +1,10 @@ import { Request, Response } from "express"; import * as imageService from "../services/imageService"; -export const uploadImage = async (req: Request, res: Response) => { +export const getPresignedUrl = async (req: Request, res: Response) => { try { - const imageUrl = await imageService.uploadImage(req); - res.status(200).json({ url: imageUrl }); + const presignedUrl = await imageService.generatePresignedUrl(req); + res.status(200).json({ url: presignedUrl }); } catch (error) { res.status(400).send((error as Error).message); } diff --git a/src/routes/imageRoutes.ts b/src/routes/imageRoutes.ts index b890fff..cbda3f8 100644 --- a/src/routes/imageRoutes.ts +++ b/src/routes/imageRoutes.ts @@ -1,7 +1,6 @@ import express from "express"; import * as imageController from "../controllers/imageController"; import authenticate from "../middlewares/authenticate"; -import { uploadImageToS3 } from "../services/imageService"; const router = express.Router(); /** @@ -51,6 +50,6 @@ const router = express.Router(); * type: string * example: "이미지 파일을 선택해주세요." */ -router.post("/upload", authenticate, uploadImageToS3, imageController.uploadImage); +router.post("/upload", authenticate, imageController.getPresignedUrl); export default router; diff --git a/src/services/imageService.ts b/src/services/imageService.ts index dfa7e1e..0f54637 100644 --- a/src/services/imageService.ts +++ b/src/services/imageService.ts @@ -1,10 +1,6 @@ -import { S3Client } from "@aws-sdk/client-s3"; -import { PrismaClient } from "@prisma/client"; +import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3"; +import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; import { Request } from "express"; -import multer from "multer"; -import multerS3 from "multer-s3"; - -const prisma = new PrismaClient(); const s3Config = new S3Client({ region: "ap-northeast-2", @@ -14,36 +10,22 @@ const s3Config = new S3Client({ }, }); -const upload = multer({ - storage: multerS3({ - s3: s3Config, - bucket: process.env.AWS_S3_BUCKET_NAME || "", - acl: "public-read", - metadata: function (req, file, cb) { - cb(null, { fieldName: file.fieldname }); - }, - key: function (req, file, cb) { - cb(null, `images/${Date.now().toString()}_${file.originalname}`); - }, - }), -}); - -export const uploadImageToS3 = upload.single("image"); +export const generatePresignedUrl = async (req: Request): Promise => { + const { fileName, fileType } = req.body; -export const uploadImage = async (req: Request): Promise => { - const file = req.file as Express.MulterS3File; - - if (!file) { + if (!fileName || !fileType) { throw new Error("이미지 파일을 선택해주세요."); } - const imageUrl: string = file.location; + const params = { + Bucket: process.env.AWS_S3_BUCKET_NAME || "", + Key: `images/${Date.now().toString()}_${fileName}`, + ContentType: fileType, + }; + + const command = new PutObjectCommand(params); - await prisma.image.create({ - data: { - imagePath: imageUrl, - }, - }); + const presignedUrl = await getSignedUrl(s3Config, command, { expiresIn: 3600 }); - return imageUrl; + return presignedUrl; }; diff --git a/test.html b/test.html index 7326125..430273a 100644 --- a/test.html +++ b/test.html @@ -5,36 +5,54 @@ Upload Image - -
+
+ diff --git a/yarn.lock b/yarn.lock index 3065afd..4235fde 100644 --- a/yarn.lock +++ b/yarn.lock @@ -574,6 +574,20 @@ "@smithy/util-middleware" "^3.0.0" tslib "^2.6.2" +"@aws-sdk/s3-request-presigner@^3.591.0": + version "3.591.0" + resolved "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.591.0.tgz" + integrity sha512-MDkPKrVC63XxED/vaWa2xkBfUPwKXqP/nVg4TUdjlUCIlP+xSouAYxkQ1aclinCbx8+E932C9kf4kNRQIxhafA== + dependencies: + "@aws-sdk/signature-v4-multi-region" "3.587.0" + "@aws-sdk/types" "3.577.0" + "@aws-sdk/util-format-url" "3.577.0" + "@smithy/middleware-endpoint" "^3.0.1" + "@smithy/protocol-http" "^4.0.0" + "@smithy/smithy-client" "^3.1.1" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + "@aws-sdk/signature-v4-multi-region@3.587.0": version "3.587.0" resolved "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.587.0.tgz" @@ -622,6 +636,16 @@ "@smithy/util-endpoints" "^2.0.1" tslib "^2.6.2" +"@aws-sdk/util-format-url@3.577.0": + version "3.577.0" + resolved "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.577.0.tgz" + integrity sha512-SyEGC2J+y/krFRuPgiF02FmMYhqbiIkOjDE6k4nYLJQRyS6XEAGxZoG+OHeOVEM+bsDgbxokXZiM3XKGu6qFIg== + dependencies: + "@aws-sdk/types" "3.577.0" + "@smithy/querystring-builder" "^3.0.0" + "@smithy/types" "^3.0.0" + tslib "^2.6.2" + "@aws-sdk/util-locate-window@^3.0.0": version "3.568.0" resolved "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz" @@ -2499,6 +2523,13 @@ resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== +"@types/aws-sdk@^2.7.0": + version "2.7.0" + resolved "https://registry.npmjs.org/@types/aws-sdk/-/aws-sdk-2.7.0.tgz" + integrity sha512-bF6brnwPN9+kheqdKCpinMgCkj+sJIUEj+0v0LPug9OQwL5/1jy+kiJwl+Nkw4Kh+7oaL1phhC4gMz6Oq60jMg== + dependencies: + aws-sdk "*" + "@types/babel__core@^7.1.14": version "7.20.5" resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz" @@ -2876,7 +2907,7 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" -aws-sdk@^2.1634.0: +aws-sdk@*, aws-sdk@^2.1634.0: version "2.1634.0" resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1634.0.tgz" integrity sha512-uSEjzAyGIbfpALzxPYES+hsBK1zuUY/8wSv2mAwijAcQfTMV89jQ4VHI/5KsyyZhDSeS/rV9cn6376KO+HDU2w== From 3ba7f0fb75ca42ddda6691d768fb45ca8a66e62e Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 6 Jun 2024 10:34:58 +0900 Subject: [PATCH 50/60] =?UTF-8?q?[#M12]=20feat=20:=20article=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=A1=9C=EC=A7=81=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - product controller 관련 로직 테스트 추가 - 원활한 테스트를 위해 asyncHandler를 route에서 controller로 이동 --- src/controllers/articleController.ts | 84 ++--- src/controllers/authController.ts | 13 +- src/controllers/commentController.ts | 63 ++-- src/controllers/imageController.ts | 5 +- src/controllers/productController.ts | 86 +++--- src/routes/articleRoutes.ts | 28 +- src/routes/authRoutes.ts | 7 +- src/routes/productRoutes.ts | 22 +- src/services/articleService.ts | 5 +- src/services/commentService.ts | 5 +- src/test/articleController.test.ts | 263 ++++++++++++++++ src/test/articleService.test.ts | 447 +++++++++++++++++++++++++++ src/test/authController.test.ts | 67 ++-- src/test/productController.test.ts | 375 ++++++++++++++++++++++ src/utils/asyncHandler.ts | 10 +- 15 files changed, 1255 insertions(+), 225 deletions(-) create mode 100644 src/test/articleController.test.ts create mode 100644 src/test/articleService.test.ts create mode 100644 src/test/productController.test.ts diff --git a/src/controllers/articleController.ts b/src/controllers/articleController.ts index 65f4c84..aae99dd 100644 --- a/src/controllers/articleController.ts +++ b/src/controllers/articleController.ts @@ -1,8 +1,8 @@ -import { NextFunction, Request, Response } from "express"; +import { Request, Response } from "express"; import { assert } from "superstruct"; import * as articleService from "../services/articleService"; import { CreateArticle, PatchArticle } from "../structs"; -import AppError from "../utils/errors"; +import asyncHandler from "../utils/asyncHandler"; interface GetArticlesQuery { offset?: string; @@ -11,91 +11,71 @@ interface GetArticlesQuery { keyword?: string; } -interface UserRequest extends Request { +export interface UserRequest extends Request { userId: number; } // GET /articles -export const getArticles = async (req: Request<{}, {}, {}, GetArticlesQuery>, res: Response) => { +export const getArticles = asyncHandler(async (req: Request<{}, {}, {}, GetArticlesQuery>, res: Response) => { const { offset = "0", limit = "10", orderBy = "recent", keyword = "" } = req.query; const offsetNumber = parseInt(offset, 10); const limitNumber = parseInt(limit, 10); const articles = await articleService.getArticles({ offset: offsetNumber, limit: limitNumber, orderBy, keyword }); const bestArticles = await articleService.getBestArticles(); res.send({ articles, bestArticles }); -}; +}); // POST /articles -export const createArticle = async (req: UserRequest, res: Response) => { +export const createArticle = asyncHandler(async (req: UserRequest, res: Response) => { assert(req.body, CreateArticle); const { userId } = req; const { imageUrl, ...articleData } = req.body; const article = await articleService.createArticle(userId!, articleData, imageUrl || ""); res.status(201).send(article); -}; +}); // GET /articles/:id -export const getArticleById = async (req: Request<{ id: string }>, res: Response): Promise => { +export const getArticleById = asyncHandler(async (req: Request<{ id: string }>, res: Response): Promise => { const { id } = req.params; const article = await articleService.getArticleById(id); res.send(article); -}; +}); // PATCH /articles/:id -export const updateArticle = async (req: UserRequest & Request<{ id: string }>, res: Response): Promise => { - assert(req.body, PatchArticle); - const { userId } = req; - const { id } = req.params; - const { imageUrl, ...articleData } = req.body; - const updatedArticle = await articleService.updateArticle(id, userId!, articleData, imageUrl || ""); - res.send(updatedArticle); -}; +export const updateArticle = asyncHandler( + async (req: UserRequest & Request<{ id: string }>, res: Response): Promise => { + assert(req.body, PatchArticle); + const { userId } = req; + const { id } = req.params; + const { imageUrl, ...articleData } = req.body; + const updatedArticle = await articleService.updateArticle(id, userId!, articleData, imageUrl || ""); + res.send(updatedArticle); + } +); // DELETE /articles/:id -export const deleteArticle = async (req: UserRequest & Request<{ id: string }>, res: Response): Promise => { - const { id: articleId } = req.params; - const { userId } = req; - try { +export const deleteArticle = asyncHandler( + async (req: UserRequest & Request<{ id: string }>, res: Response): Promise => { + const { id: articleId } = req.params; + const { userId } = req; await articleService.deleteArticle(articleId, userId); res.sendStatus(204); - } catch (error) { - if (error instanceof AppError) { - res.status(error.statusCode).json({ message: error.message }); - return; - } - throw error; } -}; +); // POST /articles/:id/like -export const likeArticle = async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { +export const likeArticle = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { const { id: articleId } = req.params; const { userId } = req; - try { - const updatedArticle = await articleService.likeArticle(articleId, userId); - res.send(updatedArticle); - } catch (error) { - if (error instanceof AppError) { - res.status(error.statusCode).json({ message: error.message }); - return; - } - next(error); - } -}; + const updatedArticle = await articleService.likeArticle(articleId, userId); + res.send(updatedArticle); +}); // POST /articles/:id/unlike -export const unlikeArticle = async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { +export const unlikeArticle = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { const { id: articleId } = req.params; const { userId } = req; - try { - const updatedArticle = await articleService.unlikeArticle(articleId, userId); - res.send(updatedArticle); - } catch (error) { - if (error instanceof AppError) { - res.status(error.statusCode).json({ message: error.message }); - return; - } - next(error); - } -}; + const updatedArticle = await articleService.unlikeArticle(articleId, userId); + res.send(updatedArticle); +}); diff --git a/src/controllers/authController.ts b/src/controllers/authController.ts index e18f73b..ad7d97f 100644 --- a/src/controllers/authController.ts +++ b/src/controllers/authController.ts @@ -4,13 +4,14 @@ import jwt from "jsonwebtoken"; import { StructError, assert } from "superstruct"; import { createUser, findUserByEmail, findUserById, validatePassword } from "../services/authService"; import { CreateUser } from "../structs"; +import asyncHandler from "../utils/asyncHandler"; import { generateAccessToken, generateRefreshToken, regenerateRefreshToken } from "../utils/tokens"; dotenv.config(); const JWT_SECRET = process.env.JWT_SECRET || "kingPanda"; -export const signUp = async (req: Request, res: Response) => { +export const signUp = asyncHandler(async (req: Request, res: Response) => { try { const { email, password, name, nickname } = req.body; assert(req.body, CreateUser); @@ -46,9 +47,9 @@ export const signUp = async (req: Request, res: Response) => { res.status(500).json({ message: "서버 에러입니다." }); } } -}; +}); -export const signIn = async (req: Request, res: Response) => { +export const signIn = asyncHandler(async (req: Request, res: Response) => { const { email, password } = req.body; if (!email || !password) { @@ -74,9 +75,9 @@ export const signIn = async (req: Request, res: Response) => { const refreshToken = generateRefreshToken(user); res.json({ accessToken, refreshToken }); -}; +}); -export const refreshToken = async (req: Request, res: Response) => { +export const refreshToken = asyncHandler(async (req: Request, res: Response) => { const { refreshToken } = req.body; if (!refreshToken) { @@ -102,7 +103,7 @@ export const refreshToken = async (req: Request, res: Response) => { res.status(401).json({ message: "유효하지 않은 토큰입니다." }); return; } -}; +}); export const googleCallback = (req: Request, res: Response, next: NextFunction) => { if (!req.user) { diff --git a/src/controllers/commentController.ts b/src/controllers/commentController.ts index 44180ee..24607ae 100644 --- a/src/controllers/commentController.ts +++ b/src/controllers/commentController.ts @@ -2,35 +2,34 @@ import { Request, Response } from "express"; import { assert } from "superstruct"; import * as commentService from "../services/commentService"; import { CreateComment, PatchComment } from "../structs"; +import asyncHandler from "../utils/asyncHandler"; interface UserRequest extends Request { userId: number; } // GET /products/:id/comments -export const getCommentsByProductId = async ( - req: Request<{ id: string }, {}, {}, { cursor?: string }>, - res: Response -) => { - const { id: productId } = req.params; - const { cursor } = req.query; - const comments = await commentService.getCommentsByProductId(productId, cursor); - res.send(comments); -}; +export const getCommentsByProductId = asyncHandler( + async (req: Request<{ id: string }, {}, {}, { cursor?: string }>, res: Response) => { + const { id: productId } = req.params; + const { cursor } = req.query; + const comments = await commentService.getCommentsByProductId(productId, cursor); + res.send(comments); + } +); // GET /articles/:id/comments -export const getCommentsByArticleId = async ( - req: Request<{ id: string }, {}, {}, { cursor?: string }>, - res: Response -) => { - const { id: articleId } = req.params; - const { cursor } = req.query; - const comments = await commentService.getCommentsByArticleId(articleId, cursor); - res.send(comments); -}; +export const getCommentsByArticleId = asyncHandler( + async (req: Request<{ id: string }, {}, {}, { cursor?: string }>, res: Response) => { + const { id: articleId } = req.params; + const { cursor } = req.query; + const comments = await commentService.getCommentsByArticleId(articleId, cursor); + res.send(comments); + } +); // POST /comments -export const createComment = async (req: UserRequest, res: Response) => { +export const createComment = asyncHandler(async (req: UserRequest, res: Response) => { assert(req.body, CreateComment); const { userId } = req; @@ -41,10 +40,10 @@ export const createComment = async (req: UserRequest, res: Response) => { const comment = await commentService.createComment(commentData); res.status(201).send(comment); -}; +}); // PATCH /comments/:commentId -export const updateComment = async (req: UserRequest & Request<{ commentId: string }>, res: Response) => { +export const updateComment = asyncHandler(async (req: UserRequest & Request<{ commentId: string }>, res: Response) => { assert(req.body, PatchComment); const { userId } = req; @@ -61,23 +60,15 @@ export const updateComment = async (req: UserRequest & Request<{ commentId: stri return; } - try { - const updatedComment = await commentService.updateComment(commentId, userId, content); - res.send(updatedComment); - } catch (error) { - res.status(403).json({ message: (error as Error).message }); - } -}; + const updatedComment = await commentService.updateComment(commentId, userId, content); + res.send(updatedComment); +}); // DELETE /comments/:commentId -export const deleteComment = async (req: UserRequest & Request<{ commentId: string }>, res: Response) => { +export const deleteComment = asyncHandler(async (req: UserRequest & Request<{ commentId: string }>, res: Response) => { const { commentId } = req.params; const { userId } = req; - try { - await commentService.deleteComment(commentId, userId); - res.sendStatus(204); - } catch (error) { - res.status(403).json({ message: (error as Error).message }); - } -}; + await commentService.deleteComment(commentId, userId); + res.sendStatus(204); +}); diff --git a/src/controllers/imageController.ts b/src/controllers/imageController.ts index 5b9c72d..7609305 100644 --- a/src/controllers/imageController.ts +++ b/src/controllers/imageController.ts @@ -1,11 +1,12 @@ import { Request, Response } from "express"; import * as imageService from "../services/imageService"; +import asyncHandler from "../utils/asyncHandler"; -export const getPresignedUrl = async (req: Request, res: Response) => { +export const getPresignedUrl = asyncHandler(async (req: Request, res: Response) => { try { const presignedUrl = await imageService.generatePresignedUrl(req); res.status(200).json({ url: presignedUrl }); } catch (error) { res.status(400).send((error as Error).message); } -}; +}); diff --git a/src/controllers/productController.ts b/src/controllers/productController.ts index 58cff79..f9c23e3 100644 --- a/src/controllers/productController.ts +++ b/src/controllers/productController.ts @@ -1,92 +1,76 @@ -import { NextFunction, Request, Response } from "express"; +import { Request, Response } from "express"; import { assert } from "superstruct"; import * as productService from "../services/productService"; import { CreateProduct, PatchProduct } from "../structs"; +import asyncHandler from "../utils/asyncHandler"; interface UserRequest extends Request { userId: number; } // GET /products -export const getProducts = async ( - req: Request<{}, {}, {}, { offset?: string; limit?: string; orderBy?: string; keyword?: string }>, - res: Response -) => { - const { offset = "0", limit = "10", orderBy = "recent", keyword = "" } = req.query; - const offsetNumber = parseInt(offset, 10); - const limitNumber = parseInt(limit, 10); - const products = await productService.getProducts({ offset: offsetNumber, limit: limitNumber, orderBy, keyword }); - const bestProducts = await productService.getBestProducts(); - res.send({ products, bestProducts }); -}; +export const getProducts = asyncHandler( + async ( + req: Request<{}, {}, {}, { offset?: string; limit?: string; orderBy?: string; keyword?: string }>, + res: Response + ) => { + const { offset = "0", limit = "10", orderBy = "recent", keyword = "" } = req.query; + const offsetNumber = parseInt(offset, 10); + const limitNumber = parseInt(limit, 10); + const products = await productService.getProducts({ offset: offsetNumber, limit: limitNumber, orderBy, keyword }); + const bestProducts = await productService.getBestProducts(); + res.send({ products, bestProducts }); + } +); // POST /products -export const createProduct = async (req: UserRequest, res: Response) => { +export const createProduct = asyncHandler(async (req: UserRequest, res: Response) => { assert(req.body, CreateProduct); const { userId } = req; const { imageUrl, ...productData } = req.body; const product = await productService.createProduct(userId!, productData, imageUrl || ""); res.status(201).send(product); -}; +}); // GET /products/:id -export const getProductById = async (req: Request<{ id: string }>, res: Response) => { +export const getProductById = asyncHandler(async (req: Request<{ id: string }>, res: Response) => { const { id } = req.params; const product = await productService.getProductById(id); res.send(product); -}; +}); // PATCH /products/:id -export const updateProduct = async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { +export const updateProduct = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { assert(req.body, PatchProduct); const { userId } = req; const { id } = req.params; const { imageUrl, ...productData } = req.body; - try { - const updatedProduct = await productService.updateProduct(id, userId, productData, imageUrl || ""); - res.send(updatedProduct); - } catch (error) { - res.status(403).json({ message: (error as Error).message }); - } -}; + const updatedProduct = await productService.updateProduct(id, userId, productData, imageUrl || ""); + res.send(updatedProduct); +}); // DELETE /products/:id -export const deleteProduct = async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { +export const deleteProduct = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { const { id: productId } = req.params; const { userId } = req; - - try { - await productService.deleteProduct(productId, userId); - res.sendStatus(204); - } catch (error) { - res.status(403).json({ message: (error as Error).message }); - } -}; + await productService.deleteProduct(productId, userId); + res.sendStatus(204); +}); // POST /products/:id/like -export const likeProduct = async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { +export const likeProduct = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { const { id: productId } = req.params; const { userId } = req; - - try { - const updatedProduct = await productService.likeProduct(productId, userId); - res.send(updatedProduct); - } catch (error) { - res.status(400).json({ message: (error as Error).message }); - } -}; + const updatedProduct = await productService.likeProduct(productId, userId); + res.send(updatedProduct); +}); // POST /products/:id/unlike -export const unlikeProduct = async (req: UserRequest & Request<{ id: string }>, res: Response, next: NextFunction) => { +export const unlikeProduct = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { const { id: productId } = req.params; const { userId } = req; - - try { - const updatedProduct = await productService.unlikeProduct(productId, userId); - res.send(updatedProduct); - } catch (error) { - res.status(400).json({ message: (error as Error).message }); - } -}; + const updatedProduct = await productService.unlikeProduct(productId, userId); + res.send(updatedProduct); +}); diff --git a/src/routes/articleRoutes.ts b/src/routes/articleRoutes.ts index 09005a2..341bc90 100644 --- a/src/routes/articleRoutes.ts +++ b/src/routes/articleRoutes.ts @@ -1,8 +1,7 @@ -import express, { Request } from "express"; +import express from "express"; import * as articleController from "../controllers/articleController"; import * as commentController from "../controllers/commentController"; -import authenticate, { UserRequest } from "../middlewares/authenticate"; -import asyncHandler from "../utils/asyncHandler"; +import authenticate from "../middlewares/authenticate"; const router = express.Router(); /** * @swagger @@ -205,10 +204,7 @@ const router = express.Router(); * message: "유효하지 않은 토큰입니다." * */ -router - .route("/") - .get(asyncHandler(articleController.getArticles)) - .post(authenticate, asyncHandler(articleController.createArticle)); +router.route("/").get(articleController.getArticles).post(authenticate, articleController.createArticle); /** * @swagger * /articles/{id}: @@ -441,9 +437,9 @@ router */ router .route("/:id") - .get(asyncHandler>(articleController.getArticleById)) - .patch(authenticate, asyncHandler>(articleController.updateArticle)) - .delete(authenticate, asyncHandler>(articleController.deleteArticle)); + .get(articleController.getArticleById) + .patch(authenticate, articleController.updateArticle) + .delete(authenticate, articleController.deleteArticle); /** * @swagger @@ -528,7 +524,7 @@ router * type: string * example: "이미 좋아요 처리된 게시글입니다." */ -router.route("/:id/like").patch(authenticate, asyncHandler(articleController.likeArticle)); +router.route("/:id/like").patch(authenticate, articleController.likeArticle); /** * @swagger @@ -613,7 +609,7 @@ router.route("/:id/like").patch(authenticate, asyncHandler(articleController.lik * type: string * example: "아직 좋아요 처리되지 않은 게시글입니다." */ -router.route("/:id/unlike").patch(authenticate, asyncHandler(articleController.unlikeArticle)); +router.route("/:id/unlike").patch(authenticate, articleController.unlikeArticle); /** * @swagger @@ -765,8 +761,8 @@ router.route("/:id/unlike").patch(authenticate, asyncHandler(articleController.u router .route("/:articleId/comments") - .get(asyncHandler(commentController.getCommentsByProductId)) - .post(authenticate, asyncHandler(commentController.createComment)); + .get(commentController.getCommentsByProductId) + .post(authenticate, commentController.createComment); /** * @swagger @@ -923,7 +919,7 @@ router */ router .route("/:articleId/comments/:commentId") - .patch(authenticate, asyncHandler(commentController.updateComment)) - .delete(authenticate, asyncHandler(commentController.deleteComment)); + .patch(authenticate, commentController.updateComment) + .delete(authenticate, commentController.deleteComment); export default router; diff --git a/src/routes/authRoutes.ts b/src/routes/authRoutes.ts index 9ebf280..cf322b3 100644 --- a/src/routes/authRoutes.ts +++ b/src/routes/authRoutes.ts @@ -1,7 +1,6 @@ import express from "express"; import passport from "../config/passport.js"; import { googleCallback, refreshToken, signIn, signUp } from "../controllers/authController.js"; -import asyncHandler from "../utils/asyncHandler.js"; const router = express.Router(); @@ -64,7 +63,7 @@ const router = express.Router(); * type: string * example: "이미 가입된 이메일입니다." */ -router.post("/signUp", asyncHandler(signUp)); +router.post("/signUp", signUp); /** * @swagger @@ -113,7 +112,7 @@ router.post("/signUp", asyncHandler(signUp)); * type: string * example: "이메일과 비밀번호를 확인해주세요." */ -router.post("/signIn", asyncHandler(signIn)); +router.post("/signIn", signIn); /** * @swagger @@ -158,7 +157,7 @@ router.post("/signIn", asyncHandler(signIn)); * type: string * example: "유효하지 않은 토큰입니다." */ -router.post("/refresh-token", asyncHandler(refreshToken)); +router.post("/refresh-token", refreshToken); /** * @swagger diff --git a/src/routes/productRoutes.ts b/src/routes/productRoutes.ts index 99be896..60f2079 100644 --- a/src/routes/productRoutes.ts +++ b/src/routes/productRoutes.ts @@ -2,7 +2,6 @@ import express from "express"; import * as commentController from "../controllers/commentController"; import * as productController from "../controllers/productController"; import authenticate from "../middlewares/authenticate"; -import asyncHandler from "../utils/asyncHandler"; const router = express.Router(); /** @@ -158,10 +157,7 @@ const router = express.Router(); * value: * message: "유효하지 않은 토큰입니다." */ -router - .route("/") - .get(asyncHandler(productController.getProducts)) - .post(authenticate, asyncHandler(productController.createProduct)); +router.route("/").get(productController.getProducts).post(authenticate, productController.createProduct); /** * @swagger @@ -387,9 +383,9 @@ router */ router .route("/:id") - .get(asyncHandler(productController.getProductById)) - .patch(authenticate, asyncHandler(productController.updateProduct)) - .delete(authenticate, asyncHandler(productController.deleteProduct)); + .get(productController.getProductById) + .patch(authenticate, productController.updateProduct) + .delete(authenticate, productController.deleteProduct); /** * @swagger @@ -470,7 +466,7 @@ router * type: string * example: "이미 좋아요 처리된 상품입니다." */ -router.route("/:id/like").patch(authenticate, asyncHandler(productController.likeProduct)); +router.route("/:id/like").patch(authenticate, productController.likeProduct); /** * @swagger @@ -551,7 +547,7 @@ router.route("/:id/like").patch(authenticate, asyncHandler(productController.lik * type: string * example: "아직 좋아요 처리되지 않은 상품입니다." */ -router.route("/:id/unlike").patch(authenticate, asyncHandler(productController.unlikeProduct)); +router.route("/:id/unlike").patch(authenticate, productController.unlikeProduct); /** * @swagger @@ -697,7 +693,7 @@ router.route("/:id/unlike").patch(authenticate, asyncHandler(productController.u router .route("/:productId/comments") .get(commentController.getCommentsByProductId) - .post(authenticate, asyncHandler(commentController.createComment)); + .post(authenticate, commentController.createComment); /** * @swagger @@ -855,7 +851,7 @@ router router .route("/:productId/comments/:commentId") - .patch(authenticate, asyncHandler(commentController.updateComment)) - .delete(authenticate, asyncHandler(commentController.deleteComment)); + .patch(authenticate, commentController.updateComment) + .delete(authenticate, commentController.deleteComment); export default router; diff --git a/src/services/articleService.ts b/src/services/articleService.ts index 2e8b7e3..30e456c 100644 --- a/src/services/articleService.ts +++ b/src/services/articleService.ts @@ -1,8 +1,7 @@ -import { Prisma, PrismaClient } from "@prisma/client"; +import { Prisma } from "@prisma/client"; +import prisma from "../client"; import AppError from "../utils/errors"; -const prisma = new PrismaClient(); - export const getArticles = async ({ offset, limit, diff --git a/src/services/commentService.ts b/src/services/commentService.ts index e20787e..ebc30af 100644 --- a/src/services/commentService.ts +++ b/src/services/commentService.ts @@ -1,8 +1,7 @@ -import { Comment, Prisma, PrismaClient } from "@prisma/client"; +import { Comment, Prisma } from "@prisma/client"; +import prisma from "../client"; import AppError from "../utils/errors"; -const prisma = new PrismaClient(); - export const getCommentsByProductId = async (productId: string, cursor?: string): Promise => { const queryOptions: Prisma.CommentFindManyArgs = { take: 10, diff --git a/src/test/articleController.test.ts b/src/test/articleController.test.ts new file mode 100644 index 0000000..353f38e --- /dev/null +++ b/src/test/articleController.test.ts @@ -0,0 +1,263 @@ +import { afterEach, describe, expect, jest, test } from "@jest/globals"; +import { NextFunction, Request, Response } from "express"; +import * as articleController from "../controllers/articleController"; +import * as articleService from "../services/articleService"; +import AppError from "../utils/errors"; + +jest.mock("../services/articleService"); + +const setup = () => { + const req = { + body: {}, + params: {}, + query: {}, + userId: 1, + } as unknown as Request<{ id: string }> & { userId: number }; + + const res = { + status: jest.fn().mockReturnThis(), + json: jest.fn(), + send: jest.fn(), + sendStatus: jest.fn(), + } as unknown as Response; + + const next = jest.fn() as NextFunction; + + return { req, res, next }; +}; + +const mockArticle = { + id: "test-article-id", + title: "새로운 게시글", + content: "새로운 게시글 내용", + createdAt: new Date(), + updatedAt: new Date(), + likeCount: 0, + writer: "김판다", + userId: 1, + images: [ + { + id: "image-id", + imagePath: "image1.jpg", + articleId: "test-article-id", + createdAt: new Date(), + updatedAt: new Date(), + productId: null, + }, + ], +}; + +describe("게시글 컨트롤러", () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + describe("getArticles", () => { + test("게시글과 베스트 게시글을 반환한다", async () => { + const { req, res, next } = setup(); + req.query = { offset: "0", limit: "10", orderBy: "recent", keyword: "" }; + + const mockArticles = [mockArticle]; + const mockBestArticles = [mockArticle]; + + (articleService.getArticles as jest.MockedFunction).mockResolvedValue( + mockArticles + ); + (articleService.getBestArticles as jest.MockedFunction).mockResolvedValue( + mockBestArticles + ); + + await articleController.getArticles(req, res, next); + + expect(res.send).toHaveBeenCalledWith({ articles: mockArticles, bestArticles: mockBestArticles }); + expect(articleService.getArticles).toHaveBeenCalledWith({ offset: 0, limit: 10, orderBy: "recent", keyword: "" }); + expect(articleService.getBestArticles).toHaveBeenCalled(); + }); + + test("쿼리 파라미터가 없는 경우 기본값으로 동작한다", async () => { + const { req, res, next } = setup(); + await articleController.getArticles(req, res, next); + expect(articleService.getArticles).toHaveBeenCalledWith({ offset: 0, limit: 10, orderBy: "recent", keyword: "" }); + }); + }); + + describe("createArticle", () => { + test("게시글을 생성한다", async () => { + const { req, res, next } = setup(); + req.body = { title: "새로운 게시글", content: "새로운 게시글 내용", imageUrl: "image1.jpg" }; + + (articleService.createArticle as jest.MockedFunction).mockResolvedValue( + mockArticle + ); + + await articleController.createArticle(req, res, next); + + expect(articleService.createArticle).toHaveBeenCalledWith( + req.userId, + { title: "새로운 게시글", content: "새로운 게시글 내용" }, + "image1.jpg" + ); + expect(res.status).toHaveBeenCalledWith(201); + expect(res.send).toHaveBeenCalledWith(mockArticle); + }); + }); + + describe("getArticleById", () => { + test("ID로 게시글을 반환한다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + + (articleService.getArticleById as jest.MockedFunction).mockResolvedValue( + mockArticle + ); + + await articleController.getArticleById(req, res, next); + + expect(articleService.getArticleById).toHaveBeenCalledWith("1"); + expect(res.send).toHaveBeenCalledWith(mockArticle); + }); + + test("존재하지 않는 게시글을 조회하려고 하면 예외를 발생시킨다", async () => { + const { req, res, next } = setup(); + req.params = { id: "non-existent-id" }; + + (articleService.getArticleById as jest.MockedFunction).mockRejectedValue( + new AppError("존재하지 않는 게시글입니다.", 404) + ); + + await articleController.getArticleById(req, res, next); + + expect(res.status).toHaveBeenCalledWith(404); + expect(res.json).toHaveBeenCalledWith({ message: "존재하지 않는 게시글입니다." }); + }); + }); + + describe("updateArticle", () => { + test("게시글을 업데이트한다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + req.body = { title: "수정된 게시글", content: "수정된 게시글 내용", imageUrl: "image1.jpg" }; + + const mockUpdatedArticle = { ...mockArticle, title: "수정된 게시글" }; + + (articleService.updateArticle as jest.MockedFunction).mockResolvedValue( + mockUpdatedArticle + ); + + await articleController.updateArticle(req, res, next); + + expect(articleService.updateArticle).toHaveBeenCalledWith( + "1", + req.userId, + { title: "수정된 게시글", content: "수정된 게시글 내용" }, + "image1.jpg" + ); + expect(res.send).toHaveBeenCalledWith(mockUpdatedArticle); + }); + + test("게시글 수정 시 권한이 없으면 예외를 발생시킨다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + req.body = { title: "수정된 게시글", content: "수정된 게시글 내용", imageUrl: "image1.jpg" }; + + (articleService.updateArticle as jest.MockedFunction).mockRejectedValue( + new AppError("게시글을 수정할 권한이 없습니다.", 403) + ); + + await articleController.updateArticle(req, res, next); + + expect(res.status).toHaveBeenCalledWith(403); + expect(res.json).toHaveBeenCalledWith({ message: "게시글을 수정할 권한이 없습니다." }); + }); + }); + + describe("deleteArticle", () => { + test("게시글을 삭제한다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + + await articleController.deleteArticle(req, res, next); + + expect(articleService.deleteArticle).toHaveBeenCalledWith("1", req.userId); + expect(res.sendStatus).toHaveBeenCalledWith(204); + }); + + test("게시글 삭제 시 권한이 없으면 예외를 발생시킨다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + + (articleService.deleteArticle as jest.MockedFunction).mockRejectedValue( + new AppError("게시글을 삭제할 권한이 없습니다.", 403) + ); + + await articleController.deleteArticle(req, res, next); + + expect(res.status).toHaveBeenCalledWith(403); + expect(res.json).toHaveBeenCalledWith({ message: "게시글을 삭제할 권한이 없습니다." }); + }); + }); + + describe("likeArticle", () => { + test("게시글에 좋아요를 누른다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + + const mockUpdatedArticle = { ...mockArticle, likeCount: 1 }; + + (articleService.likeArticle as jest.MockedFunction).mockResolvedValue( + mockUpdatedArticle + ); + + await articleController.likeArticle(req, res, next); + + expect(articleService.likeArticle).toHaveBeenCalledWith("1", req.userId); + expect(res.send).toHaveBeenCalledWith(mockUpdatedArticle); + }); + + test("이미 좋아요가 된 게시글에 좋아요를 누를 경우 에러를 반환한다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + + (articleService.likeArticle as jest.MockedFunction).mockRejectedValue( + new AppError("이미 좋아요 처리된 게시글입니다.", 409) + ); + + await articleController.likeArticle(req, res, next); + + expect(res.status).toHaveBeenCalledWith(409); + expect(res.json).toHaveBeenCalledWith({ message: "이미 좋아요 처리된 게시글입니다." }); + }); + }); + + describe("unlikeArticle", () => { + test("게시글에 좋아요를 취소한다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + + const mockUpdatedArticle = { ...mockArticle, likeCount: 0 }; + + (articleService.unlikeArticle as jest.MockedFunction).mockResolvedValue( + mockUpdatedArticle + ); + + await articleController.unlikeArticle(req, res, next); + + expect(articleService.unlikeArticle).toHaveBeenCalledWith("1", req.userId); + expect(res.send).toHaveBeenCalledWith(mockUpdatedArticle); + }); + + test("아직 좋아요 처리되지 않은 게시글의 좋아요를 취소하려고 할 경우 에러를 반환한다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + + (articleService.unlikeArticle as jest.MockedFunction).mockRejectedValue( + new AppError("아직 좋아요 처리되지 않은 게시글입니다.", 409) + ); + + await articleController.unlikeArticle(req, res, next); + + expect(res.status).toHaveBeenCalledWith(409); + expect(res.json).toHaveBeenCalledWith({ message: "아직 좋아요 처리되지 않은 게시글입니다." }); + }); + }); +}); diff --git a/src/test/articleService.test.ts b/src/test/articleService.test.ts new file mode 100644 index 0000000..2563591 --- /dev/null +++ b/src/test/articleService.test.ts @@ -0,0 +1,447 @@ +import { describe, expect, jest, test } from "@jest/globals"; +import prisma from "../client"; +import { + createArticle, + deleteArticle, + getArticleById, + getArticles, + getBestArticles, + likeArticle, + unlikeArticle, + updateArticle, +} from "../services/articleService"; +import AppError from "../utils/errors"; + +jest.mock("../client", () => ({ + __esModule: true, + default: { + article: { + findMany: jest.fn(), + create: jest.fn(), + findUnique: jest.fn(), + findUniqueOrThrow: jest.fn(), + update: jest.fn(), + delete: jest.fn(), + }, + user: { + findUnique: jest.fn(), + }, + image: { + update: jest.fn(), + create: jest.fn(), + }, + favorite: { + findUnique: jest.fn(), + create: jest.fn(), + delete: jest.fn(), + }, + $transaction: jest.fn(), + }, +})); + +const mockArticle = { + id: "test-article-id", + title: "새로운 게시글", + content: "새로운 게시글 내용", + createdAt: new Date(), + updatedAt: new Date(), + likeCount: 0, + writer: "김판다", + userId: 1, + images: [ + { + id: "image-id", + imagePath: "image1.jpg", + articleId: "test-article-id", + createdAt: new Date(), + updatedAt: new Date(), + productId: null, + }, + ], +}; + +const mockUser = { + id: 1, + googleId: null, + email: "test@example.com", + name: "테스트 유저", + nickname: "testuser", + image: null, + password: null, + createdAt: new Date(), + updatedAt: new Date(), +}; + +const mockFavorite = { + id: "favorite-id", + createdAt: new Date(), + userId: 1, + productId: null, + articleId: "test-article-id", +}; + +describe("게시글 서비스", () => { + describe("게시글을 조회한다", () => { + test("게시글을 조회한다", async () => { + const articles = [mockArticle]; + (prisma.article.findMany as jest.MockedFunction).mockResolvedValue(articles); + + const result = await getArticles({ offset: 0, limit: 10, orderBy: "recent", keyword: "" }); + expect(result).toEqual(articles); + expect(prisma.article.findMany).toHaveBeenCalledWith({ + orderBy: { createdAt: "desc" }, + skip: 0, + take: 10, + where: { + OR: [{ title: { contains: "", mode: "insensitive" } }, { content: { contains: "", mode: "insensitive" } }], + }, + select: { + id: true, + title: true, + content: true, + createdAt: true, + writer: true, + images: { + select: { imagePath: true }, + }, + }, + }); + }); + + test("베스트 게시글을 조회한다", async () => { + const articles = [mockArticle]; + (prisma.article.findMany as jest.MockedFunction).mockResolvedValue(articles); + + const result = await getBestArticles(); + expect(result).toEqual(articles); + expect(prisma.article.findMany).toHaveBeenCalledWith({ + orderBy: { likeCount: "desc" }, + take: 4, + select: { + id: true, + title: true, + content: true, + createdAt: true, + writer: true, + images: { + select: { imagePath: true }, + }, + }, + }); + }); + }); + + describe("게시글을 생성한다", () => { + test("게시글을 생성한다", async () => { + (prisma.user.findUnique as jest.MockedFunction).mockResolvedValue(mockUser); + (prisma.article.create as jest.MockedFunction).mockResolvedValue(mockArticle); + + const result = await createArticle(1, { title: "새로운 게시글", content: "새로운 게시글 내용" }, "image1.jpg"); + + expect(result).toEqual(mockArticle); + expect(prisma.user.findUnique).toHaveBeenCalledWith({ + where: { id: 1 }, + select: { name: true }, + }); + expect(prisma.article.create).toHaveBeenCalledWith({ + data: { + title: "새로운 게시글", + content: "새로운 게시글 내용", + writer: "테스트 유저", + user: { connect: { id: 1 } }, + images: { create: [{ imagePath: "image1.jpg" }] }, + }, + include: { images: true }, + }); + }); + + test("유저가 없을 때 게시글을 생성하려고 하면 예외를 발생시킨다", async () => { + (prisma.user.findUnique as jest.MockedFunction).mockResolvedValue(null); + await expect( + createArticle(1, { title: "새로운 게시글", content: "새로운 게시글 내용" }, "image1.jpg") + ).rejects.toThrow("유저 정보를 찾을 수 없습니다."); + }); + }); + + describe("게시글 ID로 게시글을 조회한다", () => { + test("게시글 ID로 게시글을 조회한다", async () => { + ( + prisma.article.findUniqueOrThrow as jest.MockedFunction + ).mockResolvedValue(mockArticle); + + const result = await getArticleById("test-article-id"); + expect(result).toEqual(mockArticle); + expect(prisma.article.findUniqueOrThrow).toHaveBeenCalledWith({ + where: { id: "test-article-id" }, + select: { + id: true, + title: true, + content: true, + createdAt: true, + likeCount: true, + writer: true, + images: { + select: { imagePath: true }, + }, + }, + }); + }); + + test("존재하지 않는 게시글을 조회하려고 하면 예외를 발생시킨다", async () => { + const error = new Error("No Article found"); + ( + prisma.article.findUniqueOrThrow as jest.MockedFunction + ).mockRejectedValue(error); + + await expect(getArticleById("non-existent-article-id")).rejects.toThrow("No Article found"); + }); + }); + + describe("게시글을 수정한다", () => { + test("게시글을 수정할 권한이 없으면 예외를 발생시킨다", async () => { + const anotherUserArticle = { ...mockArticle, userId: 2 }; + ( + prisma.article.findUniqueOrThrow as jest.MockedFunction + ).mockResolvedValue(anotherUserArticle); + + await expect( + updateArticle("test-article-id", 1, { title: "수정된 게시글", content: "수정된 게시글 내용" }, "image1.jpg") + ).rejects.toThrow("게시글을 수정할 권한이 없습니다."); + }); + + test("게시글을 수정한다", async () => { + ( + prisma.article.findUniqueOrThrow as jest.MockedFunction + ).mockResolvedValue(mockArticle); + (prisma.article.update as jest.MockedFunction).mockResolvedValue(mockArticle); + (prisma.image.update as jest.MockedFunction).mockResolvedValue(mockArticle.images[0]); + (prisma.image.create as jest.MockedFunction).mockResolvedValue(mockArticle.images[0]); + + const result = await updateArticle( + "test-article-id", + 1, + { title: "수정된 게시글", content: "수정된 게시글 내용" }, + "image1.jpg" + ); + + expect(result).toEqual(mockArticle); + expect(prisma.article.findUniqueOrThrow).toHaveBeenCalledWith({ + where: { id: "test-article-id" }, + include: { images: true }, + }); + + const existingImage = mockArticle.images[0]; + if (existingImage) { + expect(prisma.image.update).toHaveBeenCalledWith({ + where: { id: existingImage.id }, + data: { imagePath: "image1.jpg" }, + }); + } else { + expect(prisma.image.create).toHaveBeenCalledWith({ + data: { + imagePath: "image1.jpg", + article: { connect: { id: "test-article-id" } }, + }, + }); + } + + expect(prisma.article.update).toHaveBeenCalledWith({ + where: { id: "test-article-id" }, + data: { + title: "수정된 게시글", + content: "수정된 게시글 내용", + }, + include: { images: true }, + }); + }); + + test("이미지 URL이 없는 경우 게시글을 수정한다", async () => { + ( + prisma.article.findUniqueOrThrow as jest.MockedFunction + ).mockResolvedValue(mockArticle); + (prisma.article.update as jest.MockedFunction).mockResolvedValue(mockArticle); + + const result = await updateArticle( + "test-article-id", + 1, + { title: "수정된 게시글", content: "수정된 게시글 내용" }, + "" + ); + + expect(result).toEqual(mockArticle); + expect(prisma.article.findUniqueOrThrow).toHaveBeenCalledWith({ + where: { id: "test-article-id" }, + include: { images: true }, + }); + + expect(prisma.image.update).not.toHaveBeenCalled(); + expect(prisma.image.create).not.toHaveBeenCalled(); + + expect(prisma.article.update).toHaveBeenCalledWith({ + where: { id: "test-article-id" }, + data: { + title: "수정된 게시글", + content: "수정된 게시글 내용", + }, + include: { images: true }, + }); + }); + + test("기존 이미지가 없는 경우 이미지를 생성한다", async () => { + const mockArticleWithoutImage = { ...mockArticle, images: [] }; + ( + prisma.article.findUniqueOrThrow as jest.MockedFunction + ).mockResolvedValue(mockArticleWithoutImage); + (prisma.article.update as jest.MockedFunction).mockResolvedValue(mockArticle); + (prisma.image.create as jest.MockedFunction).mockResolvedValue(mockArticle.images[0]); + + const result = await updateArticle( + "test-article-id", + 1, + { title: "수정된 게시글", content: "수정된 게시글 내용" }, + "image1.jpg" + ); + + expect(result).toEqual(mockArticle); + expect(prisma.article.findUniqueOrThrow).toHaveBeenCalledWith({ + where: { id: "test-article-id" }, + include: { images: true }, + }); + + expect(prisma.image.update).not.toHaveBeenCalled(); + expect(prisma.image.create).toHaveBeenCalledWith({ + data: { + imagePath: "image1.jpg", + article: { connect: { id: "test-article-id" } }, + }, + }); + + expect(prisma.article.update).toHaveBeenCalledWith({ + where: { id: "test-article-id" }, + data: { + title: "수정된 게시글", + content: "수정된 게시글 내용", + }, + include: { images: true }, + }); + }); + }); + + describe("게시글을 삭제한다", () => { + test("게시글을 삭제한다", async () => { + ( + prisma.article.findUniqueOrThrow as jest.MockedFunction + ).mockResolvedValue(mockArticle); + (prisma.article.delete as jest.MockedFunction).mockResolvedValue(mockArticle); + + await deleteArticle("test-article-id", 1); + + expect(prisma.article.findUniqueOrThrow).toHaveBeenCalledWith({ + where: { id: "test-article-id" }, + }); + + expect(prisma.article.delete).toHaveBeenCalledWith({ + where: { id: "test-article-id" }, + }); + }); + + test("존재하지 않는 게시글을 삭제하려고 하면 예외를 발생시킨다", async () => { + ( + prisma.article.findUniqueOrThrow as jest.MockedFunction + ).mockRejectedValue(new AppError("존재하지 않는 게시글입니다.", 404)); + + await expect(deleteArticle("non-existent-article-id", 1)).rejects.toThrow("존재하지 않는 게시글입니다."); + }); + + test("게시글을 삭제할 권한이 없으면 예외를 발생시킨다", async () => { + const anotherUserArticle = { ...mockArticle, userId: 2 }; + ( + prisma.article.findUniqueOrThrow as jest.MockedFunction + ).mockResolvedValue(anotherUserArticle); + + await expect(deleteArticle("test-article-id", 1)).rejects.toThrow("게시글을 삭제할 권한이 없습니다."); + }); + }); + + describe("게시글에 좋아요를 누른다", () => { + test("게시글에 좋아요를 누른다", async () => { + const updatedArticle = { ...mockArticle, likeCount: mockArticle.likeCount + 1 }; + (prisma.favorite.findUnique as jest.MockedFunction).mockResolvedValue(null); + (prisma.article.update as jest.MockedFunction).mockResolvedValue(updatedArticle); + (prisma.$transaction as jest.MockedFunction).mockResolvedValue([ + null, + updatedArticle, + ]); + + const result = await likeArticle("test-article-id", 1); + expect(result).toEqual(updatedArticle); + expect(result.likeCount).toBe(mockArticle.likeCount + 1); + expect(prisma.favorite.findUnique).toHaveBeenCalledWith({ + where: { + userId_articleId: { + userId: 1, + articleId: "test-article-id", + }, + }, + }); + expect(prisma.$transaction).toHaveBeenCalled(); + }); + + test("이미 좋아요가 된 게시글에 좋아요를 누를 경우 에러를 반환한다", async () => { + (prisma.favorite.findUnique as jest.MockedFunction).mockResolvedValue( + mockFavorite + ); + + await expect(likeArticle("test-article-id", 1)).rejects.toThrow("이미 좋아요 처리된 게시글입니다."); + expect(prisma.favorite.findUnique).toHaveBeenCalledWith({ + where: { + userId_articleId: { + userId: 1, + articleId: "test-article-id", + }, + }, + }); + }); + }); + + describe("게시글에 좋아요를 취소한다", () => { + test("게시글에 좋아요를 취소한다", async () => { + const updatedArticle = { ...mockArticle, likeCount: mockArticle.likeCount - 1 }; + (prisma.favorite.findUnique as jest.MockedFunction).mockResolvedValue( + mockFavorite + ); + (prisma.article.update as jest.MockedFunction).mockResolvedValue(updatedArticle); + (prisma.$transaction as jest.MockedFunction).mockResolvedValue([ + null, + updatedArticle, + ]); + + const result = await unlikeArticle("test-article-id", 1); + expect(result).toEqual(updatedArticle); + expect(result.likeCount).toBe(mockArticle.likeCount - 1); + expect(prisma.favorite.findUnique).toHaveBeenCalledWith({ + where: { + userId_articleId: { + userId: 1, + articleId: "test-article-id", + }, + }, + }); + expect(prisma.$transaction).toHaveBeenCalled(); + }); + + test("좋아요가 취소된 게시글을 다시 취소하려고 할 경우 에러를 반환한다", async () => { + (prisma.favorite.findUnique as jest.MockedFunction).mockResolvedValue(null); + + await expect(unlikeArticle("test-article-id", 1)).rejects.toThrow("아직 좋아요 처리되지 않은 게시글입니다."); + expect(prisma.favorite.findUnique).toHaveBeenCalledWith({ + where: { + userId_articleId: { + userId: 1, + articleId: "test-article-id", + }, + }, + }); + }); + }); +}); diff --git a/src/test/authController.test.ts b/src/test/authController.test.ts index b6974ea..2dd1bff 100644 --- a/src/test/authController.test.ts +++ b/src/test/authController.test.ts @@ -41,11 +41,13 @@ describe("Auth Controller - 회원가입", () => { status: jest.fn().mockReturnThis(), } as unknown as Response; - return { req, res }; + const next = jest.fn() as NextFunction; + + return { req, res, next }; }; test("유효성 검사 오류가 발생하면 400 상태 코드를 반환한다", async () => { - const { req, res } = setup(); + const { req, res, next } = setup(); req.body.email = ""; @@ -67,7 +69,7 @@ describe("Auth Controller - 회원가입", () => { throw structError; }); - await signUp(req, res); + await signUp(req, res, next); expect(res.status).toHaveBeenCalledWith(400); expect(res.json).toHaveBeenCalledWith({ @@ -77,7 +79,7 @@ describe("Auth Controller - 회원가입", () => { }); test("이미 존재하는 이메일로 회원가입하면 400 상태 코드를 반환한다", async () => { - const { req, res } = setup(); + const { req, res, next } = setup(); (assert as jest.Mock).mockImplementation(() => {}); const mockUser = { id: 1, @@ -93,14 +95,14 @@ describe("Auth Controller - 회원가입", () => { (findUserByEmail as jest.MockedFunction).mockResolvedValue(mockUser); - await signUp(req, res); + await signUp(req, res, next); expect(res.status).toHaveBeenCalledWith(400); expect(res.json).toHaveBeenCalledWith({ message: "이미 가입된 이메일입니다." }); }); test("StructError가 발생하면 400 상태 코드를 반환한다", async () => { - const { req, res } = setup(); + const { req, res, next } = setup(); const failure = { type: "email", @@ -120,7 +122,7 @@ describe("Auth Controller - 회원가입", () => { throw structError; }); - await signUp(req, res); + await signUp(req, res, next); expect(res.status).toHaveBeenCalledWith(400); expect(res.json).toHaveBeenCalledWith({ @@ -130,21 +132,21 @@ describe("Auth Controller - 회원가입", () => { }); test("일반적인 오류가 발생하면 500 상태 코드를 반환한다", async () => { - const { req, res } = setup(); + const { req, res, next } = setup(); (assert as jest.Mock).mockImplementation(() => {}); (findUserByEmail as jest.MockedFunction).mockResolvedValue(null); (createUser as jest.MockedFunction).mockImplementation(() => { throw new Error("Database error"); }); - await signUp(req, res); + await signUp(req, res, next); expect(res.status).toHaveBeenCalledWith(500); expect(res.json).toHaveBeenCalledWith({ message: "서버 에러입니다." }); }); test("성공적으로 회원가입하면 201 상태 코드를 반환한다", async () => { - const { req, res } = setup(); + const { req, res, next } = setup(); (assert as jest.Mock).mockImplementation(() => {}); (findUserByEmail as jest.MockedFunction).mockResolvedValue(null); (createUser as jest.MockedFunction).mockResolvedValue({ @@ -159,7 +161,7 @@ describe("Auth Controller - 회원가입", () => { updatedAt: new Date(), }); - await signUp(req, res); + await signUp(req, res, next); expect(res.status).toHaveBeenCalledWith(201); expect(res.json).toHaveBeenCalledWith({ message: "회원가입이 완료되었습니다." }); @@ -180,7 +182,8 @@ describe("Auth Controller - signIn", () => { status: jest.fn().mockReturnThis(), } as unknown as Response; - return { req, res }; + const next = jest.fn() as NextFunction; + return { req, res, next }; }; test("성공적으로 로그인하면 토큰을 반환한다", async () => { @@ -196,14 +199,14 @@ describe("Auth Controller - signIn", () => { image: null, }; - const { req, res } = setup(); + const { req, res, next } = setup(); (findUserByEmail as jest.MockedFunction).mockResolvedValue(mockUser); (validatePassword as jest.MockedFunction).mockResolvedValue(true); (generateAccessToken as jest.MockedFunction).mockReturnValue("accessToken"); (generateRefreshToken as jest.MockedFunction).mockReturnValue("refreshToken"); - await signIn(req, res); + await signIn(req, res, next); expect(findUserByEmail).toHaveBeenCalledWith("test@example.com"); expect(validatePassword).toHaveBeenCalledWith("password", "hashedPassword"); @@ -213,7 +216,7 @@ describe("Auth Controller - signIn", () => { }); test("비밀번호가 틀리면 401 상태 코드를 반환한다", async () => { - const { req, res } = setup(); + const { req, res, next } = setup(); const mockUser = { id: 1, @@ -230,18 +233,18 @@ describe("Auth Controller - signIn", () => { (findUserByEmail as jest.MockedFunction).mockResolvedValue(mockUser); (validatePassword as jest.MockedFunction).mockResolvedValue(false); - await signIn(req, res); + await signIn(req, res, next); expect(res.status).toHaveBeenCalledWith(401); expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 확인해주세요." }); }); test("사용자가 존재하지 않으면 401 상태 코드를 반환한다", async () => { - const { req, res } = setup(); + const { req, res, next } = setup(); (findUserByEmail as jest.MockedFunction).mockResolvedValue(null); - await signIn(req, res); + await signIn(req, res, next); expect(res.status).toHaveBeenCalledWith(401); expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 확인해주세요." }); @@ -259,8 +262,8 @@ describe("Auth Controller - signIn", () => { json: jest.fn(), status: jest.fn().mockReturnThis(), } as unknown as Response; - - await signIn(req, res); + const next = jest.fn() as NextFunction; + await signIn(req, res, next); expect(res.status).toHaveBeenCalledWith(400); expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 입력해주세요." }); @@ -278,8 +281,8 @@ describe("Auth Controller - signIn", () => { json: jest.fn(), status: jest.fn().mockReturnThis(), } as unknown as Response; - - await signIn(req, res); + const next = jest.fn() as NextFunction; + await signIn(req, res, next); expect(res.status).toHaveBeenCalledWith(400); expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 입력해주세요." }); @@ -297,8 +300,8 @@ describe("Auth Controller - signIn", () => { json: jest.fn(), status: jest.fn().mockReturnThis(), } as unknown as Response; - - await signIn(req, res); + const next = jest.fn() as NextFunction; + await signIn(req, res, next); expect(res.status).toHaveBeenCalledWith(401); expect(res.json).toHaveBeenCalledWith({ message: "이메일과 비밀번호를 확인해주세요." }); @@ -324,7 +327,7 @@ describe("Auth Controller - refreshToken", () => { }; test("유효한 토큰이면 새로운 액세스 토큰과 리프레시 토큰을 반환한다", async () => { - const { req, res } = setup(); + const { req, res, next } = setup(); const mockUser = { id: 1, email: "test@example.com", @@ -342,20 +345,20 @@ describe("Auth Controller - refreshToken", () => { (findUserById as jest.MockedFunction).mockResolvedValue(mockUser); (generateAccessToken as jest.MockedFunction).mockReturnValue("newAccessToken"); - await refreshToken(req, res); + await refreshToken(req, res, next); expect(jwt.verify).toHaveBeenCalledWith("validToken", JWT_SECRET); expect(res.json).toHaveBeenCalledWith({ accessToken: "newAccessToken", refreshToken: "validToken" }); }); test("유효하지 않은 토큰이면 401 상태 코드를 반환한다", async () => { - const { req, res } = setup(); + const { req, res, next } = setup(); (regenerateRefreshToken as jest.MockedFunction).mockImplementation(() => { throw new Error("Invalid token"); }); - await refreshToken(req, res); + await refreshToken(req, res, next); expect(res.status).toHaveBeenCalledWith(401); expect(res.json).toHaveBeenCalledWith({ message: "유효하지 않은 토큰입니다." }); @@ -370,21 +373,21 @@ describe("Auth Controller - refreshToken", () => { json: jest.fn(), status: jest.fn().mockReturnThis(), } as unknown as Response; - - await refreshToken(req, res); + const next = jest.fn() as NextFunction; + await refreshToken(req, res, next); expect(res.status).toHaveBeenCalledWith(401); expect(res.json).toHaveBeenCalledWith({ message: "토큰은 필수값입니다." }); }); test("findUserById가 null을 반환하면 401 상태 코드를 반환한다", async () => { - const { req, res } = setup(); + const { req, res, next } = setup(); (regenerateRefreshToken as jest.MockedFunction).mockReturnValue("newRefreshToken"); (jwt.verify as jest.Mock).mockReturnValue({ userId: 1 } as JWTPayload); (findUserById as jest.MockedFunction).mockResolvedValue(null); - await refreshToken(req, res); + await refreshToken(req, res, next); expect(res.status).toHaveBeenCalledWith(401); expect(res.json).toHaveBeenCalledWith({ message: "유효하지 않은 토큰입니다." }); diff --git a/src/test/productController.test.ts b/src/test/productController.test.ts new file mode 100644 index 0000000..3a13b6e --- /dev/null +++ b/src/test/productController.test.ts @@ -0,0 +1,375 @@ +import { describe, expect, jest, test } from "@jest/globals"; +import { NextFunction, Request, Response } from "express"; +import { assert } from "superstruct"; +import * as productController from "../controllers/productController"; +import * as productService from "../services/productService"; +import { CreateProduct, PatchProduct } from "../structs"; +import AppError from "../utils/errors"; + +const mockProducts = [ + { + id: "test-product-id", + name: "테스트 상품", + description: "이것은 테스트 상품입니다", + price: 100, + favoriteCount: 0, + createdAt: new Date(), + updatedAt: new Date(), + writer: "테스트 유저", + tags: [], + userId: 1, + images: [ + { + id: "image-id", + imagePath: "image1.jpg", + productId: null, + createdAt: new Date(), + updatedAt: new Date(), + articleId: null, + }, + ], + }, +]; + +const mockBestProducts = [ + { + id: "test-product-id", + name: "베스트 상품", + description: "이것은 베스트 상품입니다", + price: 200, + favoriteCount: 100, + createdAt: new Date(), + updatedAt: new Date(), + writer: "베스트 유저", + tags: [], + userId: 1, + images: [ + { + id: "image-id", + imagePath: "bestimage1.jpg", + productId: null, + createdAt: new Date(), + updatedAt: new Date(), + articleId: null, + }, + ], + }, +]; + +jest.mock("superstruct", () => { + const originalModule = jest.requireActual("superstruct"); + return { + ...originalModule, + assert: jest.fn(), + }; +}); + +jest.mock("../services/productService"); + +const setup = () => { + const req = { + body: {}, + params: {}, + query: {}, + userId: 1, + } as unknown as Request<{ id: string }> & { userId: number }; + + const res = { + status: jest.fn().mockReturnThis(), + json: jest.fn(), + send: jest.fn(), + sendStatus: jest.fn(), + } as unknown as Response; + + const next = jest.fn() as NextFunction; + + return { req, res, next }; +}; + +describe("상품 컨트롤러", () => { + describe("getProducts", () => { + test("상품과 베스트 상품을 반환해야 한다", async () => { + const { req, res, next } = setup(); + req.query = { offset: "0", limit: "10", orderBy: "recent", keyword: "" }; + + (productService.getProducts as jest.MockedFunction).mockResolvedValue( + mockProducts + ); + (productService.getBestProducts as jest.MockedFunction).mockResolvedValue( + mockBestProducts + ); + + await productController.getProducts(req, res, next); + + expect(res.send).toHaveBeenCalledWith({ products: mockProducts, bestProducts: mockBestProducts }); + }); + }); + + describe("createProduct", () => { + test("상품을 생성해야 한다", async () => { + const { req, res, next } = setup(); + req.body = { name: "새로운 판다인형", price: 100, description: "새로운 상품입니다." }; + + const mockProduct = { + id: "test-product-id", + name: "새로운 판다인형", + description: "새로운 상품입니다.", + price: 100, + favoriteCount: 0, + createdAt: new Date(), + updatedAt: new Date(), + writer: "테스트 유저", + tags: [], + userId: 1, + images: [ + { + id: "image-id", + imagePath: "image1.jpg", + productId: null, + createdAt: new Date(), + updatedAt: new Date(), + articleId: null, + }, + ], + }; + + (productService.createProduct as jest.MockedFunction).mockResolvedValue( + mockProduct + ); + + await productController.createProduct(req, res, next); + + expect(assert).toHaveBeenCalledWith(req.body, CreateProduct); + expect(productService.createProduct).toHaveBeenCalledWith(req.userId, req.body, ""); + expect(res.status).toHaveBeenCalledWith(201); + expect(res.send).toHaveBeenCalledWith(mockProduct); + }); + }); + + describe("getProductById", () => { + test("ID로 상품을 반환해야 한다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + + const mockProduct = { + id: "test-product-id", + name: "새로운 판다 1", + description: "새로운 상품", + price: 100, + favoriteCount: 0, + createdAt: new Date(), + updatedAt: new Date(), + writer: "테스트 유저", + tags: [], + userId: 1, + images: [ + { + id: "image-id", + imagePath: "image1.jpg", + productId: null, + createdAt: new Date(), + updatedAt: new Date(), + articleId: null, + }, + ], + }; + + (productService.getProductById as jest.MockedFunction).mockResolvedValue( + mockProduct + ); + + await productController.getProductById(req, res, next); + + expect(productService.getProductById).toHaveBeenCalledWith("1"); + expect(res.send).toHaveBeenCalledWith(mockProduct); + }); + }); + + describe("updateProduct", () => { + test("상품을 업데이트해야 한다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + req.body = { name: "수정된 판다", price: 150 }; + + const mockUpdatedProduct = { + id: "test-product-id", + name: "수정된 판다", + description: "수정된 상품입니다.", + price: 150, + favoriteCount: 0, + createdAt: new Date(), + updatedAt: new Date(), + writer: "테스트 유저", + tags: [], + userId: 1, + images: [ + { + id: "image-id", + imagePath: "image1.jpg", + productId: null, + createdAt: new Date(), + updatedAt: new Date(), + articleId: null, + }, + ], + }; + + (productService.updateProduct as jest.MockedFunction).mockResolvedValue( + mockUpdatedProduct + ); + + await productController.updateProduct(req, res, next); + + expect(assert).toHaveBeenCalledWith(req.body, PatchProduct); + expect(productService.updateProduct).toHaveBeenCalledWith("1", req.userId, req.body, ""); + expect(res.send).toHaveBeenCalledWith(mockUpdatedProduct); + }); + + test("상품 수정 시 권한이 없으면 예외를 발생시킨다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + req.body = { name: "Updated Product", price: 150 }; + + (productService.updateProduct as jest.MockedFunction).mockRejectedValue( + new AppError("게시글을 수정할 권한이 없습니다.", 403) + ); + + await productController.updateProduct(req, res, next); + + expect(res.status).toHaveBeenCalledWith(403); + expect(res.json).toHaveBeenCalledWith({ message: "게시글을 수정할 권한이 없습니다." }); + }); + }); + + describe("deleteProduct", () => { + test("상품을 삭제해야 한다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + + await productController.deleteProduct(req, res, next); + + expect(productService.deleteProduct).toHaveBeenCalledWith("1", req.userId); + expect(res.sendStatus).toHaveBeenCalledWith(204); + }); + + test("상품 삭제 시 권한이 없으면 예외를 발생시킨다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + + (productService.deleteProduct as jest.MockedFunction).mockRejectedValue( + new AppError("게시글을 삭제할 권한이 없습니다.", 403) + ); + + await productController.deleteProduct(req, res, next); + + expect(res.status).toHaveBeenCalledWith(403); + expect(res.json).toHaveBeenCalledWith({ message: "게시글을 삭제할 권한이 없습니다." }); + }); + }); + + describe("likeProduct", () => { + test("상품에 좋아요를 눌러야 한다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + + const mockUpdatedProduct = { + id: "test-product-id", + name: "상품 1", + description: "상품입니다.", + price: 100, + favoriteCount: 10, + createdAt: new Date(), + updatedAt: new Date(), + writer: "테스트 유저", + tags: [], + userId: 1, + images: [ + { + id: "image-id", + imagePath: "image1.jpg", + productId: null, + createdAt: new Date(), + updatedAt: new Date(), + articleId: null, + }, + ], + }; + + (productService.likeProduct as jest.MockedFunction).mockResolvedValue( + mockUpdatedProduct + ); + + await productController.likeProduct(req, res, next); + + expect(productService.likeProduct).toHaveBeenCalledWith("1", req.userId); + expect(res.send).toHaveBeenCalledWith(mockUpdatedProduct); + }); + + test("이미 좋아요가 된 게시글에 좋아요를 누를 경우 에러를 반환한다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + + (productService.likeProduct as jest.MockedFunction).mockRejectedValue( + new AppError("이미 좋아요 처리된 게시글입니다.", 409) + ); + + await productController.likeProduct(req, res, next); + + expect(res.status).toHaveBeenCalledWith(409); + expect(res.json).toHaveBeenCalledWith({ message: "이미 좋아요 처리된 게시글입니다." }); + }); + }); + + describe("unlikeProduct", () => { + test("상품의 좋아요를 취소해야 한다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + + const mockUpdatedProduct = { + id: "test-product-id", + name: "판다 1", + description: "상품입니다.", + price: 100, + favoriteCount: 5, + createdAt: new Date(), + updatedAt: new Date(), + writer: "테스트 유저", + tags: [], + userId: 1, + images: [ + { + id: "image-id", + imagePath: "image1.jpg", + productId: null, + createdAt: new Date(), + updatedAt: new Date(), + articleId: null, + }, + ], + }; + + (productService.unlikeProduct as jest.MockedFunction).mockResolvedValue( + mockUpdatedProduct + ); + + await productController.unlikeProduct(req, res, next); + + expect(productService.unlikeProduct).toHaveBeenCalledWith("1", req.userId); + expect(res.send).toHaveBeenCalledWith(mockUpdatedProduct); + }); + + test("아직 좋아요 처리되지 않은 상품의 좋아요를 취소하려고 할 경우 에러를 반환한다", async () => { + const { req, res, next } = setup(); + req.params = { id: "1" }; + + (productService.unlikeProduct as jest.MockedFunction).mockRejectedValue( + new AppError("아직 좋아요 처리되지 않은 게시글입니다.", 409) + ); + + await productController.unlikeProduct(req, res, next); + + expect(res.status).toHaveBeenCalledWith(409); + expect(res.json).toHaveBeenCalledWith({ message: "아직 좋아요 처리되지 않은 게시글입니다." }); + }); + }); +}); diff --git a/src/utils/asyncHandler.ts b/src/utils/asyncHandler.ts index 6387fac..d25d0a5 100644 --- a/src/utils/asyncHandler.ts +++ b/src/utils/asyncHandler.ts @@ -1,6 +1,6 @@ import { Prisma } from "@prisma/client"; import { NextFunction, Request, RequestHandler, Response } from "express"; -import { StructError } from "superstruct"; +import AppError from "./errors"; type AsyncHandler = (req: T, res: Response, next: NextFunction) => Promise; @@ -9,12 +9,8 @@ const asyncHandler = (handler: AsyncHandler): RequestHandl try { return await handler(req as T, res, next); } catch (e) { - if (e instanceof StructError) { - const errors = e.failures().map((failure) => ({ - path: failure.path.join("."), - message: failure.message, - })); - res.status(400).json({ message: "유효성 검사 오류입니다.", errors }); + if (e instanceof AppError) { + res.status(e.statusCode).json({ message: e.message }); } else if (e instanceof Prisma.PrismaClientValidationError) { res.status(400).json({ message: e.message }); } else if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") { From b52de6cefb9335ee54d16c9649770fc0f35a3c66 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 6 Jun 2024 13:10:43 +0900 Subject: [PATCH 51/60] =?UTF-8?q?[#M12]=20feat=20:=20comment=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=A1=9C=EC=A7=81=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/commentController.test.ts | 211 +++++++++++++++++++++++ src/test/commentService.test.ts | 266 +++++++++++++++++++++++++++++ 2 files changed, 477 insertions(+) create mode 100644 src/test/commentController.test.ts create mode 100644 src/test/commentService.test.ts diff --git a/src/test/commentController.test.ts b/src/test/commentController.test.ts new file mode 100644 index 0000000..69b1925 --- /dev/null +++ b/src/test/commentController.test.ts @@ -0,0 +1,211 @@ +import { beforeEach, describe, expect, jest, test } from "@jest/globals"; +import { NextFunction, Request, Response } from "express"; +import { assert } from "superstruct"; +import * as commentController from "../controllers/commentController"; +import * as commentService from "../services/commentService"; +import { CreateComment, PatchComment } from "../structs"; +import AppError from "../utils/errors"; + +jest.mock("../services/commentService"); +jest.mock("superstruct", () => { + const originalModule = jest.requireActual("superstruct"); + return { + ...originalModule, + assert: jest.fn(), + }; +}); + +const setup = () => { + const req = { + body: {}, + params: {}, + query: {}, + userId: 1, + } as unknown as Request<{ id: string; commentId: string }> & { userId: number }; + + const res = { + status: jest.fn().mockReturnThis(), + json: jest.fn(), + send: jest.fn(), + sendStatus: jest.fn(), + } as unknown as Response; + + const next = jest.fn() as NextFunction; + + return { req, res, next }; +}; + +describe("댓글 컨트롤러", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe("getCommentsByProductId", () => { + test("상품의 댓글을 반환해야 한다", async () => { + const { req, res, next } = setup(); + req.params.id = "1"; + const mockComments = [ + { + id: "1", + content: "멋진 상품!", + writer: "테스트 유저", + createdAt: new Date(), + updatedAt: new Date(), + productId: "1", + articleId: null, + userId: 1, + }, + ]; + ( + commentService.getCommentsByProductId as jest.MockedFunction + ).mockResolvedValue(mockComments); + + await commentController.getCommentsByProductId(req, res, next); + + expect(res.send).toHaveBeenCalledWith(mockComments); + }); + }); + + describe("getCommentsByArticleId", () => { + test("게시글의 댓글을 반환해야 한다", async () => { + const { req, res, next } = setup(); + req.params.id = "1"; + const mockComments = [ + { + id: "1", + content: "멋진 게시글!", + writer: "테스트 유저", + createdAt: new Date(), + updatedAt: new Date(), + productId: null, + articleId: "1", + userId: 1, + }, + ]; + ( + commentService.getCommentsByArticleId as jest.MockedFunction + ).mockResolvedValue(mockComments); + + await commentController.getCommentsByArticleId(req, res, next); + + expect(res.send).toHaveBeenCalledWith(mockComments); + }); + }); + + describe("createComment", () => { + test("댓글을 생성해야 한다", async () => { + const { req, res, next } = setup(); + req.body = { content: "좋아요!" }; + const mockComment = { + id: "1", + content: "좋아요!", + writer: "테스트 유저", + createdAt: new Date(), + updatedAt: new Date(), + productId: null, + articleId: "1", + userId: 1, + }; + (commentService.createComment as jest.MockedFunction).mockResolvedValue( + mockComment + ); + + await commentController.createComment(req, res, next); + + expect(assert).toHaveBeenCalledWith(req.body, CreateComment); + expect(commentService.createComment).toHaveBeenCalledWith({ ...req.body, userId: req.userId }); + expect(res.status).toHaveBeenCalledWith(201); + expect(res.send).toHaveBeenCalledWith(mockComment); + }); + }); + + describe("updateComment", () => { + test("댓글을 업데이트해야 한다", async () => { + const { req, res, next } = setup(); + req.params.commentId = "1"; + req.body = { content: "업데이트된 댓글" }; + + const mockUpdatedComment = { + id: "1", + content: "업데이트된 댓글", + writer: "테스트 유저", + createdAt: new Date(), + updatedAt: new Date(), + productId: null, + articleId: "1", + userId: 1, + }; + (commentService.updateComment as jest.MockedFunction).mockResolvedValue( + mockUpdatedComment + ); + + await commentController.updateComment(req, res, next); + + expect(assert).toHaveBeenCalledWith(req.body, PatchComment); + expect(commentService.updateComment).toHaveBeenCalledWith("1", req.userId, "업데이트된 댓글"); + expect(res.send).toHaveBeenCalledWith(mockUpdatedComment); + }); + + test("댓글 수정 시 commentId가 없으면 400 에러를 반환해야 한다", async () => { + const { req, res, next } = setup(); + req.params.commentId = ""; + + await commentController.updateComment(req, res, next); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith({ message: "존재하지 않는 댓글입니다." }); + }); + + test("댓글 수정 시 content가 없으면 400 에러를 반환해야 한다", async () => { + const { req, res, next } = setup(); + req.params.commentId = "1"; + req.body.content = ""; + + await commentController.updateComment(req, res, next); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith({ message: "댓글 내용은 필수값입니다." }); + }); + + test("댓글 수정 시 권한이 없으면 예외를 발생시켜야 한다", async () => { + const { req, res, next } = setup(); + req.params.commentId = "1"; + req.body = { content: "업데이트된 댓글" }; + + (commentService.updateComment as jest.MockedFunction).mockRejectedValue( + new AppError("댓글을 수정할 권한이 없습니다.", 403) + ); + + await commentController.updateComment(req, res, next); + + expect(res.status).toHaveBeenCalledWith(403); + expect(res.json).toHaveBeenCalledWith({ message: "댓글을 수정할 권한이 없습니다." }); + }); + }); + + describe("deleteComment", () => { + test("댓글을 삭제해야 한다", async () => { + const { req, res, next } = setup(); + req.params.commentId = "1"; + + await commentController.deleteComment(req, res, next); + + expect(commentService.deleteComment).toHaveBeenCalledWith("1", req.userId); + expect(res.sendStatus).toHaveBeenCalledWith(204); + }); + + test("댓글 삭제 시 권한이 없으면 예외를 발생시켜야 한다", async () => { + const { req, res, next } = setup(); + req.params.commentId = "1"; + + (commentService.deleteComment as jest.MockedFunction).mockRejectedValue( + new AppError("댓글을 삭제할 권한이 없습니다.", 403) + ); + + await commentController.deleteComment(req, res, next); + + expect(res.status).toHaveBeenCalledWith(403); + expect(res.json).toHaveBeenCalledWith({ message: "댓글을 삭제할 권한이 없습니다." }); + }); + }); +}); diff --git a/src/test/commentService.test.ts b/src/test/commentService.test.ts new file mode 100644 index 0000000..38aaa6f --- /dev/null +++ b/src/test/commentService.test.ts @@ -0,0 +1,266 @@ +import { beforeEach, describe, expect, jest, test } from "@jest/globals"; +import { Comment } from "@prisma/client"; +import prisma from "../client"; +import * as commentService from "../services/commentService"; + +jest.mock("../client", () => ({ + __esModule: true, + default: { + comment: { + findMany: jest.fn(), + findUnique: jest.fn(), + create: jest.fn(), + update: jest.fn(), + delete: jest.fn(), + }, + user: { + findUnique: jest.fn(), + }, + $transaction: jest.fn(), + }, +})); + +const mockUser = { + id: 1, + googleId: null, + email: "test@example.com", + name: "테스트 유저", + nickname: "testuser", + image: null, + password: null, + createdAt: new Date(), + updatedAt: new Date(), +}; + +const mockComments: Comment[] = [ + { + id: "1", + content: "좋은 게시글!", + createdAt: new Date(), + updatedAt: new Date(), + writer: "사용자1", + productId: "1", + articleId: "1", + userId: 1, + }, +]; + +describe("Comment Service", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe("getCommentsByProductId", () => { + test("상품 ID로 댓글을 가져와야 한다", async () => { + (prisma.comment.findMany as jest.MockedFunction).mockResolvedValue(mockComments); + + const comments = await commentService.getCommentsByProductId("1"); + + expect(prisma.comment.findMany).toHaveBeenCalledWith({ + take: 10, + orderBy: { createdAt: "desc" }, + where: { productId: "1" }, + select: { id: true, content: true, createdAt: true, writer: true }, + cursor: undefined, + skip: undefined, + }); + expect(comments).toEqual(mockComments); + }); + }); + + describe("getCommentsByArticleId", () => { + test("게시글 ID로 댓글을 가져와야 한다", async () => { + (prisma.comment.findMany as jest.MockedFunction).mockResolvedValue(mockComments); + + const comments = await commentService.getCommentsByArticleId("1"); + + expect(prisma.comment.findMany).toHaveBeenCalledWith({ + take: 10, + orderBy: { createdAt: "desc" }, + where: { articleId: "1" }, + select: { id: true, content: true, createdAt: true, writer: true }, + cursor: undefined, + skip: undefined, + }); + expect(comments).toEqual(mockComments); + }); + }); + + describe("createComment", () => { + test("댓글을 생성해야 한다", async () => { + const mockComment: Comment = { + id: "1", + content: "새로운 댓글", + writer: "사용자1", + createdAt: new Date(), + updatedAt: new Date(), + productId: "1", + articleId: null, + userId: 1, + }; + + (prisma.user.findUnique as jest.MockedFunction).mockResolvedValue(mockUser); + (prisma.comment.create as jest.MockedFunction).mockResolvedValue(mockComment); + + const commentData = { + content: "새로운 댓글", + userId: 1, + productId: "1", + }; + + const comment = await commentService.createComment(commentData); + + expect(prisma.user.findUnique).toHaveBeenCalledWith({ + where: { id: commentData.userId }, + select: { name: true }, + }); + expect(prisma.comment.create).toHaveBeenCalledWith({ + data: { ...commentData, writer: mockUser.name }, + }); + expect(comment).toEqual(mockComment); + }); + + test("존재하지 않는 사용자는 에러를 발생시켜야 한다", async () => { + (prisma.user.findUnique as jest.MockedFunction).mockResolvedValue(null); + + const commentData = { + content: "새로운 댓글", + userId: 1, + productId: "1", + }; + + await expect(commentService.createComment(commentData)).rejects.toThrow("User not found"); + + expect(prisma.user.findUnique).toHaveBeenCalledWith({ + where: { id: commentData.userId }, + select: { name: true }, + }); + expect(prisma.comment.create).not.toHaveBeenCalled(); + }); + }); + + describe("updateComment", () => { + test("댓글을 업데이트해야 한다", async () => { + const mockComment: Comment = { + id: "1", + content: "기존 댓글", + createdAt: new Date(), + updatedAt: new Date(), + writer: "사용자1", + productId: "1", + articleId: null, + userId: 1, + }; + + const updatedComment: Comment = { + ...mockComment, + content: "업데이트된 댓글", + }; + + (prisma.comment.findUnique as jest.MockedFunction).mockResolvedValue( + mockComment + ); + (prisma.comment.update as jest.MockedFunction).mockResolvedValue(updatedComment); + + const result = await commentService.updateComment("1", 1, "업데이트된 댓글"); + + expect(prisma.comment.findUnique).toHaveBeenCalledWith({ where: { id: "1" } }); + expect(prisma.comment.update).toHaveBeenCalledWith({ + where: { id: "1" }, + data: { content: "업데이트된 댓글" }, + }); + expect(result).toEqual(updatedComment); + }); + + test("존재하지 않는 댓글은 에러를 발생시켜야 한다", async () => { + (prisma.comment.findUnique as jest.MockedFunction).mockResolvedValue(null); + + await expect(commentService.updateComment("1", 1, "업데이트된 댓글")).rejects.toThrow( + "존재하지 않는 댓글입니다." + ); + + expect(prisma.comment.findUnique).toHaveBeenCalledWith({ where: { id: "1" } }); + expect(prisma.comment.update).not.toHaveBeenCalled(); + }); + + test("다른 사용자의 댓글은 에러를 발생시켜야 한다", async () => { + const mockComment: Comment = { + id: "1", + content: "기존 댓글", + createdAt: new Date(), + updatedAt: new Date(), + writer: "사용자1", + productId: "1", + articleId: null, + userId: 2, + }; + + (prisma.comment.findUnique as jest.MockedFunction).mockResolvedValue( + mockComment + ); + + await expect(commentService.updateComment("1", 1, "업데이트된 댓글")).rejects.toThrow( + "이 댓글을 수정할 권한이 없습니다." + ); + + expect(prisma.comment.findUnique).toHaveBeenCalledWith({ where: { id: "1" } }); + expect(prisma.comment.update).not.toHaveBeenCalled(); + }); + }); + + describe("deleteComment", () => { + test("댓글을 삭제해야 한다", async () => { + const mockComment: Comment = { + id: "1", + content: "기존 댓글", + createdAt: new Date(), + updatedAt: new Date(), + writer: "사용자1", + productId: "1", + articleId: null, + userId: 1, + }; + + (prisma.comment.findUnique as jest.MockedFunction).mockResolvedValue( + mockComment + ); + (prisma.comment.delete as jest.MockedFunction).mockResolvedValue(mockComment); + + await commentService.deleteComment("1", 1); + + expect(prisma.comment.findUnique).toHaveBeenCalledWith({ where: { id: "1" } }); + expect(prisma.comment.delete).toHaveBeenCalledWith({ where: { id: "1" } }); + }); + + test("존재하지 않는 댓글은 에러를 발생시켜야 한다", async () => { + (prisma.comment.findUnique as jest.MockedFunction).mockResolvedValue(null); + + await expect(commentService.deleteComment("1", 1)).rejects.toThrow("존재하지 않는 댓글입니다."); + + expect(prisma.comment.findUnique).toHaveBeenCalledWith({ where: { id: "1" } }); + expect(prisma.comment.delete).not.toHaveBeenCalled(); + }); + + test("다른 사용자의 댓글은 에러를 발생시켜야 한다", async () => { + const mockComment: Comment = { + id: "1", + content: "기존 댓글", + createdAt: new Date(), + updatedAt: new Date(), + writer: "사용자1", + productId: "1", + articleId: null, + userId: 2, + }; + + (prisma.comment.findUnique as jest.MockedFunction).mockResolvedValue( + mockComment + ); + + await expect(commentService.deleteComment("1", 1)).rejects.toThrow("이 댓글을 삭제할 권한이 없습니다."); + + expect(prisma.comment.findUnique).toHaveBeenCalledWith({ where: { id: "1" } }); + expect(prisma.comment.delete).not.toHaveBeenCalled(); + }); + }); +}); From f0f4dc7f9885f86d0af6871ee37effb361005bc6 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 6 Jun 2024 14:07:38 +0900 Subject: [PATCH 52/60] =?UTF-8?q?[#M12]=20feat=20:=20image,=20asyncHandler?= =?UTF-8?q?=20=EA=B4=80=EB=A0=A8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 134 +++++++++++++++++++++++++++++ package.json | 2 + src/controllers/imageController.ts | 12 +-- src/test/asyncHandler.test.ts | 77 +++++++++++++++++ src/test/imageController.test.ts | 85 ++++++++++++++++++ src/test/imageService.test.ts | 47 ++++++++++ yarn.lock | 110 ++++++++++++++++++++++- 7 files changed, 455 insertions(+), 12 deletions(-) create mode 100644 src/test/asyncHandler.test.ts create mode 100644 src/test/imageController.test.ts create mode 100644 src/test/imageService.test.ts diff --git a/package-lock.json b/package-lock.json index 9596111..d8898cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,8 @@ "@aws-sdk/s3-request-presigner": "^3.591.0", "@prisma/client": "^5.4.2", "aws-sdk": "^2.1634.0", + "aws-sdk-client-mock": "^4.0.1", + "aws-sdk-client-mock-jest": "^4.0.1", "bcrypt": "^5.1.1", "dotenv": "^16.3.1", "express": "^4.18.2", @@ -3741,6 +3743,29 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@sinonjs/samsam": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", + "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", + "dependencies": { + "@sinonjs/commons": "^2.0.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==" + }, "node_modules/@smithy/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.0.0.tgz", @@ -4690,6 +4715,19 @@ "@types/send": "*" } }, + "node_modules/@types/sinon": { + "version": "10.0.20", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.20.tgz", + "integrity": "sha512-2APKKruFNCAZgx3daAyACGzWuJ028VVCUDk6o2rw/Z4PXT0ogwdV4KUegW0MwVs0Zu59auPXbbuBJHF12Sx1Eg==", + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==" + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -4929,6 +4967,28 @@ "node": ">= 10.0.0" } }, + "node_modules/aws-sdk-client-mock": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aws-sdk-client-mock/-/aws-sdk-client-mock-4.0.1.tgz", + "integrity": "sha512-yD2mmgy73Xce097G5hIpr1k7j50qzvJ49/+6osGZiCyk4m6cwhb+2x7kKFY1gEMwTzaS8+m8fXv9SB29SkRYyQ==", + "dependencies": { + "@types/sinon": "^10.0.10", + "sinon": "^16.1.3", + "tslib": "^2.1.0" + } + }, + "node_modules/aws-sdk-client-mock-jest": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aws-sdk-client-mock-jest/-/aws-sdk-client-mock-jest-4.0.1.tgz", + "integrity": "sha512-PilgESg/u2sJvHg0+4C8/ty7w2+/pMhBYpdfPlCysnsjNfFk6a7eW7fwfIWoL93BCvcEblPdLyVL/vYTRCNFYA==", + "dependencies": { + "expect": ">28.1.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "aws-sdk-client-mock": "4.0.1" + } + }, "node_modules/aws-sdk/node_modules/uuid": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", @@ -7445,6 +7505,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/just-extend": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==" + }, "node_modules/jwa": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", @@ -7843,6 +7908,31 @@ "node": ">= 0.6" } }, + "node_modules/nise": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", + "integrity": "sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==", + "dependencies": { + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^11.2.2", + "@sinonjs/text-encoding": "^0.7.2", + "just-extend": "^6.2.0", + "path-to-regexp": "^6.2.1" + } + }, + "node_modules/nise/node_modules/@sinonjs/fake-timers": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", + "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/nise/node_modules/path-to-regexp": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==" + }, "node_modules/node-addon-api": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", @@ -8815,6 +8905,50 @@ "node": ">=10" } }, + "node_modules/sinon": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-16.1.3.tgz", + "integrity": "sha512-mjnWWeyxcAf9nC0bXcPmiDut+oE8HYridTNzBbF98AYVLmWwGRp2ISEpyhYflG1ifILT+eNn3BmKUJPxjXUPlA==", + "dependencies": { + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^10.3.0", + "@sinonjs/samsam": "^8.0.0", + "diff": "^5.1.0", + "nise": "^5.1.4", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/sinon/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/sinon/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", diff --git a/package.json b/package.json index d521040..624746d 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,8 @@ "@aws-sdk/s3-request-presigner": "^3.591.0", "@prisma/client": "^5.4.2", "aws-sdk": "^2.1634.0", + "aws-sdk-client-mock": "^4.0.1", + "aws-sdk-client-mock-jest": "^4.0.1", "bcrypt": "^5.1.1", "dotenv": "^16.3.1", "express": "^4.18.2", diff --git a/src/controllers/imageController.ts b/src/controllers/imageController.ts index 7609305..b0df16d 100644 --- a/src/controllers/imageController.ts +++ b/src/controllers/imageController.ts @@ -1,12 +1,8 @@ -import { Request, Response } from "express"; +import { NextFunction, Request, Response } from "express"; import * as imageService from "../services/imageService"; import asyncHandler from "../utils/asyncHandler"; -export const getPresignedUrl = asyncHandler(async (req: Request, res: Response) => { - try { - const presignedUrl = await imageService.generatePresignedUrl(req); - res.status(200).json({ url: presignedUrl }); - } catch (error) { - res.status(400).send((error as Error).message); - } +export const getPresignedUrl = asyncHandler(async (req: Request, res: Response, next: NextFunction) => { + const presignedUrl = await imageService.generatePresignedUrl(req); + res.status(200).json({ url: presignedUrl }); }); diff --git a/src/test/asyncHandler.test.ts b/src/test/asyncHandler.test.ts new file mode 100644 index 0000000..d0d419f --- /dev/null +++ b/src/test/asyncHandler.test.ts @@ -0,0 +1,77 @@ +import { beforeEach, describe, expect, jest, test } from "@jest/globals"; +import { Prisma } from "@prisma/client"; +import { NextFunction, Request, Response } from "express"; +import asyncHandler from "../utils/asyncHandler"; +import AppError from "../utils/errors"; + +const mockRequest = {} as Request; +const mockResponse = { + status: jest.fn().mockReturnThis(), + json: jest.fn(), +} as unknown as Response; +const mockNext = jest.fn() as NextFunction; + +describe("asyncHandler", () => { + beforeEach(() => { + jest.clearAllMocks(); + console.error = jest.fn(); + }); + + test("AppError를 처리하고 올바른 응답을 반환해야 한다", async () => { + const handler = jest.fn(async () => { + throw new AppError("Test AppError", 400); + }); + const wrappedHandler = asyncHandler(handler); + + await wrappedHandler(mockRequest, mockResponse, mockNext); + + expect(mockResponse.status).toHaveBeenCalledWith(400); + expect(mockResponse.json).toHaveBeenCalledWith({ message: "Test AppError" }); + }); + + test("PrismaClientValidationError를 처리하고 올바른 응답을 반환해야 한다", async () => { + const validationError = new Prisma.PrismaClientValidationError("Test PrismaClientValidationError", { + clientVersion: "1.2.3", + }); + + const handler = jest.fn(async () => { + throw validationError; + }); + const wrappedHandler = asyncHandler(handler); + + await wrappedHandler(mockRequest, mockResponse, mockNext); + + expect(mockResponse.status).toHaveBeenCalledWith(400); + expect(mockResponse.json).toHaveBeenCalledWith({ message: "Test PrismaClientValidationError" }); + }); + + test("PrismaClientKnownRequestError를 처리하고 올바른 응답을 반환해야 한다", async () => { + const knownRequestError = new Prisma.PrismaClientKnownRequestError("Test PrismaClientKnownRequestError", { + code: "P2025", + clientVersion: "1.2.3", + }); + + const handler = jest.fn(async () => { + throw knownRequestError; + }); + const wrappedHandler = asyncHandler(handler); + + await wrappedHandler(mockRequest, mockResponse, mockNext); + + expect(mockResponse.status).toHaveBeenCalledWith(404); + expect(mockResponse.json).toHaveBeenCalledWith({ message: "존재하지 않는 게시글입니다." }); + }); + + test("알 수 없는 에러를 처리하고 올바른 응답을 반환해야 한다", async () => { + const handler = jest.fn(async () => { + throw new Error("Test Error"); + }); + const wrappedHandler = asyncHandler(handler); + + await wrappedHandler(mockRequest, mockResponse, mockNext); + + expect(console.error).toHaveBeenCalledWith(new Error("Test Error")); + expect(mockResponse.status).toHaveBeenCalledWith(500); + expect(mockResponse.json).toHaveBeenCalledWith({ message: "서버 에러입니다." }); + }); +}); diff --git a/src/test/imageController.test.ts b/src/test/imageController.test.ts new file mode 100644 index 0000000..8f4ca35 --- /dev/null +++ b/src/test/imageController.test.ts @@ -0,0 +1,85 @@ +import { afterEach, beforeEach, describe, expect, jest, test } from "@jest/globals"; +import { NextFunction, Request, Response } from "express"; +import { getPresignedUrl } from "../controllers/imageController"; +import * as imageService from "../services/imageService"; +import AppError from "../utils/errors"; + +jest.mock("../services/imageService"); + +const setup = () => { + const req = { + body: { + fileName: "test.png", + fileType: "image/png", + }, + params: {}, + query: {}, + userId: 1, + } as unknown as Request<{ id: string }> & { userId: number }; + + const res = { + status: jest.fn().mockReturnThis(), + json: jest.fn(), + send: jest.fn(), + sendStatus: jest.fn(), + } as unknown as Response; + + const next = jest.fn() as NextFunction; + + return { req, res, next }; +}; + +describe("getPresignedUrl", () => { + let originalConsoleError: any; + + beforeEach(() => { + jest.clearAllMocks(); + originalConsoleError = console.error; + console.error = jest.fn(); // suppress console.error during tests + }); + + afterEach(() => { + console.error = originalConsoleError; + }); + + test("성공적으로 presigned URL을 반환해야 한다", async () => { + const { req, res, next } = setup(); + + const mockUrl = "https://example.com/presigned-url"; + ( + imageService.generatePresignedUrl as jest.MockedFunction + ).mockResolvedValue(mockUrl); + + await getPresignedUrl(req, res, next); + + expect(res.status).toHaveBeenCalledWith(200); + expect(res.json).toHaveBeenCalledWith({ url: mockUrl }); + expect(next).not.toHaveBeenCalled(); + }); + + test("fileName 또는 fileType이 없을 경우 AppError를 반환해야 한다", async () => { + const { req, res, next } = setup(); + req.body = {}; + + ( + imageService.generatePresignedUrl as jest.MockedFunction + ).mockRejectedValue(new AppError("이미지 파일을 선택해주세요.", 400)); + + await getPresignedUrl(req, res, next); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith({ message: "이미지 파일을 선택해주세요." }); + }); + + test("service에서 발생한 다른 에러를 반환해야 한다", async () => { + const { req, res, next } = setup(); + ( + imageService.generatePresignedUrl as jest.MockedFunction + ).mockRejectedValue(new AppError("서버 에러입니다.", 500)); + + await getPresignedUrl(req, res, next); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ message: "서버 에러입니다." }); + }); +}); diff --git a/src/test/imageService.test.ts b/src/test/imageService.test.ts new file mode 100644 index 0000000..4846304 --- /dev/null +++ b/src/test/imageService.test.ts @@ -0,0 +1,47 @@ +import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3"; +import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; +import { beforeEach, describe, expect, jest, test } from "@jest/globals"; +import { Request } from "express"; +import { generatePresignedUrl } from "../services/imageService"; + +jest.mock("@aws-sdk/s3-request-presigner"); +jest.mock("@aws-sdk/client-s3"); + +describe("generatePresignedUrl", () => { + const mockRequest = { + body: { + fileName: "test.png", + fileType: "image/png", + }, + } as Request; + + beforeEach(() => { + jest.clearAllMocks(); + process.env.AWS_S3_BUCKET_NAME = "test-bucket"; + process.env.AWS_ACCESS_KEY_ID = "test-access-key"; + process.env.AWS_SECRET_ACCESS_KEY = "test-secret-key"; + }); + + test("presigned URL을 생성한다", async () => { + const mockUrl: string = "https://example.com/presigned-url"; + (getSignedUrl as jest.MockedFunction).mockResolvedValue(mockUrl); + + const result = await generatePresignedUrl(mockRequest); + + expect(result).toBe(mockUrl); + expect(PutObjectCommand).toHaveBeenCalledWith({ + Bucket: "test-bucket", + Key: expect.stringContaining("images/"), + ContentType: "image/png", + }); + expect(getSignedUrl).toHaveBeenCalledWith(expect.any(S3Client), expect.any(PutObjectCommand), { expiresIn: 3600 }); + }); + + test("fileName 또는 fileType이 없으면 에러를 발생시킨다", async () => { + const invalidRequest = { + body: {}, + } as Request; + + await expect(generatePresignedUrl(invalidRequest)).rejects.toThrow("이미지 파일을 선택해주세요."); + }); +}); diff --git a/yarn.lock b/yarn.lock index 4235fde..58c1ed4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2025,6 +2025,13 @@ resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== +"@sinonjs/commons@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz" + integrity sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg== + dependencies: + type-detect "4.0.8" + "@sinonjs/commons@^3.0.0": version "3.0.1" resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz" @@ -2032,13 +2039,34 @@ dependencies: type-detect "4.0.8" -"@sinonjs/fake-timers@^10.0.2": +"@sinonjs/fake-timers@^10.0.2", "@sinonjs/fake-timers@^10.3.0": version "10.3.0" resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz" integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== dependencies: "@sinonjs/commons" "^3.0.0" +"@sinonjs/fake-timers@^11.2.2": + version "11.2.2" + resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz" + integrity sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw== + dependencies: + "@sinonjs/commons" "^3.0.0" + +"@sinonjs/samsam@^8.0.0": + version "8.0.0" + resolved "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz" + integrity sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew== + dependencies: + "@sinonjs/commons" "^2.0.0" + lodash.get "^4.4.2" + type-detect "^4.0.8" + +"@sinonjs/text-encoding@^0.7.2": + version "0.7.2" + resolved "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz" + integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ== + "@smithy/abort-controller@^3.0.0": version "3.0.0" resolved "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.0.0.tgz" @@ -2761,6 +2789,18 @@ "@types/node" "*" "@types/send" "*" +"@types/sinon@^10.0.10": + version "10.0.20" + resolved "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.20.tgz" + integrity sha512-2APKKruFNCAZgx3daAyACGzWuJ028VVCUDk6o2rw/Z4PXT0ogwdV4KUegW0MwVs0Zu59auPXbbuBJHF12Sx1Eg== + dependencies: + "@types/sinonjs__fake-timers" "*" + +"@types/sinonjs__fake-timers@*": + version "8.1.5" + resolved "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz" + integrity sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ== + "@types/stack-utils@^2.0.0": version "2.0.3" resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz" @@ -2907,6 +2947,23 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" +aws-sdk-client-mock-jest@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/aws-sdk-client-mock-jest/-/aws-sdk-client-mock-jest-4.0.1.tgz" + integrity sha512-PilgESg/u2sJvHg0+4C8/ty7w2+/pMhBYpdfPlCysnsjNfFk6a7eW7fwfIWoL93BCvcEblPdLyVL/vYTRCNFYA== + dependencies: + expect ">28.1.3" + tslib "^2.1.0" + +aws-sdk-client-mock@^4.0.1, aws-sdk-client-mock@4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/aws-sdk-client-mock/-/aws-sdk-client-mock-4.0.1.tgz" + integrity sha512-yD2mmgy73Xce097G5hIpr1k7j50qzvJ49/+6osGZiCyk4m6cwhb+2x7kKFY1gEMwTzaS8+m8fXv9SB29SkRYyQ== + dependencies: + "@types/sinon" "^10.0.10" + sinon "^16.1.3" + tslib "^2.1.0" + aws-sdk@*, aws-sdk@^2.1634.0: version "2.1634.0" resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1634.0.tgz" @@ -3489,6 +3546,11 @@ diff@^4.0.1: resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diff@^5.1.0: + version "5.2.0" + resolved "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + doctrine@3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" @@ -3646,7 +3708,7 @@ exit@^0.1.2: resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== -expect@^29.7.0: +expect@^29.7.0, expect@>28.1.3: version "29.7.0" resolved "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz" integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== @@ -4605,6 +4667,11 @@ jsonwebtoken@^9.0.2: ms "^2.1.1" semver "^7.5.4" +just-extend@^6.2.0: + version "6.2.0" + resolved "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz" + integrity sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw== + jwa@^1.4.1: version "1.4.1" resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz" @@ -4907,6 +4974,17 @@ negotiator@0.6.3: resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +nise@^5.1.4: + version "5.1.9" + resolved "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz" + integrity sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww== + dependencies: + "@sinonjs/commons" "^3.0.0" + "@sinonjs/fake-timers" "^11.2.2" + "@sinonjs/text-encoding" "^0.7.2" + just-extend "^6.2.0" + path-to-regexp "^6.2.1" + node-addon-api@^5.0.0: version "5.1.0" resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz" @@ -5138,6 +5216,11 @@ path-parse@^1.0.7: resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-to-regexp@^6.2.1: + version "6.2.2" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz" + integrity sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw== + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" @@ -5535,6 +5618,18 @@ simple-update-notifier@^2.0.0: dependencies: semver "^7.5.3" +sinon@^16.1.3: + version "16.1.3" + resolved "https://registry.npmjs.org/sinon/-/sinon-16.1.3.tgz" + integrity sha512-mjnWWeyxcAf9nC0bXcPmiDut+oE8HYridTNzBbF98AYVLmWwGRp2ISEpyhYflG1ifILT+eNn3BmKUJPxjXUPlA== + dependencies: + "@sinonjs/commons" "^3.0.0" + "@sinonjs/fake-timers" "^10.3.0" + "@sinonjs/samsam" "^8.0.0" + diff "^5.1.0" + nise "^5.1.4" + supports-color "^7.2.0" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" @@ -5658,6 +5753,13 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^7.2.0: + version "7.2.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + supports-color@^8.0.0: version "8.1.1" resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" @@ -5797,7 +5899,7 @@ tslib@^1.11.1: resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.3.1, tslib@^2.6.2: +tslib@^2.1.0, tslib@^2.3.1, tslib@^2.6.2: version "2.6.3" resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz" integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== @@ -5812,7 +5914,7 @@ tsx@^4.11.0: optionalDependencies: fsevents "~2.3.3" -type-detect@4.0.8: +type-detect@^4.0.8, type-detect@4.0.8: version "4.0.8" resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== From e0e6562b71eebcb5f7649485674c74c41ca1f207 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Thu, 6 Jun 2024 14:37:23 +0900 Subject: [PATCH 53/60] =?UTF-8?q?[#M12]=20fix=20:=20article=EA=B3=BC=20pro?= =?UTF-8?q?duct=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C=20images=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=EA=B0=80=20=EB=AC=B8=EC=9E=90=EC=97=B4=20=EB=B0=B0?= =?UTF-8?q?=EC=97=B4=EB=A1=9C=20=EB=B0=98=ED=99=98=EB=90=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 테스트 코드 수정 - Swagger 문서에서 images 필드 타입 수정 --- src/middlewares/authenticate.ts | 2 +- src/routes/articleRoutes.ts | 100 ++++++++------ src/routes/productRoutes.ts | 213 +++++++++++++++++++++++------ src/services/articleService.ts | 55 +++++++- src/services/productService.ts | 58 ++++++-- src/test/articleController.test.ts | 11 +- src/test/articleService.test.ts | 49 +++++-- src/test/imageController.test.ts | 2 +- src/test/productController.test.ts | 77 +---------- src/test/productService.test.ts | 60 ++++++-- src/test/tokens.test.ts | 2 - 11 files changed, 422 insertions(+), 207 deletions(-) diff --git a/src/middlewares/authenticate.ts b/src/middlewares/authenticate.ts index 55eb0a6..23e6ac0 100644 --- a/src/middlewares/authenticate.ts +++ b/src/middlewares/authenticate.ts @@ -17,7 +17,7 @@ const authenticate: RequestHandler = (req: Request, res: Response, next: NextFun try { const decoded = jwt.verify(token, JWT_SECRET) as { userId: number }; - req.user = { _id: decoded.userId }; // 기존 _id를 userId로 설정 + req.user = { _id: decoded.userId }; next(); } catch (error) { res.status(401).json({ message: "올바르지 않은 토큰입니다." }); diff --git a/src/routes/articleRoutes.ts b/src/routes/articleRoutes.ts index 341bc90..35fa3f9 100644 --- a/src/routes/articleRoutes.ts +++ b/src/routes/articleRoutes.ts @@ -3,6 +3,7 @@ import * as articleController from "../controllers/articleController"; import * as commentController from "../controllers/commentController"; import authenticate from "../middlewares/authenticate"; const router = express.Router(); + /** * @swagger * tags: @@ -64,9 +65,11 @@ const router = express.Router(); * content: * type: string * example: "게시글 내용" - * imageUrl: - * type: string - * example: "http://example.com/image.jpg" + * images: + * type: array + * items: + * type: string + * example: "http://example.com/image.jpg" * createdAt: * type: string * format: date-time @@ -91,9 +94,11 @@ const router = express.Router(); * content: * type: string * example: "인기 게시글 내용" - * imageUrl: - * type: string - * example: "http://example.com/image.jpg" + * images: + * type: array + * items: + * type: string + * example: "http://example.com/image.jpg" * createdAt: * type: string * format: date-time @@ -111,7 +116,9 @@ const router = express.Router(); * - id: "550e8400-e29b-41d4-a716-446655440000" * title: "게시글 제목" * content: "게시글 내용" - * imageUrl: "http://example.com/image.jpg" + * images: + * - "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg" + * - "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg" * createdAt: "2023-01-01T00:00:00.000Z" * likeCount: 5 * writer: "작성자" @@ -119,7 +126,9 @@ const router = express.Router(); * - id: "550e8400-e29b-41d4-a716-446655440000" * title: "인기 게시글 제목" * content: "인기 게시글 내용" - * imageUrl: "http://example.com/image.jpg" + * images: + * - "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg" + * - "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg" * createdAt: "2023-01-01T00:00:00.000Z" * likeCount: 10 * writer: "작성자" @@ -161,9 +170,11 @@ const router = express.Router(); * content: * type: string * example: "게시글 내용" - * imageUrl: - * type: string - * example: "http://example.com/image.jpg" + * images: + * type: array + * items: + * type: string + * example: "http://example.com/image.jpg" * createdAt: * type: string * format: date-time @@ -180,7 +191,8 @@ const router = express.Router(); * id: "550e8400-e29b-41d4-a716-446655440000" * title: "게시글 제목" * content: "게시글 내용" - * imageUrl: "http://example.com/image.jpg" + * images: + * - "http://example.com/image.jpg" * createdAt: "2023-01-01T00:00:00.000Z" * likeCount: 0 * writer: "작성자" @@ -202,9 +214,9 @@ const router = express.Router(); * summary: 유효하지 않은 토큰인 경우 * value: * message: "유효하지 않은 토큰입니다." - * */ router.route("/").get(articleController.getArticles).post(authenticate, articleController.createArticle); + /** * @swagger * /articles/{id}: @@ -234,9 +246,11 @@ router.route("/").get(articleController.getArticles).post(authenticate, articleC * content: * type: string * example: "게시글 내용" - * imageUrl: - * type: string - * example: "http://example.com/image.jpg" + * images: + * type: array + * items: + * type: string + * example: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg" * createdAt: * type: string * format: date-time @@ -253,7 +267,9 @@ router.route("/").get(articleController.getArticles).post(authenticate, articleC * id: "550e8400-e29b-41d4-a716-446655440000" * title: "게시글 제목" * content: "게시글 내용" - * imageUrl: "http://example.com/image.jpg" + * images: + * - "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg" + * - "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg" * createdAt: "2023-01-01T00:00:00.000Z" * likeCount: 5 * writer: "작성자" @@ -311,9 +327,11 @@ router.route("/").get(articleController.getArticles).post(authenticate, articleC * content: * type: string * example: "게시글 내용" - * imageUrl: - * type: string - * example: "http://example.com/image.jpg" + * images: + * type: array + * items: + * type: string + * example: "http://example.com/image.jpg" * createdAt: * type: string * format: date-time @@ -330,7 +348,8 @@ router.route("/").get(articleController.getArticles).post(authenticate, articleC * id: "550e8400-e29b-41d4-a716-446655440000" * title: "게시글 제목" * content: "게시글 내용" - * imageUrl: "http://example.com/image.jpg" + * images: + * - "http://example.com/image.jpg" * createdAt: "2023-01-01T00:00:00.000Z" * likeCount: 5 * writer: "작성자" @@ -472,9 +491,11 @@ router * content: * type: string * example: "게시글 내용" - * imageUrl: - * type: string - * example: "http://example.com/image.jpg" + * images: + * type: array + * items: + * type: string + * example: "http://example.com/image.jpg" * createdAt: * type: string * format: date-time @@ -491,7 +512,8 @@ router * id: "550e8400-e29b-41d4-a716-446655440000" * title: "게시글 제목" * content: "게시글 내용" - * imageUrl: "http://example.com/image.jpg" + * images: + * - "http://example.com/image.jpg" * createdAt: "2023-01-01T00:00:00.000Z" * likeCount: 6 * writer: "작성자" @@ -557,9 +579,11 @@ router.route("/:id/like").patch(authenticate, articleController.likeArticle); * content: * type: string * example: "게시글 내용" - * imageUrl: - * type: string - * example: "http://example.com/image.jpg" + * images: + * type: array + * items: + * type: string + * example: "http://example.com/image.jpg" * createdAt: * type: string * format: date-time @@ -576,7 +600,8 @@ router.route("/:id/like").patch(authenticate, articleController.likeArticle); * id: "550e8400-e29b-41d4-a716-446655440000" * title: "게시글 제목" * content: "게시글 내용" - * imageUrl: "http://example.com/image.jpg" + * images: + * - "http://example.com/image.jpg" * createdAt: "2023-01-01T00:00:00.000Z" * likeCount: 4 * writer: "작성자" @@ -611,6 +636,13 @@ router.route("/:id/like").patch(authenticate, articleController.likeArticle); */ router.route("/:id/unlike").patch(authenticate, articleController.unlikeArticle); +/** + * @swagger + * tags: + * name: Comments + * description: 댓글 + */ + /** * @swagger * /articles/{articleId}/comments: @@ -730,7 +762,6 @@ router.route("/:id/unlike").patch(authenticate, articleController.unlikeArticle) * type: object * properties: * message: - * type: string * examples: * noToken: * summary: 토큰이 제공되지 않은 경우 @@ -752,13 +783,6 @@ router.route("/:id/unlike").patch(authenticate, articleController.unlikeArticle) * example: "존재하지 않는 게시글입니다." */ -/** - * @swagger - * tags: - * name: Comments - * description: 댓글 - */ - router .route("/:articleId/comments") .get(commentController.getCommentsByProductId) @@ -829,7 +853,6 @@ router * type: object * properties: * message: - * type: string * examples: * noToken: * summary: 토큰이 제공되지 않은 경우 @@ -886,7 +909,6 @@ router * type: object * properties: * message: - * type: string * examples: * noToken: * summary: 토큰이 제공되지 않은 경우 diff --git a/src/routes/productRoutes.ts b/src/routes/productRoutes.ts index 60f2079..a160deb 100644 --- a/src/routes/productRoutes.ts +++ b/src/routes/productRoutes.ts @@ -45,42 +45,137 @@ const router = express.Router(); * description: 검색 키워드 * responses: * 200: - * description: 상품 목록 조회 성공 + * description: 성공적으로 제품 목록을 반환합니다. * content: * application/json: * schema: - * type: array - * items: - * type: object - * properties: - * id: - * type: string - * example: "1" - * name: - * type: string - * example: "상품 이름" - * description: - * type: string - * example: "상품 설명" - * price: - * type: number - * example: 1000 - * favoriteCount: - * type: number - * example: 5 - * createdAt: - * type: string - * format: date-time - * example: "2023-01-01T00:00:00.000Z" + * type: object + * properties: + * products: + * type: array + * items: + * type: object + * properties: + * id: + * type: string + * example: "상품 ID" + * name: + * type: string + * example: "상품 이름" + * description: + * type: string + * example: "상품 설명" + * price: + * type: number + * example: 1000 + * favoriteCount: + * type: number + * example: 5 + * createdAt: + * type: string + * format: date-time + * example: "2024-06-05T09:10:51.099Z" + * updatedAt: + * type: string + * format: date-time + * example: "2024-06-05T09:10:51.099Z" + * writer: + * type: string + * example: "작성자" + * tags: + * type: array + * items: + * type: string + * example: "태그" + * userId: + * type: number + * example: 1 + * images: + * type: array + * items: + * type: string + * example: "https://example.com/image.jpg" + * bestProducts: + * type: array + * items: + * type: object + * properties: + * id: + * type: string + * example: "상품 ID" + * name: + * type: string + * example: "상품 이름" + * description: + * type: string + * example: "상품 설명" + * price: + * type: number + * example: 7000 + * favoriteCount: + * type: number + * example: 7 + * createdAt: + * type: string + * format: date-time + * example: "2024-06-05T09:10:51.099Z" + * updatedAt: + * type: string + * format: date-time + * example: "2024-06-05T09:10:51.099Z" + * writer: + * type: string + * example: "김판다" + * tags: + * type: array + * items: + * type: string + * example: "판다인형" + * userId: + * type: number + * example: 1 + * images: + * type: array + * items: + * type: string + * example: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg" * examples: * application/json: * value: - * - id: "1" - * name: "상품 이름" - * description: "상품 설명" - * price: 1000 - * favoriteCount: 5 - * createdAt: "2023-01-01T00:00:00.000Z" + * products: [] + * bestProducts: + * - id: "377ce06c-23c8-46de-b86f-2cfd43d41cbc" + * name: "판다인형" + * description: "판다인형 판다" + * price: 700000 + * favoriteCount: 7 + * createdAt: "2024-06-05T09:10:51.099Z" + * updatedAt: "2024-06-05T09:10:51.099Z" + * writer: "김판다" + * tags: + * - "판다인형" + * - "인형" + * - "판다" + * userId: 1 + * images: + * - "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg" + * - "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg" + * - id: "d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9" + * name: "불곰사세요" + * description: "판다인형 안판다" + * price: 7000 + * favoriteCount: 2 + * createdAt: "2024-06-05T09:10:51.099Z" + * updatedAt: "2024-06-05T09:10:51.099Z" + * writer: "박불곰" + * tags: + * - "판다인형" + * - "인형" + * - "판다" + * - "불곰" + * userId: 2 + * images: + * - "https://view01.wemep.co.kr/wmp-product/4/879/2515748794/pm_ebifv5nrjsyf.jpg?1683280710&f=webp&w=460&h=460" * post: * summary: 상품 생성 * tags: [Products] @@ -181,32 +276,62 @@ router.route("/").get(productController.getProducts).post(authenticate, productC * properties: * id: * type: string - * example: "1" + * example: "377ce06c-23c8-46de-b86f-2cfd43d41cbc" * name: * type: string - * example: "상품 이름" + * example: "판다인형" * description: * type: string - * example: "상품 설명" + * example: "판다인형 판다" * price: * type: number - * example: 1000 + * example: 700000 * favoriteCount: * type: number - * example: 5 + * example: 7 * createdAt: * type: string * format: date-time - * example: "2023-01-01T00:00:00.000Z" + * example: "2024-06-05T09:10:51.099Z" + * writer: + * type: string + * example: "김판다" + * images: + * type: array + * items: + * type: string + * example: "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg" + * tags: + * type: array + * items: + * type: string + * example: "판다인형" + * updatedAt: + * type: string + * format: date-time + * example: "2024-06-05T09:10:51.099Z" + * userId: + * type: number + * example: 1 * examples: * application/json: * value: - * id: "1" - * name: "상품 이름" - * description: "상품 설명" - * price: 1000 - * favoriteCount: 5 - * createdAt: "2023-01-01T00:00:00.000Z" + * id: "377ce06c-23c8-46de-b86f-2cfd43d41cbc" + * name: "판다인형" + * description: "판다인형 판다" + * price: 700000 + * favoriteCount: 7 + * createdAt: "2024-06-05T09:10:51.099Z" + * writer: "김판다" + * images: + * - "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg" + * - "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg" + * tags: + * - "판다인형" + * - "인형" + * - "판다" + * updatedAt: "2024-06-05T09:10:51.099Z" + * userId: 1 * 404: * description: 상품을 찾을 수 없음 * content: @@ -608,7 +733,7 @@ router.route("/:id/unlike").patch(authenticate, productController.unlikeProduct) * - bearerAuth: [] * parameters: * - in: path - * name: articleId + * name: productId * required: true * schema: * type: string @@ -797,7 +922,7 @@ router * - bearerAuth: [] * parameters: * - in: path - * name: articleId + * name: productId * required: true * schema: * type: string diff --git a/src/services/articleService.ts b/src/services/articleService.ts index 30e456c..eb753f2 100644 --- a/src/services/articleService.ts +++ b/src/services/articleService.ts @@ -50,7 +50,10 @@ export const getArticles = async ({ }, }); - return articles; + return articles.map((article) => ({ + ...article, + images: article.images.map((image) => image.imagePath), + })); }; export const getBestArticles = async () => { @@ -73,7 +76,10 @@ export const getBestArticles = async () => { take: 4, }); - return bestArticles; + return bestArticles.map((article) => ({ + ...article, + images: article.images.map((image) => image.imagePath), + })); }; export const createArticle = async ( @@ -101,16 +107,21 @@ export const createArticle = async ( }, }; - return await prisma.article.create({ + const createdArticle = await prisma.article.create({ data: articleDataWithWriterName, include: { images: true, }, }); + + return { + ...createdArticle, + images: createdArticle.images.map((image) => image.imagePath), + }; }; export const getArticleById = async (id: string) => { - return await prisma.article.findUniqueOrThrow({ + const article = await prisma.article.findUniqueOrThrow({ where: { id }, select: { id: true, @@ -126,6 +137,11 @@ export const getArticleById = async (id: string) => { }, }, }); + + return { + ...article, + images: article.images.map((image) => image.imagePath), + }; }; export const updateArticle = async ( @@ -160,13 +176,18 @@ export const updateArticle = async ( } } - return await prisma.article.update({ + const updatedArticle = await prisma.article.update({ where: { id }, data: articleData, include: { images: true, }, }); + + return { + ...updatedArticle, + images: updatedArticle.images.map((image) => image.imagePath), + }; }; export const deleteArticle = async (articleId: string, userId: number) => { @@ -213,10 +234,20 @@ export const likeArticle = async (articleId: string, userId: number) => { increment: 1, }, }, + include: { + images: { + select: { + imagePath: true, + }, + }, + }, }), ]); - return updatedArticle; + return { + ...updatedArticle, + images: updatedArticle.images.map((image) => image.imagePath), + }; }; export const unlikeArticle = async (articleId: string, userId: number) => { @@ -251,8 +282,18 @@ export const unlikeArticle = async (articleId: string, userId: number) => { decrement: 1, }, }, + include: { + images: { + select: { + imagePath: true, + }, + }, + }, }), ]); - return updatedArticle; + return { + ...updatedArticle, + images: updatedArticle.images.map((image) => image.imagePath), + }; }; diff --git a/src/services/productService.ts b/src/services/productService.ts index 5664de3..144aa2a 100644 --- a/src/services/productService.ts +++ b/src/services/productService.ts @@ -12,11 +12,11 @@ export const getProducts = async ({ limit: number; orderBy: string; keyword: string; -}): Promise => { +}): Promise<(Product & { images: string[] })[]> => { const order: Prisma.ProductOrderByWithRelationInput = orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; - return await prisma.product.findMany({ + const products = await prisma.product.findMany({ orderBy: order, skip: offset, take: limit, @@ -54,9 +54,14 @@ export const getProducts = async ({ ], }, }); + + return products.map((product) => ({ + ...product, + images: product.images.map((image) => image.imagePath), + })); }; -export const getBestProducts = async () => { +export const getBestProducts = async (): Promise<(Product & { images: string[] })[]> => { const bestProducts = await prisma.product.findMany({ select: { id: true, @@ -81,14 +86,17 @@ export const getBestProducts = async () => { take: 4, }); - return bestProducts; + return bestProducts.map((product) => ({ + ...product, + images: product.images.map((image) => image.imagePath), + })); }; export const createProduct = async ( userId: number, productData: Omit, imageUrl: string -) => { +): Promise => { const user = await prisma.user.findUnique({ where: { id: userId }, select: { name: true }, @@ -109,15 +117,20 @@ export const createProduct = async ( }, }; - return await prisma.product.create({ + const createdProduct = await prisma.product.create({ data: productDataWithWriterName, include: { images: true, }, }); + + return { + ...createdProduct, + images: createdProduct.images.map((image) => image.imagePath), + }; }; -export const getProductById = async (id: string): Promise => { +export const getProductById = async (id: string): Promise<(Product & { images: string[] }) | null> => { const product = await prisma.product.findUnique({ where: { id }, select: { @@ -142,7 +155,11 @@ export const getProductById = async (id: string): Promise => { if (!product) { throw new AppError("존재하지 않는 상품입니다.", 404); } - return product; + + return { + ...product, + images: product.images.map((image) => image.imagePath), + }; }; export const updateProduct = async ( @@ -150,7 +167,7 @@ export const updateProduct = async ( userId: number, productData: Prisma.ProductUpdateInput, imageUrl: string -): Promise => { +): Promise => { const product = await prisma.product.findUniqueOrThrow({ where: { id }, include: { images: true }, @@ -177,13 +194,18 @@ export const updateProduct = async ( } } - return await prisma.product.update({ + const updatedProduct = await prisma.product.update({ where: { id }, data: productData, include: { images: true, }, }); + + return { + ...updatedProduct, + images: updatedProduct.images.map((image) => image.imagePath), + }; }; export const deleteProduct = async (productId: string, userId: number): Promise => { @@ -204,7 +226,7 @@ export const deleteProduct = async (productId: string, userId: number): Promise< }); }; -export const likeProduct = async (productId: string, userId: number): Promise => { +export const likeProduct = async (productId: string, userId: number): Promise => { const favorite = await prisma.favorite.findUnique({ where: { userId_productId: { @@ -234,13 +256,17 @@ export const likeProduct = async (productId: string, userId: number): Promise image.imagePath), + }; }; -export const unlikeProduct = async (productId: string, userId: number): Promise => { +export const unlikeProduct = async (productId: string, userId: number): Promise => { const favorite = await prisma.favorite.findUnique({ where: { userId_productId: { @@ -272,8 +298,12 @@ export const unlikeProduct = async (productId: string, userId: number): Promise< decrement: 1, }, }, + include: { images: true }, }), ]); - return updatedProduct; + return { + ...updatedProduct, + images: updatedProduct.images.map((image) => image.imagePath), + }; }; diff --git a/src/test/articleController.test.ts b/src/test/articleController.test.ts index 353f38e..7449585 100644 --- a/src/test/articleController.test.ts +++ b/src/test/articleController.test.ts @@ -35,16 +35,7 @@ const mockArticle = { likeCount: 0, writer: "김판다", userId: 1, - images: [ - { - id: "image-id", - imagePath: "image1.jpg", - articleId: "test-article-id", - createdAt: new Date(), - updatedAt: new Date(), - productId: null, - }, - ], + images: ["image1.jpg"], }; describe("게시글 컨트롤러", () => { diff --git a/src/test/articleService.test.ts b/src/test/articleService.test.ts index 2563591..ed0ec95 100644 --- a/src/test/articleService.test.ts +++ b/src/test/articleService.test.ts @@ -87,7 +87,12 @@ describe("게시글 서비스", () => { (prisma.article.findMany as jest.MockedFunction).mockResolvedValue(articles); const result = await getArticles({ offset: 0, limit: 10, orderBy: "recent", keyword: "" }); - expect(result).toEqual(articles); + expect(result).toEqual( + articles.map((article) => ({ + ...article, + images: article.images.map((image) => image.imagePath), + })) + ); expect(prisma.article.findMany).toHaveBeenCalledWith({ orderBy: { createdAt: "desc" }, skip: 0, @@ -113,7 +118,12 @@ describe("게시글 서비스", () => { (prisma.article.findMany as jest.MockedFunction).mockResolvedValue(articles); const result = await getBestArticles(); - expect(result).toEqual(articles); + expect(result).toEqual( + articles.map((article) => ({ + ...article, + images: article.images.map((image) => image.imagePath), + })) + ); expect(prisma.article.findMany).toHaveBeenCalledWith({ orderBy: { likeCount: "desc" }, take: 4, @@ -138,7 +148,10 @@ describe("게시글 서비스", () => { const result = await createArticle(1, { title: "새로운 게시글", content: "새로운 게시글 내용" }, "image1.jpg"); - expect(result).toEqual(mockArticle); + expect(result).toEqual({ + ...mockArticle, + images: mockArticle.images.map((image) => image.imagePath), + }); expect(prisma.user.findUnique).toHaveBeenCalledWith({ where: { id: 1 }, select: { name: true }, @@ -170,7 +183,10 @@ describe("게시글 서비스", () => { ).mockResolvedValue(mockArticle); const result = await getArticleById("test-article-id"); - expect(result).toEqual(mockArticle); + expect(result).toEqual({ + ...mockArticle, + images: mockArticle.images.map((image) => image.imagePath), + }); expect(prisma.article.findUniqueOrThrow).toHaveBeenCalledWith({ where: { id: "test-article-id" }, select: { @@ -224,7 +240,10 @@ describe("게시글 서비스", () => { "image1.jpg" ); - expect(result).toEqual(mockArticle); + expect(result).toEqual({ + ...mockArticle, + images: mockArticle.images.map((image) => image.imagePath), + }); expect(prisma.article.findUniqueOrThrow).toHaveBeenCalledWith({ where: { id: "test-article-id" }, include: { images: true }, @@ -268,7 +287,10 @@ describe("게시글 서비스", () => { "" ); - expect(result).toEqual(mockArticle); + expect(result).toEqual({ + ...mockArticle, + images: mockArticle.images.map((image) => image.imagePath), + }); expect(prisma.article.findUniqueOrThrow).toHaveBeenCalledWith({ where: { id: "test-article-id" }, include: { images: true }, @@ -302,7 +324,10 @@ describe("게시글 서비스", () => { "image1.jpg" ); - expect(result).toEqual(mockArticle); + expect(result).toEqual({ + ...mockArticle, + images: mockArticle.images.map((image) => image.imagePath), + }); expect(prisma.article.findUniqueOrThrow).toHaveBeenCalledWith({ where: { id: "test-article-id" }, include: { images: true }, @@ -374,7 +399,10 @@ describe("게시글 서비스", () => { ]); const result = await likeArticle("test-article-id", 1); - expect(result).toEqual(updatedArticle); + expect(result).toEqual({ + ...updatedArticle, + images: updatedArticle.images.map((image) => image.imagePath), + }); expect(result.likeCount).toBe(mockArticle.likeCount + 1); expect(prisma.favorite.findUnique).toHaveBeenCalledWith({ where: { @@ -417,7 +445,10 @@ describe("게시글 서비스", () => { ]); const result = await unlikeArticle("test-article-id", 1); - expect(result).toEqual(updatedArticle); + expect(result).toEqual({ + ...updatedArticle, + images: updatedArticle.images.map((image) => image.imagePath), + }); expect(result.likeCount).toBe(mockArticle.likeCount - 1); expect(prisma.favorite.findUnique).toHaveBeenCalledWith({ where: { diff --git a/src/test/imageController.test.ts b/src/test/imageController.test.ts index 8f4ca35..5f37f70 100644 --- a/src/test/imageController.test.ts +++ b/src/test/imageController.test.ts @@ -35,7 +35,7 @@ describe("getPresignedUrl", () => { beforeEach(() => { jest.clearAllMocks(); originalConsoleError = console.error; - console.error = jest.fn(); // suppress console.error during tests + console.error = jest.fn(); }); afterEach(() => { diff --git a/src/test/productController.test.ts b/src/test/productController.test.ts index 3a13b6e..bf66bff 100644 --- a/src/test/productController.test.ts +++ b/src/test/productController.test.ts @@ -18,16 +18,7 @@ const mockProducts = [ writer: "테스트 유저", tags: [], userId: 1, - images: [ - { - id: "image-id", - imagePath: "image1.jpg", - productId: null, - createdAt: new Date(), - updatedAt: new Date(), - articleId: null, - }, - ], + images: ["image1.jpg"], }, ]; @@ -43,16 +34,7 @@ const mockBestProducts = [ writer: "베스트 유저", tags: [], userId: 1, - images: [ - { - id: "image-id", - imagePath: "bestimage1.jpg", - productId: null, - createdAt: new Date(), - updatedAt: new Date(), - articleId: null, - }, - ], + images: ["bestimage1.jpg"], }, ]; @@ -121,16 +103,7 @@ describe("상품 컨트롤러", () => { writer: "테스트 유저", tags: [], userId: 1, - images: [ - { - id: "image-id", - imagePath: "image1.jpg", - productId: null, - createdAt: new Date(), - updatedAt: new Date(), - articleId: null, - }, - ], + images: ["image1.jpg"], }; (productService.createProduct as jest.MockedFunction).mockResolvedValue( @@ -162,16 +135,7 @@ describe("상품 컨트롤러", () => { writer: "테스트 유저", tags: [], userId: 1, - images: [ - { - id: "image-id", - imagePath: "image1.jpg", - productId: null, - createdAt: new Date(), - updatedAt: new Date(), - articleId: null, - }, - ], + images: ["image1.jpg"], }; (productService.getProductById as jest.MockedFunction).mockResolvedValue( @@ -202,16 +166,7 @@ describe("상품 컨트롤러", () => { writer: "테스트 유저", tags: [], userId: 1, - images: [ - { - id: "image-id", - imagePath: "image1.jpg", - productId: null, - createdAt: new Date(), - updatedAt: new Date(), - articleId: null, - }, - ], + images: ["image1.jpg"], }; (productService.updateProduct as jest.MockedFunction).mockResolvedValue( @@ -283,16 +238,7 @@ describe("상품 컨트롤러", () => { writer: "테스트 유저", tags: [], userId: 1, - images: [ - { - id: "image-id", - imagePath: "image1.jpg", - productId: null, - createdAt: new Date(), - updatedAt: new Date(), - articleId: null, - }, - ], + images: ["image1.jpg"], }; (productService.likeProduct as jest.MockedFunction).mockResolvedValue( @@ -336,16 +282,7 @@ describe("상품 컨트롤러", () => { writer: "테스트 유저", tags: [], userId: 1, - images: [ - { - id: "image-id", - imagePath: "image1.jpg", - productId: null, - createdAt: new Date(), - updatedAt: new Date(), - articleId: null, - }, - ], + images: ["image1.jpg"], }; (productService.unlikeProduct as jest.MockedFunction).mockResolvedValue( diff --git a/src/test/productService.test.ts b/src/test/productService.test.ts index ac5495b..27f881d 100644 --- a/src/test/productService.test.ts +++ b/src/test/productService.test.ts @@ -51,7 +51,16 @@ describe("상품 서비스", () => { writer: "테스트 유저", tags: [], userId: 1, - images: [{ id: "image-id", imagePath: "image1.jpg" }], + images: [ + { + id: "image-id", + imagePath: "image1.jpg", + productId: "test-product-id", + articleId: null, + createdAt: new Date(), + updatedAt: new Date(), + }, + ], }; const mockUser = { @@ -88,7 +97,12 @@ describe("상품 서비스", () => { (prisma.product.findMany as jest.MockedFunction).mockResolvedValue(products); const result = await getProducts({ offset: 0, limit: 10, orderBy: "recent", keyword: "" }); - expect(result).toEqual(products); + expect(result).toEqual( + products.map((product) => ({ + ...product, + images: product.images.map((image) => image.imagePath), + })) + ); expect(prisma.product.findMany).toHaveBeenCalledWith({ orderBy: { createdAt: "desc" }, skip: 0, @@ -119,7 +133,12 @@ describe("상품 서비스", () => { (prisma.product.findMany as jest.MockedFunction).mockResolvedValue(products); const result = await getBestProducts(); - expect(result).toEqual(products); + expect(result).toEqual( + products.map((product) => ({ + ...product, + images: product.images.map((image) => image.imagePath), + })) + ); expect(prisma.product.findMany).toHaveBeenCalledWith({ orderBy: { favoriteCount: "desc" }, take: 4, @@ -155,7 +174,10 @@ describe("상품 서비스", () => { "image1.jpg" ); - expect(result).toEqual(mockProduct); + expect(result).toEqual({ + ...mockProduct, + images: ["image1.jpg"], + }); expect(prisma.user.findUnique).toHaveBeenCalledWith({ where: { id: 1 }, select: { name: true }, @@ -196,7 +218,10 @@ describe("상품 서비스", () => { (prisma.product.findUnique as jest.MockedFunction).mockResolvedValue(mockProduct); const result = await getProductById("test-product-id"); - expect(result).toEqual(mockProduct); + expect(result).toEqual({ + ...mockProduct, + images: ["image1.jpg"], + }); expect(prisma.product.findUnique).toHaveBeenCalledWith({ where: { id: "test-product-id" }, select: { @@ -263,7 +288,10 @@ describe("상품 서비스", () => { "image1.jpg" ); - expect(result).toEqual(mockProduct); + expect(result).toEqual({ + ...mockProduct, + images: ["image1.jpg"], + }); expect(prisma.product.findUniqueOrThrow).toHaveBeenCalledWith({ where: { id: "test-product-id" }, include: { images: true }, @@ -312,7 +340,10 @@ describe("상품 서비스", () => { "" ); - expect(result).toEqual(mockProduct); + expect(result).toEqual({ + ...mockProduct, + images: mockProduct.images.map((image) => image.imagePath), + }); expect(prisma.product.findUniqueOrThrow).toHaveBeenCalledWith({ where: { id: "test-product-id" }, include: { images: true }, @@ -370,7 +401,10 @@ describe("상품 서비스", () => { "image1.jpg" ); - expect(result).toEqual(mockProduct); + expect(result).toEqual({ + ...mockProduct, + images: ["image1.jpg"], + }); expect(prisma.product.findUniqueOrThrow).toHaveBeenCalledWith({ where: { id: "test-product-id" }, include: { images: true }, @@ -440,7 +474,10 @@ describe("상품 서비스", () => { (prisma.$transaction as jest.MockedFunction).mockResolvedValue([null, updatedProduct]); const result = await likeProduct("test-product-id", 1); - expect(result).toEqual(updatedProduct); + expect(result).toEqual({ + ...updatedProduct, + images: ["image1.jpg"], + }); expect(result.favoriteCount).toBe(mockProduct.favoriteCount + 1); expect(prisma.favorite.findUnique).toHaveBeenCalledWith({ where: { @@ -478,7 +515,10 @@ describe("상품 서비스", () => { (prisma.$transaction as jest.MockedFunction).mockResolvedValue([null, updatedProduct]); const result = await unlikeProduct("test-product-id", 1); - expect(result).toEqual(updatedProduct); + expect(result).toEqual({ + ...updatedProduct, + images: ["image1.jpg"], + }); expect(result.favoriteCount).toBe(mockProduct.favoriteCount - 1); expect(prisma.favorite.findUnique).toHaveBeenCalledWith({ where: { diff --git a/src/test/tokens.test.ts b/src/test/tokens.test.ts index ae35ac8..4b87353 100644 --- a/src/test/tokens.test.ts +++ b/src/test/tokens.test.ts @@ -28,7 +28,6 @@ describe("Tokens Utility", () => { expect(jwt.sign).toHaveBeenCalledWith({ userId: mockUser.id }, secret, { expiresIn: "7d" }); expect(token).toBe("refreshToken"); }); - // 추가된 테스트 케이스: 유효한 리프레시 토큰을 사용하여 새로운 리프레시 토큰을 생성하는 경우 test("유효한 리프레시 토큰을 사용하여 새로운 리프레시 토큰을 생성한다", () => { const refreshToken = "validRefreshToken"; @@ -43,7 +42,6 @@ describe("Tokens Utility", () => { expect(token).toBe("newRefreshToken"); }); - // 추가된 테스트 케이스: 유효하지 않은 리프레시 토큰으로 인해 오류가 발생하는 경우 test("유효하지 않은 리프레시 토큰으로 인해 오류가 발생한다", () => { const refreshToken = "invalidRefreshToken"; From f3de0e790dcb0a106bea877d8f61dd0207cac17e Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Sun, 9 Jun 2024 11:24:49 +0900 Subject: [PATCH 54/60] =?UTF-8?q?[#M12]=20fix=20:=20article,=20product,=20?= =?UTF-8?q?comment=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C?= =?UTF-8?q?=20totalCount=EB=A5=BC=20=ED=95=A8=EA=BB=98=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/articleController.ts | 9 +++- src/controllers/commentController.ts | 12 +++-- src/controllers/productController.ts | 10 ++-- src/routes/articleRoutes.ts | 56 +++++++++++++-------- src/routes/productRoutes.ts | 75 ++++++++++++++++++++-------- src/services/articleService.ts | 21 ++++++++ src/services/commentService.ts | 42 +++++++--------- src/services/productService.ts | 21 ++++++++ 8 files changed, 170 insertions(+), 76 deletions(-) diff --git a/src/controllers/articleController.ts b/src/controllers/articleController.ts index aae99dd..22e6d20 100644 --- a/src/controllers/articleController.ts +++ b/src/controllers/articleController.ts @@ -20,9 +20,14 @@ export const getArticles = asyncHandler(async (req: Request<{}, {}, {}, GetArtic const { offset = "0", limit = "10", orderBy = "recent", keyword = "" } = req.query; const offsetNumber = parseInt(offset, 10); const limitNumber = parseInt(limit, 10); - const articles = await articleService.getArticles({ offset: offsetNumber, limit: limitNumber, orderBy, keyword }); + + const [articles, totalCount] = await Promise.all([ + articleService.getArticles({ offset: offsetNumber, limit: limitNumber, orderBy, keyword }), + articleService.getArticlesCount(keyword), + ]); + const bestArticles = await articleService.getBestArticles(); - res.send({ articles, bestArticles }); + res.send({ totalCount, articles, bestArticles }); }); // POST /articles diff --git a/src/controllers/commentController.ts b/src/controllers/commentController.ts index 24607ae..3d78c36 100644 --- a/src/controllers/commentController.ts +++ b/src/controllers/commentController.ts @@ -13,8 +13,10 @@ export const getCommentsByProductId = asyncHandler( async (req: Request<{ id: string }, {}, {}, { cursor?: string }>, res: Response) => { const { id: productId } = req.params; const { cursor } = req.query; - const comments = await commentService.getCommentsByProductId(productId, cursor); - res.send(comments); + const comments = await commentService.getCommentsByEntityId("product", productId, cursor); + const totalCount = await commentService.getCommentsCountByEntityId("product", productId); + + res.send({ totalCount, comments }); } ); @@ -23,8 +25,10 @@ export const getCommentsByArticleId = asyncHandler( async (req: Request<{ id: string }, {}, {}, { cursor?: string }>, res: Response) => { const { id: articleId } = req.params; const { cursor } = req.query; - const comments = await commentService.getCommentsByArticleId(articleId, cursor); - res.send(comments); + const comments = await commentService.getCommentsByEntityId("article", articleId, cursor); + const totalCount = await commentService.getCommentsCountByEntityId("article", articleId); + + res.send({ totalCount, comments }); } ); diff --git a/src/controllers/productController.ts b/src/controllers/productController.ts index f9c23e3..caa2c6e 100644 --- a/src/controllers/productController.ts +++ b/src/controllers/productController.ts @@ -7,7 +7,6 @@ import asyncHandler from "../utils/asyncHandler"; interface UserRequest extends Request { userId: number; } - // GET /products export const getProducts = asyncHandler( async ( @@ -17,9 +16,14 @@ export const getProducts = asyncHandler( const { offset = "0", limit = "10", orderBy = "recent", keyword = "" } = req.query; const offsetNumber = parseInt(offset, 10); const limitNumber = parseInt(limit, 10); - const products = await productService.getProducts({ offset: offsetNumber, limit: limitNumber, orderBy, keyword }); + + const [products, totalCount] = await Promise.all([ + productService.getProducts({ offset: offsetNumber, limit: limitNumber, orderBy, keyword }), + productService.getProductsCount(keyword), + ]); + const bestProducts = await productService.getBestProducts(); - res.send({ products, bestProducts }); + res.send({ totalCount, products, bestProducts }); } ); diff --git a/src/routes/articleRoutes.ts b/src/routes/articleRoutes.ts index 35fa3f9..1b923dc 100644 --- a/src/routes/articleRoutes.ts +++ b/src/routes/articleRoutes.ts @@ -51,6 +51,10 @@ const router = express.Router(); * schema: * type: object * properties: + * totalCount: + * type: number + * example: 100 + * description: "전체 게시글 수" * articles: * type: array * items: @@ -112,6 +116,7 @@ const router = express.Router(); * examples: * application/json: * value: + * totalCount: 100 * articles: * - id: "550e8400-e29b-41d4-a716-446655440000" * title: "게시글 제목" @@ -661,30 +666,39 @@ router.route("/:id/unlike").patch(authenticate, articleController.unlikeArticle) * content: * application/json: * schema: - * type: array - * items: - * type: object - * properties: - * id: - * type: string - * example: "550e8400-e29b-41d4-a716-446655440000" - * content: - * type: string - * example: "댓글 내용" - * createdAt: - * type: string - * format: date-time - * example: "2023-01-01T00:00:00.000Z" - * writer: - * type: string - * example: "작성자" + * type: object + * properties: + * totalCount: + * type: number + * example: 100 + * description: "전체 댓글 수" + * comments: + * type: array + * items: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * content: + * type: string + * example: "댓글 내용" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * writer: + * type: string + * example: "작성자" * examples: * application/json: * value: - * - id: "550e8400-e29b-41d4-a716-446655440000" - * content: "댓글 내용" - * createdAt: "2023-01-01T00:00:00.000Z" - * writer: "작성자" + * totalCount: 100 + * comments: + * - id: "550e8400-e29b-41d4-a716-446655440000" + * content: "댓글 내용" + * createdAt: "2023-01-01T00:00:00.000Z" + * writer: "작성자" * 404: * description: 게시글을 찾을 수 없음 * content: diff --git a/src/routes/productRoutes.ts b/src/routes/productRoutes.ts index a160deb..eb164d2 100644 --- a/src/routes/productRoutes.ts +++ b/src/routes/productRoutes.ts @@ -51,6 +51,10 @@ const router = express.Router(); * schema: * type: object * properties: + * totalCount: + * type: number + * example: 100 + * description: "전체 제품 수" * products: * type: array * items: @@ -142,7 +146,24 @@ const router = express.Router(); * examples: * application/json: * value: - * products: [] + * totalCount: 100 + * products: + * - id: "377ce06c-23c8-46de-b86f-2cfd43d41cbc" + * name: "판다인형" + * description: "판다인형 판다" + * price: 700000 + * favoriteCount: 7 + * createdAt: "2024-06-05T09:10:51.099Z" + * updatedAt: "2024-06-05T09:10:51.099Z" + * writer: "김판다" + * tags: + * - "판다인형" + * - "인형" + * - "판다" + * userId: 1 + * images: + * - "https://sitem.ssgcdn.com/62/11/49/item/1000559491162_i1_1100.jpg" + * - "https://wimg.mk.co.kr/meet/2021/09/image_listtop_2021_854860_1630738087.jpg" * bestProducts: * - id: "377ce06c-23c8-46de-b86f-2cfd43d41cbc" * name: "판다인형" @@ -176,6 +197,7 @@ const router = express.Router(); * userId: 2 * images: * - "https://view01.wemep.co.kr/wmp-product/4/879/2515748794/pm_ebifv5nrjsyf.jpg?1683280710&f=webp&w=460&h=460" + * post: * summary: 상품 생성 * tags: [Products] @@ -692,30 +714,39 @@ router.route("/:id/unlike").patch(authenticate, productController.unlikeProduct) * content: * application/json: * schema: - * type: array - * items: - * type: object - * properties: - * id: - * type: string - * example: "550e8400-e29b-41d4-a716-446655440000" - * content: - * type: string - * example: "댓글 내용" - * createdAt: - * type: string - * format: date-time - * example: "2023-01-01T00:00:00.000Z" - * writer: - * type: string - * example: "작성자" + * type: object + * properties: + * totalCount: + * type: number + * example: 100 + * description: "전체 댓글 수" + * comments: + * type: array + * items: + * type: object + * properties: + * id: + * type: string + * example: "550e8400-e29b-41d4-a716-446655440000" + * content: + * type: string + * example: "댓글 내용" + * createdAt: + * type: string + * format: date-time + * example: "2023-01-01T00:00:00.000Z" + * writer: + * type: string + * example: "작성자" * examples: * application/json: * value: - * - id: "550e8400-e29b-41d4-a716-446655440000" - * content: "댓글 내용" - * createdAt: "2023-01-01T00:00:00.000Z" - * writer: "작성자" + * totalCount: 100 + * comments: + * - id: "550e8400-e29b-41d4-a716-446655440000" + * content: "댓글 내용" + * createdAt: "2023-01-01T00:00:00.000Z" + * writer: "작성자" * 404: * description: 게시글을 찾을 수 없음 * content: diff --git a/src/services/articleService.ts b/src/services/articleService.ts index eb753f2..08edf86 100644 --- a/src/services/articleService.ts +++ b/src/services/articleService.ts @@ -82,6 +82,27 @@ export const getBestArticles = async () => { })); }; +export const getArticlesCount = async (keyword: string): Promise => { + return await prisma.article.count({ + where: { + OR: [ + { + title: { + contains: keyword, + mode: "insensitive", + }, + }, + { + content: { + contains: keyword, + mode: "insensitive", + }, + }, + ], + }, + }); +}; + export const createArticle = async ( userId: number, articleData: Omit, diff --git a/src/services/commentService.ts b/src/services/commentService.ts index ebc30af..4f55610 100644 --- a/src/services/commentService.ts +++ b/src/services/commentService.ts @@ -2,15 +2,19 @@ import { Comment, Prisma } from "@prisma/client"; import prisma from "../client"; import AppError from "../utils/errors"; -export const getCommentsByProductId = async (productId: string, cursor?: string): Promise => { +export const getCommentsByEntityId = async ( + entityType: "product" | "article", + entityId: string, + cursor?: string +): Promise => { + const whereClause = entityType === "product" ? { productId: entityId } : { articleId: entityId }; + const queryOptions: Prisma.CommentFindManyArgs = { take: 10, orderBy: { createdAt: "desc", }, - where: { - productId: productId, - }, + where: whereClause, select: { id: true, content: true, @@ -24,28 +28,18 @@ export const getCommentsByProductId = async (productId: string, cursor?: string) return await prisma.comment.findMany(queryOptions); }; -export const getCommentsByArticleId = async (articleId: string, cursor?: string): Promise => { - const queryOptions: Prisma.CommentFindManyArgs = { - take: 10, - orderBy: { - createdAt: "desc", - }, - where: { - articleId: articleId, - }, - select: { - id: true, - content: true, - createdAt: true, - writer: true, - }, - cursor: cursor ? { id: cursor } : undefined, - skip: cursor ? 1 : undefined, - }; +export const getCommentsCountByEntityId = async ( + entityType: "product" | "article", + entityId: string +): Promise => { + const whereClause = entityType === "product" ? { productId: entityId } : { articleId: entityId }; - return await prisma.comment.findMany(queryOptions); -}; + const totalCount = await prisma.comment.count({ + where: whereClause, + }); + return totalCount; +}; export const createComment = async (commentData: { content: string; imageUrl?: string; diff --git a/src/services/productService.ts b/src/services/productService.ts index 144aa2a..b7745a6 100644 --- a/src/services/productService.ts +++ b/src/services/productService.ts @@ -92,6 +92,27 @@ export const getBestProducts = async (): Promise<(Product & { images: string[] } })); }; +export const getProductsCount = async (keyword: string): Promise => { + return await prisma.product.count({ + where: { + OR: [ + { + name: { + contains: keyword, + mode: "insensitive", + }, + }, + { + description: { + contains: keyword, + mode: "insensitive", + }, + }, + ], + }, + }); +}; + export const createProduct = async ( userId: number, productData: Omit, From 61515809e27b58e56d813bc363a86ae70d037106 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Sun, 9 Jun 2024 12:34:51 +0900 Subject: [PATCH 55/60] =?UTF-8?q?[#M12]=20feat:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=EC=9D=84=20=EC=98=AC=EB=B0=94=EB=A5=B4?= =?UTF-8?q?=EA=B2=8C=20=EB=B0=9B=EC=95=84=EC=98=AC=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20API=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/commentController.ts | 9 ++++----- src/routes/articleRoutes.ts | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/controllers/commentController.ts b/src/controllers/commentController.ts index 3d78c36..d0caddb 100644 --- a/src/controllers/commentController.ts +++ b/src/controllers/commentController.ts @@ -10,8 +10,8 @@ interface UserRequest extends Request { // GET /products/:id/comments export const getCommentsByProductId = asyncHandler( - async (req: Request<{ id: string }, {}, {}, { cursor?: string }>, res: Response) => { - const { id: productId } = req.params; + async (req: Request<{ productId: string }, {}, {}, { cursor?: string }>, res: Response) => { + const { productId } = req.params; const { cursor } = req.query; const comments = await commentService.getCommentsByEntityId("product", productId, cursor); const totalCount = await commentService.getCommentsCountByEntityId("product", productId); @@ -22,8 +22,8 @@ export const getCommentsByProductId = asyncHandler( // GET /articles/:id/comments export const getCommentsByArticleId = asyncHandler( - async (req: Request<{ id: string }, {}, {}, { cursor?: string }>, res: Response) => { - const { id: articleId } = req.params; + async (req: Request<{ articleId: string }, {}, {}, { cursor?: string }>, res: Response) => { + const { articleId } = req.params; const { cursor } = req.query; const comments = await commentService.getCommentsByEntityId("article", articleId, cursor); const totalCount = await commentService.getCommentsCountByEntityId("article", articleId); @@ -31,7 +31,6 @@ export const getCommentsByArticleId = asyncHandler( res.send({ totalCount, comments }); } ); - // POST /comments export const createComment = asyncHandler(async (req: UserRequest, res: Response) => { assert(req.body, CreateComment); diff --git a/src/routes/articleRoutes.ts b/src/routes/articleRoutes.ts index 1b923dc..d80b695 100644 --- a/src/routes/articleRoutes.ts +++ b/src/routes/articleRoutes.ts @@ -799,7 +799,7 @@ router.route("/:id/unlike").patch(authenticate, articleController.unlikeArticle) router .route("/:articleId/comments") - .get(commentController.getCommentsByProductId) + .get(commentController.getCommentsByArticleId) .post(authenticate, commentController.createComment); /** From 169c842849c7f6f531f769dcb2623bc52fc18218 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Sun, 9 Jun 2024 14:01:05 +0900 Subject: [PATCH 56/60] =?UTF-8?q?[#M12]=20fix=20:=20=EC=A2=8B=EC=95=84?= =?UTF-8?q?=EC=9A=94=20=EC=A0=95=EB=A0=AC=EC=9D=84=20like=EB=A1=9C=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC,=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=EC=8B=9C=EC=97=90=EB=8F=84=20=EC=A2=8B=EC=95=84?= =?UTF-8?q?=EC=9A=94=20=EA=B0=9C=EC=88=98=EB=A5=BC=20=EA=B0=80=EC=A0=B8?= =?UTF-8?q?=EC=98=A4=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/productRoutes.ts | 2 +- src/services/articleService.ts | 1 + src/services/productService.ts | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/routes/productRoutes.ts b/src/routes/productRoutes.ts index eb164d2..adcd434 100644 --- a/src/routes/productRoutes.ts +++ b/src/routes/productRoutes.ts @@ -34,7 +34,7 @@ const router = express.Router(); * name: orderBy * schema: * type: string - * enum: [favorite, recent] + * enum: [like, recent] * example: recent * description: 정렬 기준 * - in: query diff --git a/src/services/articleService.ts b/src/services/articleService.ts index 08edf86..7b2685c 100644 --- a/src/services/articleService.ts +++ b/src/services/articleService.ts @@ -28,6 +28,7 @@ export const getArticles = async ({ imagePath: true, }, }, + likeCount: true, }, orderBy: order, skip: offset, diff --git a/src/services/productService.ts b/src/services/productService.ts index b7745a6..e3df547 100644 --- a/src/services/productService.ts +++ b/src/services/productService.ts @@ -14,7 +14,7 @@ export const getProducts = async ({ keyword: string; }): Promise<(Product & { images: string[] })[]> => { const order: Prisma.ProductOrderByWithRelationInput = - orderBy === "favorite" ? { favoriteCount: "desc" } : { createdAt: "desc" }; + orderBy === "like" ? { favoriteCount: "desc" } : { createdAt: "desc" }; const products = await prisma.product.findMany({ orderBy: order, From 8b4f90ed8666837b37023ab95afb2a680e12f1ca Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Sun, 9 Jun 2024 14:49:28 +0900 Subject: [PATCH 57/60] =?UTF-8?q?[#M12]=20fix=20:=20=EB=93=B1=EB=A1=9D,=20?= =?UTF-8?q?=EC=88=98=EC=A0=95,=20=EC=82=AD=EC=A0=9C=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=EC=9D=98=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- http/articles.http | 4 ++-- http/products.http | 6 +++--- src/controllers/articleController.ts | 12 ++++++------ src/controllers/commentController.ts | 8 ++++---- src/controllers/productController.ts | 12 ++++++------ 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/http/articles.http b/http/articles.http index b65d943..e9e1675 100644 --- a/http/articles.http +++ b/http/articles.http @@ -9,7 +9,7 @@ GET http://localhost:3000/articles/2c027764-d7ef-4a94-8399-f15ffbf8f4da ### # 게시글 등록 POST http://localhost:3000/articles -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzMwNDc2OCwiZXhwIjoxNzE3MzA1NjY4fQ.0Neh8i3gQWCU0o0y01-Co8jsW8kiXKl3dW7H6wK94pY +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzkxMjA4MCwiZXhwIjoxNzE3OTEyOTgwfQ.zYdtc0Vud63UdEn1dQVkiZwc-cDbvRzPogs0CfV29nY Content-Type: application/json { @@ -60,7 +60,7 @@ GET http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments # 자유게시판 댓글 등록 POST http://localhost:3000/articles/287cb4c8-48c5-49e1-82fa-a1b9e2d7b4e3/comments Content-Type: application/json -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODU1MiwiZXhwIjoxNzE3MTI5NDUyfQ.OAcMKEyrlzrtCOlz4HXu3mmDdEQ0s-oYBlbvlHWAJUY +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzkxMjA4MCwiZXhwIjoxNzE3OTEyOTgwfQ.zYdtc0Vud63UdEn1dQVkiZwc-cDbvRzPogs0CfV29nY { "content":"판다가 너무 귀여워요2" diff --git a/http/products.http b/http/products.http index ac4a7d6..bc248cc 100644 --- a/http/products.http +++ b/http/products.http @@ -18,7 +18,7 @@ GET http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc ### # 상품 등록 POST http://localhost:3000/products -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzM2ODk4OCwiZXhwIjoxNzE3MzY5ODg4fQ.KJMk2M5J_3fkHsYGljXhx30vBVUZI4rMYAOiROf6gLo +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzkxMjA4MCwiZXhwIjoxNzE3OTEyOTgwfQ.zYdtc0Vud63UdEn1dQVkiZwc-cDbvRzPogs0CfV29nY Content-Type: application/json { @@ -32,7 +32,7 @@ Content-Type: application/json ### # 상품 수정 PATCH http://localhost:3000/products/d4e8c9a0-5d45-4c9f-9b4b-7626f3c9c9a9 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzMwNTM2MCwiZXhwIjoxNzE3MzA2MjYwfQ.oxUkWqPB86HyizeCuzU-KcWvnOGRiA1_8CNPh9HuO0A +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzkxMjA4MCwiZXhwIjoxNzE3OTEyOTgwfQ.zYdtc0Vud63UdEn1dQVkiZwc-cDbvRzPogs0CfV29nY Content-Type: application/json { @@ -51,7 +51,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhd ### # 상품 좋아요 PATCH http://localhost:3000/products/377ce06c-23c8-46de-b86f-2cfd43d41cbc/like -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzEyODc3NiwiZXhwIjoxNzE3MTI5Njc2fQ.1P-sxAljy-HP-1LQ3F53tJJLCry3--KdL6mJSZSy4bc +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsImlhdCI6MTcxNzkxMjA4MCwiZXhwIjoxNzE3OTEyOTgwfQ.zYdtc0Vud63UdEn1dQVkiZwc-cDbvRzPogs0CfV29nY ### # 상품 좋아요 취소 diff --git a/src/controllers/articleController.ts b/src/controllers/articleController.ts index 22e6d20..f574523 100644 --- a/src/controllers/articleController.ts +++ b/src/controllers/articleController.ts @@ -12,7 +12,7 @@ interface GetArticlesQuery { } export interface UserRequest extends Request { - userId: number; + user: { _id: number }; } // GET /articles @@ -33,7 +33,7 @@ export const getArticles = asyncHandler(async (req: Request<{}, {}, {}, GetArtic // POST /articles export const createArticle = asyncHandler(async (req: UserRequest, res: Response) => { assert(req.body, CreateArticle); - const { userId } = req; + const { _id: userId } = req.user; const { imageUrl, ...articleData } = req.body; const article = await articleService.createArticle(userId!, articleData, imageUrl || ""); @@ -51,7 +51,7 @@ export const getArticleById = asyncHandler(async (req: Request<{ id: string }>, export const updateArticle = asyncHandler( async (req: UserRequest & Request<{ id: string }>, res: Response): Promise => { assert(req.body, PatchArticle); - const { userId } = req; + const { _id: userId } = req.user; const { id } = req.params; const { imageUrl, ...articleData } = req.body; const updatedArticle = await articleService.updateArticle(id, userId!, articleData, imageUrl || ""); @@ -63,7 +63,7 @@ export const updateArticle = asyncHandler( export const deleteArticle = asyncHandler( async (req: UserRequest & Request<{ id: string }>, res: Response): Promise => { const { id: articleId } = req.params; - const { userId } = req; + const { _id: userId } = req.user; await articleService.deleteArticle(articleId, userId); res.sendStatus(204); } @@ -72,7 +72,7 @@ export const deleteArticle = asyncHandler( // POST /articles/:id/like export const likeArticle = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { const { id: articleId } = req.params; - const { userId } = req; + const { _id: userId } = req.user; const updatedArticle = await articleService.likeArticle(articleId, userId); res.send(updatedArticle); }); @@ -80,7 +80,7 @@ export const likeArticle = asyncHandler(async (req: UserRequest & Request<{ id: // POST /articles/:id/unlike export const unlikeArticle = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { const { id: articleId } = req.params; - const { userId } = req; + const { _id: userId } = req.user; const updatedArticle = await articleService.unlikeArticle(articleId, userId); res.send(updatedArticle); }); diff --git a/src/controllers/commentController.ts b/src/controllers/commentController.ts index d0caddb..4fd31a3 100644 --- a/src/controllers/commentController.ts +++ b/src/controllers/commentController.ts @@ -5,7 +5,7 @@ import { CreateComment, PatchComment } from "../structs"; import asyncHandler from "../utils/asyncHandler"; interface UserRequest extends Request { - userId: number; + user: { _id: number }; } // GET /products/:id/comments @@ -35,7 +35,7 @@ export const getCommentsByArticleId = asyncHandler( export const createComment = asyncHandler(async (req: UserRequest, res: Response) => { assert(req.body, CreateComment); - const { userId } = req; + const { _id: userId } = req.user; const commentData = { ...req.body, userId, @@ -49,7 +49,7 @@ export const createComment = asyncHandler(async (req: UserRequest, res: Response export const updateComment = asyncHandler(async (req: UserRequest & Request<{ commentId: string }>, res: Response) => { assert(req.body, PatchComment); - const { userId } = req; + const { _id: userId } = req.user; const { content } = req.body; const { commentId } = req.params; @@ -70,7 +70,7 @@ export const updateComment = asyncHandler(async (req: UserRequest & Request<{ co // DELETE /comments/:commentId export const deleteComment = asyncHandler(async (req: UserRequest & Request<{ commentId: string }>, res: Response) => { const { commentId } = req.params; - const { userId } = req; + const { _id: userId } = req.user; await commentService.deleteComment(commentId, userId); res.sendStatus(204); diff --git a/src/controllers/productController.ts b/src/controllers/productController.ts index caa2c6e..374b250 100644 --- a/src/controllers/productController.ts +++ b/src/controllers/productController.ts @@ -5,7 +5,7 @@ import { CreateProduct, PatchProduct } from "../structs"; import asyncHandler from "../utils/asyncHandler"; interface UserRequest extends Request { - userId: number; + user: { _id: number }; } // GET /products export const getProducts = asyncHandler( @@ -30,7 +30,7 @@ export const getProducts = asyncHandler( // POST /products export const createProduct = asyncHandler(async (req: UserRequest, res: Response) => { assert(req.body, CreateProduct); - const { userId } = req; + const { _id: userId } = req.user; const { imageUrl, ...productData } = req.body; const product = await productService.createProduct(userId!, productData, imageUrl || ""); @@ -48,7 +48,7 @@ export const getProductById = asyncHandler(async (req: Request<{ id: string }>, export const updateProduct = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { assert(req.body, PatchProduct); - const { userId } = req; + const { _id: userId } = req.user; const { id } = req.params; const { imageUrl, ...productData } = req.body; const updatedProduct = await productService.updateProduct(id, userId, productData, imageUrl || ""); @@ -58,7 +58,7 @@ export const updateProduct = asyncHandler(async (req: UserRequest & Request<{ id // DELETE /products/:id export const deleteProduct = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { const { id: productId } = req.params; - const { userId } = req; + const { _id: userId } = req.user; await productService.deleteProduct(productId, userId); res.sendStatus(204); }); @@ -66,7 +66,7 @@ export const deleteProduct = asyncHandler(async (req: UserRequest & Request<{ id // POST /products/:id/like export const likeProduct = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { const { id: productId } = req.params; - const { userId } = req; + const { _id: userId } = req.user; const updatedProduct = await productService.likeProduct(productId, userId); res.send(updatedProduct); }); @@ -74,7 +74,7 @@ export const likeProduct = asyncHandler(async (req: UserRequest & Request<{ id: // POST /products/:id/unlike export const unlikeProduct = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { const { id: productId } = req.params; - const { userId } = req; + const { _id: userId } = req.user; const updatedProduct = await productService.unlikeProduct(productId, userId); res.send(updatedProduct); }); From f64babecfee230d258fa6ed822583c8b85107779 Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Sun, 9 Jun 2024 15:05:09 +0900 Subject: [PATCH 58/60] =?UTF-8?q?[#M12]=20fix:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EC=8B=9C=20productId=EC=99=80=20articleId?= =?UTF-8?q?=EA=B0=80=20=EC=A0=9C=EB=8C=80=EB=A1=9C=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/commentController.ts | 5 ++++- src/services/commentService.ts | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/controllers/commentController.ts b/src/controllers/commentController.ts index 4fd31a3..c055ab4 100644 --- a/src/controllers/commentController.ts +++ b/src/controllers/commentController.ts @@ -34,14 +34,17 @@ export const getCommentsByArticleId = asyncHandler( // POST /comments export const createComment = asyncHandler(async (req: UserRequest, res: Response) => { assert(req.body, CreateComment); - + const { productId, articleId } = req.params; const { _id: userId } = req.user; const commentData = { + productId: productId, + articleId: articleId, ...req.body, userId, }; const comment = await commentService.createComment(commentData); + console.log(comment); res.status(201).send(comment); }); diff --git a/src/services/commentService.ts b/src/services/commentService.ts index 4f55610..3278f90 100644 --- a/src/services/commentService.ts +++ b/src/services/commentService.ts @@ -65,6 +65,7 @@ export const createComment = async (commentData: { data: commentDataWithWriterName, }); }; + export const updateComment = async (commentId: string, userId: number, content: string): Promise => { const comment = await prisma.comment.findUnique({ where: { id: commentId }, From 6512847c5c2b3d49ccebe82b4aecc7d06570845b Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Fri, 14 Jun 2024 14:34:57 +0900 Subject: [PATCH 59/60] =?UTF-8?q?[#M12]=20fix:=20=EC=A2=8B=EC=95=84?= =?UTF-8?q?=EC=9A=94,=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EC=B7=A8=EC=86=8C?= =?UTF-8?q?=EC=9D=98=20http=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 테스트가 모두 통과할 수 있도록 테스트 코드 수정 --- src/controllers/commentController.ts | 1 - src/routes/articleRoutes.ts | 4 +- src/routes/productRoutes.ts | 4 +- src/services/commentService.ts | 1 + src/test/articleController.test.ts | 14 +++--- src/test/articleService.test.ts | 1 + src/test/commentController.test.ts | 75 +++++++++++++++------------- src/test/commentService.test.ts | 4 +- src/test/productController.test.ts | 14 +++--- 9 files changed, 64 insertions(+), 54 deletions(-) diff --git a/src/controllers/commentController.ts b/src/controllers/commentController.ts index c055ab4..e97e0dc 100644 --- a/src/controllers/commentController.ts +++ b/src/controllers/commentController.ts @@ -44,7 +44,6 @@ export const createComment = asyncHandler(async (req: UserRequest, res: Response }; const comment = await commentService.createComment(commentData); - console.log(comment); res.status(201).send(comment); }); diff --git a/src/routes/articleRoutes.ts b/src/routes/articleRoutes.ts index d80b695..e951c6f 100644 --- a/src/routes/articleRoutes.ts +++ b/src/routes/articleRoutes.ts @@ -551,7 +551,7 @@ router * type: string * example: "이미 좋아요 처리된 게시글입니다." */ -router.route("/:id/like").patch(authenticate, articleController.likeArticle); +router.route("/:id/like").post(authenticate, articleController.likeArticle); /** * @swagger @@ -639,7 +639,7 @@ router.route("/:id/like").patch(authenticate, articleController.likeArticle); * type: string * example: "아직 좋아요 처리되지 않은 게시글입니다." */ -router.route("/:id/unlike").patch(authenticate, articleController.unlikeArticle); +router.route("/:id/unlike").delete(authenticate, articleController.unlikeArticle); /** * @swagger diff --git a/src/routes/productRoutes.ts b/src/routes/productRoutes.ts index adcd434..1fe75f0 100644 --- a/src/routes/productRoutes.ts +++ b/src/routes/productRoutes.ts @@ -613,7 +613,7 @@ router * type: string * example: "이미 좋아요 처리된 상품입니다." */ -router.route("/:id/like").patch(authenticate, productController.likeProduct); +router.route("/:id/like").post(authenticate, productController.likeProduct); /** * @swagger @@ -694,7 +694,7 @@ router.route("/:id/like").patch(authenticate, productController.likeProduct); * type: string * example: "아직 좋아요 처리되지 않은 상품입니다." */ -router.route("/:id/unlike").patch(authenticate, productController.unlikeProduct); +router.route("/:id/unlike").delete(authenticate, productController.unlikeProduct); /** * @swagger diff --git a/src/services/commentService.ts b/src/services/commentService.ts index 3278f90..774471e 100644 --- a/src/services/commentService.ts +++ b/src/services/commentService.ts @@ -40,6 +40,7 @@ export const getCommentsCountByEntityId = async ( return totalCount; }; + export const createComment = async (commentData: { content: string; imageUrl?: string; diff --git a/src/test/articleController.test.ts b/src/test/articleController.test.ts index 7449585..cce246d 100644 --- a/src/test/articleController.test.ts +++ b/src/test/articleController.test.ts @@ -11,7 +11,9 @@ const setup = () => { body: {}, params: {}, query: {}, - userId: 1, + user:{ + _id:1 + } } as unknown as Request<{ id: string }> & { userId: number }; const res = { @@ -84,7 +86,7 @@ describe("게시글 컨트롤러", () => { await articleController.createArticle(req, res, next); expect(articleService.createArticle).toHaveBeenCalledWith( - req.userId, + req.user?._id, { title: "새로운 게시글", content: "새로운 게시글 내용" }, "image1.jpg" ); @@ -139,7 +141,7 @@ describe("게시글 컨트롤러", () => { expect(articleService.updateArticle).toHaveBeenCalledWith( "1", - req.userId, + req.user?._id, { title: "수정된 게시글", content: "수정된 게시글 내용" }, "image1.jpg" ); @@ -169,7 +171,7 @@ describe("게시글 컨트롤러", () => { await articleController.deleteArticle(req, res, next); - expect(articleService.deleteArticle).toHaveBeenCalledWith("1", req.userId); + expect(articleService.deleteArticle).toHaveBeenCalledWith("1", req.user?._id); expect(res.sendStatus).toHaveBeenCalledWith(204); }); @@ -201,7 +203,7 @@ describe("게시글 컨트롤러", () => { await articleController.likeArticle(req, res, next); - expect(articleService.likeArticle).toHaveBeenCalledWith("1", req.userId); + expect(articleService.likeArticle).toHaveBeenCalledWith("1", req.user?._id); expect(res.send).toHaveBeenCalledWith(mockUpdatedArticle); }); @@ -233,7 +235,7 @@ describe("게시글 컨트롤러", () => { await articleController.unlikeArticle(req, res, next); - expect(articleService.unlikeArticle).toHaveBeenCalledWith("1", req.userId); + expect(articleService.unlikeArticle).toHaveBeenCalledWith("1", req.user?._id); expect(res.send).toHaveBeenCalledWith(mockUpdatedArticle); }); diff --git a/src/test/articleService.test.ts b/src/test/articleService.test.ts index ed0ec95..1f6d175 100644 --- a/src/test/articleService.test.ts +++ b/src/test/articleService.test.ts @@ -103,6 +103,7 @@ describe("게시글 서비스", () => { select: { id: true, title: true, + likeCount: true, content: true, createdAt: true, writer: true, diff --git a/src/test/commentController.test.ts b/src/test/commentController.test.ts index 69b1925..c9f82bb 100644 --- a/src/test/commentController.test.ts +++ b/src/test/commentController.test.ts @@ -1,4 +1,5 @@ import { beforeEach, describe, expect, jest, test } from "@jest/globals"; +import { Comment } from '@prisma/client'; import { NextFunction, Request, Response } from "express"; import { assert } from "superstruct"; import * as commentController from "../controllers/commentController"; @@ -15,13 +16,13 @@ jest.mock("superstruct", () => { }; }); -const setup = () => { +const setup = (params: { [key: string]: string } = {}) => { const req = { body: {}, - params: {}, + params: params, query: {}, - userId: 1, - } as unknown as Request<{ id: string; commentId: string }> & { userId: number }; + user: { _id: '1' }, + } as unknown as Request & { user: { _id: string } }; const res = { status: jest.fn().mockReturnThis(), @@ -41,10 +42,10 @@ describe("댓글 컨트롤러", () => { }); describe("getCommentsByProductId", () => { - test("상품의 댓글을 반환해야 한다", async () => { - const { req, res, next } = setup(); - req.params.id = "1"; - const mockComments = [ + test("상품의 댓글과 댓글 수를 반환해야 한다", async () => { + const { req, res, next } = setup({ productId: "1" }); + + const mockComments: Comment[] = [ { id: "1", content: "멋진 상품!", @@ -56,21 +57,26 @@ describe("댓글 컨트롤러", () => { userId: 1, }, ]; - ( - commentService.getCommentsByProductId as jest.MockedFunction - ).mockResolvedValue(mockComments); + + const mockTotalCount = 1; + + (commentService.getCommentsByEntityId as jest.MockedFunction).mockResolvedValue(mockComments); + (commentService.getCommentsCountByEntityId as jest.MockedFunction).mockResolvedValue(mockTotalCount); await commentController.getCommentsByProductId(req, res, next); - expect(res.send).toHaveBeenCalledWith(mockComments); + expect(commentService.getCommentsByEntityId).toHaveBeenCalledWith("product", "1", undefined); + expect(commentService.getCommentsCountByEntityId).toHaveBeenCalledWith("product", "1"); + expect(res.send).toHaveBeenCalledWith({ comments: mockComments, totalCount: mockTotalCount }); + expect(res.send).toHaveBeenCalledTimes(1); }); }); describe("getCommentsByArticleId", () => { - test("게시글의 댓글을 반환해야 한다", async () => { - const { req, res, next } = setup(); - req.params.id = "1"; - const mockComments = [ + test("게시글의 댓글과 댓글 수를 반환해야 한다", async () => { + const { req, res, next } = setup({ articleId: "1" }); + + const mockComments: Comment[] = [ { id: "1", content: "멋진 게시글!", @@ -82,13 +88,18 @@ describe("댓글 컨트롤러", () => { userId: 1, }, ]; - ( - commentService.getCommentsByArticleId as jest.MockedFunction - ).mockResolvedValue(mockComments); + + const mockTotalCount = 1; + + (commentService.getCommentsByEntityId as jest.MockedFunction).mockResolvedValue(mockComments); + (commentService.getCommentsCountByEntityId as jest.MockedFunction).mockResolvedValue(mockTotalCount); await commentController.getCommentsByArticleId(req, res, next); - expect(res.send).toHaveBeenCalledWith(mockComments); + expect(commentService.getCommentsByEntityId).toHaveBeenCalledWith("article", "1", undefined); + expect(commentService.getCommentsCountByEntityId).toHaveBeenCalledWith("article", "1"); + expect(res.send).toHaveBeenCalledWith({ comments: mockComments, totalCount: mockTotalCount }); + expect(res.send).toHaveBeenCalledTimes(1); }); }); @@ -113,7 +124,7 @@ describe("댓글 컨트롤러", () => { await commentController.createComment(req, res, next); expect(assert).toHaveBeenCalledWith(req.body, CreateComment); - expect(commentService.createComment).toHaveBeenCalledWith({ ...req.body, userId: req.userId }); + expect(commentService.createComment).toHaveBeenCalledWith({ ...req.body, userId: req.user._id }); expect(res.status).toHaveBeenCalledWith(201); expect(res.send).toHaveBeenCalledWith(mockComment); }); @@ -121,8 +132,7 @@ describe("댓글 컨트롤러", () => { describe("updateComment", () => { test("댓글을 업데이트해야 한다", async () => { - const { req, res, next } = setup(); - req.params.commentId = "1"; + const { req, res, next } = setup({ commentId: "1" }); req.body = { content: "업데이트된 댓글" }; const mockUpdatedComment = { @@ -142,13 +152,12 @@ describe("댓글 컨트롤러", () => { await commentController.updateComment(req, res, next); expect(assert).toHaveBeenCalledWith(req.body, PatchComment); - expect(commentService.updateComment).toHaveBeenCalledWith("1", req.userId, "업데이트된 댓글"); + expect(commentService.updateComment).toHaveBeenCalledWith("1", req.user._id, "업데이트된 댓글"); expect(res.send).toHaveBeenCalledWith(mockUpdatedComment); }); test("댓글 수정 시 commentId가 없으면 400 에러를 반환해야 한다", async () => { - const { req, res, next } = setup(); - req.params.commentId = ""; + const { req, res, next } = setup({ commentId: "" }); await commentController.updateComment(req, res, next); @@ -157,8 +166,7 @@ describe("댓글 컨트롤러", () => { }); test("댓글 수정 시 content가 없으면 400 에러를 반환해야 한다", async () => { - const { req, res, next } = setup(); - req.params.commentId = "1"; + const { req, res, next } = setup({ commentId: "1" }); req.body.content = ""; await commentController.updateComment(req, res, next); @@ -168,8 +176,7 @@ describe("댓글 컨트롤러", () => { }); test("댓글 수정 시 권한이 없으면 예외를 발생시켜야 한다", async () => { - const { req, res, next } = setup(); - req.params.commentId = "1"; + const { req, res, next } = setup({ commentId: "1" }); req.body = { content: "업데이트된 댓글" }; (commentService.updateComment as jest.MockedFunction).mockRejectedValue( @@ -185,18 +192,16 @@ describe("댓글 컨트롤러", () => { describe("deleteComment", () => { test("댓글을 삭제해야 한다", async () => { - const { req, res, next } = setup(); - req.params.commentId = "1"; + const { req, res, next } = setup({ commentId: "1" }); await commentController.deleteComment(req, res, next); - expect(commentService.deleteComment).toHaveBeenCalledWith("1", req.userId); + expect(commentService.deleteComment).toHaveBeenCalledWith("1", req.user._id); expect(res.sendStatus).toHaveBeenCalledWith(204); }); test("댓글 삭제 시 권한이 없으면 예외를 발생시켜야 한다", async () => { - const { req, res, next } = setup(); - req.params.commentId = "1"; + const { req, res, next } = setup({ commentId: "1" }); (commentService.deleteComment as jest.MockedFunction).mockRejectedValue( new AppError("댓글을 삭제할 권한이 없습니다.", 403) diff --git a/src/test/commentService.test.ts b/src/test/commentService.test.ts index 38aaa6f..9f4fd04 100644 --- a/src/test/commentService.test.ts +++ b/src/test/commentService.test.ts @@ -54,7 +54,7 @@ describe("Comment Service", () => { test("상품 ID로 댓글을 가져와야 한다", async () => { (prisma.comment.findMany as jest.MockedFunction).mockResolvedValue(mockComments); - const comments = await commentService.getCommentsByProductId("1"); + const comments = await commentService.getCommentsByEntityId('product', "1"); expect(prisma.comment.findMany).toHaveBeenCalledWith({ take: 10, @@ -72,7 +72,7 @@ describe("Comment Service", () => { test("게시글 ID로 댓글을 가져와야 한다", async () => { (prisma.comment.findMany as jest.MockedFunction).mockResolvedValue(mockComments); - const comments = await commentService.getCommentsByArticleId("1"); + const comments = await commentService.getCommentsByEntityId('article',"1"); expect(prisma.comment.findMany).toHaveBeenCalledWith({ take: 10, diff --git a/src/test/productController.test.ts b/src/test/productController.test.ts index bf66bff..0b500cc 100644 --- a/src/test/productController.test.ts +++ b/src/test/productController.test.ts @@ -53,7 +53,9 @@ const setup = () => { body: {}, params: {}, query: {}, - userId: 1, + user: { + _id:1 + }, } as unknown as Request<{ id: string }> & { userId: number }; const res = { @@ -113,7 +115,7 @@ describe("상품 컨트롤러", () => { await productController.createProduct(req, res, next); expect(assert).toHaveBeenCalledWith(req.body, CreateProduct); - expect(productService.createProduct).toHaveBeenCalledWith(req.userId, req.body, ""); + expect(productService.createProduct).toHaveBeenCalledWith(req.user?._id, req.body, ""); expect(res.status).toHaveBeenCalledWith(201); expect(res.send).toHaveBeenCalledWith(mockProduct); }); @@ -176,7 +178,7 @@ describe("상품 컨트롤러", () => { await productController.updateProduct(req, res, next); expect(assert).toHaveBeenCalledWith(req.body, PatchProduct); - expect(productService.updateProduct).toHaveBeenCalledWith("1", req.userId, req.body, ""); + expect(productService.updateProduct).toHaveBeenCalledWith("1", req.user?._id, req.body, ""); expect(res.send).toHaveBeenCalledWith(mockUpdatedProduct); }); @@ -203,7 +205,7 @@ describe("상품 컨트롤러", () => { await productController.deleteProduct(req, res, next); - expect(productService.deleteProduct).toHaveBeenCalledWith("1", req.userId); + expect(productService.deleteProduct).toHaveBeenCalledWith("1", req.user?._id); expect(res.sendStatus).toHaveBeenCalledWith(204); }); @@ -247,7 +249,7 @@ describe("상품 컨트롤러", () => { await productController.likeProduct(req, res, next); - expect(productService.likeProduct).toHaveBeenCalledWith("1", req.userId); + expect(productService.likeProduct).toHaveBeenCalledWith("1", req.user?._id); expect(res.send).toHaveBeenCalledWith(mockUpdatedProduct); }); @@ -291,7 +293,7 @@ describe("상품 컨트롤러", () => { await productController.unlikeProduct(req, res, next); - expect(productService.unlikeProduct).toHaveBeenCalledWith("1", req.userId); + expect(productService.unlikeProduct).toHaveBeenCalledWith("1", req.user?._id); expect(res.send).toHaveBeenCalledWith(mockUpdatedProduct); }); From ebde44ad06c764e4bc521ac7efe257682fcd7c3b Mon Sep 17 00:00:00 2001 From: aowjarkwk Date: Fri, 14 Jun 2024 15:39:36 +0900 Subject: [PATCH 60/60] =?UTF-8?q?[#M12]=20fix:=20=EC=83=81=ED=92=88,=20?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=83=81=EC=84=B8=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=8B=9C=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EC=97=AC?= =?UTF-8?q?=EB=B6=80=EB=A5=BC=20=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 로그인 사용자만 상세 조회 가능하도록 수정 --- src/controllers/articleController.ts | 5 +++-- src/controllers/productController.ts | 5 +++-- src/routes/articleRoutes.ts | 2 +- src/routes/productRoutes.ts | 2 +- src/services/articleService.ts | 16 ++++++++++++++-- src/services/productService.ts | 18 +++++++++++++++--- src/test/articleController.test.ts | 15 ++++++++++++++- src/test/articleService.test.ts | 3 ++- src/test/productController.test.ts | 3 ++- src/test/productService.test.ts | 1 + 10 files changed, 56 insertions(+), 14 deletions(-) diff --git a/src/controllers/articleController.ts b/src/controllers/articleController.ts index f574523..a10dfa7 100644 --- a/src/controllers/articleController.ts +++ b/src/controllers/articleController.ts @@ -41,9 +41,10 @@ export const createArticle = asyncHandler(async (req: UserRequest, res: Response }); // GET /articles/:id -export const getArticleById = asyncHandler(async (req: Request<{ id: string }>, res: Response): Promise => { +export const getArticleById = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response): Promise => { const { id } = req.params; - const article = await articleService.getArticleById(id); + const { _id: userId } = req.user; + const article = await articleService.getArticleById(id,userId); res.send(article); }); diff --git a/src/controllers/productController.ts b/src/controllers/productController.ts index 374b250..ef98bbd 100644 --- a/src/controllers/productController.ts +++ b/src/controllers/productController.ts @@ -38,9 +38,10 @@ export const createProduct = asyncHandler(async (req: UserRequest, res: Response }); // GET /products/:id -export const getProductById = asyncHandler(async (req: Request<{ id: string }>, res: Response) => { +export const getProductById = asyncHandler(async (req: UserRequest & Request<{ id: string }>, res: Response) => { const { id } = req.params; - const product = await productService.getProductById(id); + const { _id: userId } = req.user; + const product = await productService.getProductById(id, userId); res.send(product); }); diff --git a/src/routes/articleRoutes.ts b/src/routes/articleRoutes.ts index e951c6f..0cc9f72 100644 --- a/src/routes/articleRoutes.ts +++ b/src/routes/articleRoutes.ts @@ -461,7 +461,7 @@ router.route("/").get(articleController.getArticles).post(authenticate, articleC */ router .route("/:id") - .get(articleController.getArticleById) + .get(authenticate,articleController.getArticleById) .patch(authenticate, articleController.updateArticle) .delete(authenticate, articleController.deleteArticle); diff --git a/src/routes/productRoutes.ts b/src/routes/productRoutes.ts index 1fe75f0..50ee5c5 100644 --- a/src/routes/productRoutes.ts +++ b/src/routes/productRoutes.ts @@ -530,7 +530,7 @@ router.route("/").get(productController.getProducts).post(authenticate, productC */ router .route("/:id") - .get(productController.getProductById) + .get(authenticate,productController.getProductById) .patch(authenticate, productController.updateProduct) .delete(authenticate, productController.deleteProduct); diff --git a/src/services/articleService.ts b/src/services/articleService.ts index 7b2685c..0377e33 100644 --- a/src/services/articleService.ts +++ b/src/services/articleService.ts @@ -142,9 +142,9 @@ export const createArticle = async ( }; }; -export const getArticleById = async (id: string) => { +export const getArticleById = async (articleId: string,userId?:number) => { const article = await prisma.article.findUniqueOrThrow({ - where: { id }, + where: { id: articleId }, select: { id: true, title: true, @@ -160,9 +160,21 @@ export const getArticleById = async (id: string) => { }, }); + const isLiked = userId + ? await prisma.favorite.findUnique({ + where: { + userId_articleId: { + userId, + articleId, + }, + }, + }) + : null; + return { ...article, images: article.images.map((image) => image.imagePath), + isLiked: Boolean(isLiked), }; }; diff --git a/src/services/productService.ts b/src/services/productService.ts index e3df547..c41d7fb 100644 --- a/src/services/productService.ts +++ b/src/services/productService.ts @@ -151,9 +151,9 @@ export const createProduct = async ( }; }; -export const getProductById = async (id: string): Promise<(Product & { images: string[] }) | null> => { +export const getProductById = async (productId: string,userId?:number) => { const product = await prisma.product.findUnique({ - where: { id }, + where: { id:productId }, select: { id: true, name: true, @@ -173,13 +173,25 @@ export const getProductById = async (id: string): Promise<(Product & { images: s }, }); + const isLiked = userId + ? await prisma.favorite.findUnique({ + where: { + userId_productId: { + userId, + productId, + }, + }, + }) + : null; + if (!product) { throw new AppError("존재하지 않는 상품입니다.", 404); } return { ...product, - images: product.images.map((image) => image.imagePath), + images: product.images.map((image) => image.imagePath), + isLiked: Boolean(isLiked), }; }; diff --git a/src/test/articleController.test.ts b/src/test/articleController.test.ts index cce246d..cbd3794 100644 --- a/src/test/articleController.test.ts +++ b/src/test/articleController.test.ts @@ -100,13 +100,26 @@ describe("게시글 컨트롤러", () => { const { req, res, next } = setup(); req.params = { id: "1" }; + const mockArticle = { + id: "1", + title: "새로운 게시글", + content: "새로운 게시글 내용", + createdAt: new Date(), + updatedAt: new Date(), + likeCount: 0, + writer: "김판다", + userId: 1, + images: ["image1.jpg"], + isLiked: false, + }; + (articleService.getArticleById as jest.MockedFunction).mockResolvedValue( mockArticle ); await articleController.getArticleById(req, res, next); - expect(articleService.getArticleById).toHaveBeenCalledWith("1"); + expect(articleService.getArticleById).toHaveBeenCalledWith("1",req.user?._id); expect(res.send).toHaveBeenCalledWith(mockArticle); }); diff --git a/src/test/articleService.test.ts b/src/test/articleService.test.ts index 1f6d175..42f6660 100644 --- a/src/test/articleService.test.ts +++ b/src/test/articleService.test.ts @@ -103,9 +103,9 @@ describe("게시글 서비스", () => { select: { id: true, title: true, - likeCount: true, content: true, createdAt: true, + likeCount: true, writer: true, images: { select: { imagePath: true }, @@ -187,6 +187,7 @@ describe("게시글 서비스", () => { expect(result).toEqual({ ...mockArticle, images: mockArticle.images.map((image) => image.imagePath), + isLiked: false, }); expect(prisma.article.findUniqueOrThrow).toHaveBeenCalledWith({ where: { id: "test-article-id" }, diff --git a/src/test/productController.test.ts b/src/test/productController.test.ts index 0b500cc..9b8a07b 100644 --- a/src/test/productController.test.ts +++ b/src/test/productController.test.ts @@ -138,6 +138,7 @@ describe("상품 컨트롤러", () => { tags: [], userId: 1, images: ["image1.jpg"], + isLiked: false }; (productService.getProductById as jest.MockedFunction).mockResolvedValue( @@ -146,7 +147,7 @@ describe("상품 컨트롤러", () => { await productController.getProductById(req, res, next); - expect(productService.getProductById).toHaveBeenCalledWith("1"); + expect(productService.getProductById).toHaveBeenCalledWith("1",req.user?._id); expect(res.send).toHaveBeenCalledWith(mockProduct); }); }); diff --git a/src/test/productService.test.ts b/src/test/productService.test.ts index 27f881d..fc0daf2 100644 --- a/src/test/productService.test.ts +++ b/src/test/productService.test.ts @@ -221,6 +221,7 @@ describe("상품 서비스", () => { expect(result).toEqual({ ...mockProduct, images: ["image1.jpg"], + isLiked:false }); expect(prisma.product.findUnique).toHaveBeenCalledWith({ where: { id: "test-product-id" },