From e62342e016502bb400f4827fc9d44defd264a2a4 Mon Sep 17 00:00:00 2001 From: AzizbekFayziyev Date: Tue, 1 Jul 2025 21:07:46 +0500 Subject: [PATCH] finish --- .eslintignore | 1 + .eslintrc.json | 61 + .gitignore | 33 + .husky/pre-commit | 3 + .prettierignore | 8 + .sequelizerc | 5 + README.md | 38 + config/config.cjs | 16 + jsconfig.json | 8 + nodemon.json | 6 + package-lock.json | 9849 +++++++++++++++++ package.json | 58 + prettier.config.cjs | 12 + public/currencies/all.svg | 11 + public/currencies/btc.svg | 11 + public/currencies/cad.svg | 11 + public/currencies/ct.svg | 12 + public/currencies/eur.svg | 11 + public/currencies/firo.svg | 12 + public/currencies/jpy.svg | 11 + public/currencies/trade_tsds.svg | 12 + public/currencies/trade_wbtc.svg | 3 + public/currencies/trade_weth.svg | 15 + public/currencies/trade_zano.svg | 4 + public/currencies/tsds.svg | 12 + public/currencies/usd.svg | 11 + public/currencies/wbtc.svg | 11 + public/currencies/weth.svg | 16 + public/currencies/xmr.svg | 12 + public/currencies/zano.svg | 41 + public/favicon.ico | Bin 0 -> 197309 bytes public/social-banner.png | Bin 0 -> 122782 bytes public/ui/featured.svg | 16 + public/ui/whitelisted.svg | 11 + shared/utils.ts | 91 + src/controllers/auth.controller.ts | 52 + src/controllers/chats.controller.ts | 144 + src/controllers/config.controller.ts | 18 + src/controllers/dex.controller.ts | 205 + src/controllers/offers.controller.ts | 118 + src/controllers/orders.controller.ts | 246 + src/controllers/process.controller.ts | 67 + src/controllers/transactions.controller.ts | 75 + src/controllers/user.controller.ts | 98 + src/database.ts | 29 + src/interfaces/bodies/chats/CreateBody.ts | 12 + .../bodies/chats/CreateMessageBody.ts | 10 + src/interfaces/bodies/chats/DeleteChatBody.ts | 8 + .../bodies/chats/GetAllChatsBody.ts | 7 + src/interfaces/bodies/chats/GetChatBody.ts | 9 + .../ConfirmTransactionBody.ts | 8 + .../GetActiveTxByOrdersIdsBody.ts | 7 + src/interfaces/bodies/offers/DeleteBody.ts | 10 + src/interfaces/bodies/offers/GetPageBody.ts | 18 + src/interfaces/bodies/offers/UpdateBody.ts | 23 + .../bodies/orders/ApplyOrderBody.ts | 14 + .../bodies/orders/CancelOrderBody.ts | 8 + .../bodies/orders/CreateOrderBody.ts | 18 + .../bodies/orders/GetCandlesBody.ts | 8 + .../bodies/orders/GetChartOrdersBody.ts | 5 + .../bodies/orders/GetUserOrdersBody.ts | 7 + .../bodies/orders/GetUserOrdersPageBody.ts | 8 + src/interfaces/bodies/user/AuthData.ts | 6 + src/interfaces/bodies/user/GetUserBody.ts | 5 + .../bodies/user/SetFavouriteCurrsBody.ts | 8 + src/interfaces/common/Candle.ts | 9 + src/interfaces/common/CurrecnyType.ts | 3 + src/interfaces/common/Message.ts | 12 + src/interfaces/common/OfferType.ts | 3 + src/interfaces/common/PairStats.ts | 7 + src/interfaces/common/Period.ts | 3 + src/interfaces/common/Side.ts | 3 + src/interfaces/common/UserData.ts | 8 + src/interfaces/database/CandleRow.ts | 11 + src/interfaces/database/ChatRow.ts | 18 + src/interfaces/database/CurrencyRow.ts | 11 + src/interfaces/database/ExchangeRow.ts | 12 + src/interfaces/database/MessagesRow.ts | 13 + src/interfaces/database/OfferRow.ts | 21 + src/interfaces/database/OrderRow.ts | 17 + src/interfaces/database/TradingPairRow.ts | 7 + src/interfaces/database/UserRow.ts | 8 + src/interfaces/enum/pair.ts | 5 + src/interfaces/responses/ErrorResponse.ts | 6 + src/interfaces/responses/chats/chats.ts | 47 + src/interfaces/responses/config/config.ts | 10 + .../responses/offers/GetStatsRes.ts | 11 + src/interfaces/responses/orders/ApplyTip.ts | 17 + .../responses/orders/GetPairStatsRes.ts | 16 + .../special/socket-data/AuthorizedData.ts | 8 + .../special/socket-data/ChatSocketData.ts | 8 + .../special/socket-data/DepositSocketData.ts | 7 + .../special/socket-data/MessageSocketData.ts | 8 + .../special/socket-data/OrderData.ts | 21 + .../special/socket-data/SocketData.ts | 5 + .../special/socket-data/UserSocketData.ts | 5 + src/methods/validateWallet.ts | 50 + src/middleware/middleware.ts | 41 + src/middleware/socket.ts | 65 + src/models/Candles.ts | 179 + src/models/Chats.ts | 450 + src/models/Config.ts | 36 + src/models/Dex.ts | 301 + src/models/ExchangeTransactions.ts | 295 + src/models/Offers.ts | 299 + src/models/Orders.ts | 580 + src/models/User.ts | 190 + src/routes/admin.router.ts | 103 + src/routes/auth.router.ts | 8 + src/routes/chats.router.ts | 23 + src/routes/config.router.ts | 8 + src/routes/dex.router.ts | 15 + src/routes/offers.router.ts | 14 + src/routes/orders.router.ts | 28 + src/routes/transactions.router.ts | 15 + src/routes/user.router.ts | 12 + src/schemes/Chat.ts | 86 + src/schemes/Currency.ts | 112 + src/schemes/Message.ts | 77 + src/schemes/Offer.ts | 118 + src/schemes/Order.ts | 119 + src/schemes/Pair.ts | 69 + src/schemes/Transaction.ts | 65 + src/schemes/User.ts | 79 + src/sequelize.ts | 13 + src/server.ts | 94 + src/socket/main.ts | 180 + src/workers/assetsUpdateChecker.ts | 138 + tsconfig.json | 109 + 129 files changed, 15994 insertions(+) create mode 100644 .eslintignore create mode 100644 .eslintrc.json create mode 100644 .gitignore create mode 100644 .husky/pre-commit create mode 100644 .prettierignore create mode 100644 .sequelizerc create mode 100644 README.md create mode 100644 config/config.cjs create mode 100644 jsconfig.json create mode 100644 nodemon.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 prettier.config.cjs create mode 100644 public/currencies/all.svg create mode 100644 public/currencies/btc.svg create mode 100644 public/currencies/cad.svg create mode 100644 public/currencies/ct.svg create mode 100644 public/currencies/eur.svg create mode 100644 public/currencies/firo.svg create mode 100644 public/currencies/jpy.svg create mode 100644 public/currencies/trade_tsds.svg create mode 100644 public/currencies/trade_wbtc.svg create mode 100644 public/currencies/trade_weth.svg create mode 100644 public/currencies/trade_zano.svg create mode 100644 public/currencies/tsds.svg create mode 100644 public/currencies/usd.svg create mode 100644 public/currencies/wbtc.svg create mode 100644 public/currencies/weth.svg create mode 100644 public/currencies/xmr.svg create mode 100644 public/currencies/zano.svg create mode 100644 public/favicon.ico create mode 100644 public/social-banner.png create mode 100644 public/ui/featured.svg create mode 100644 public/ui/whitelisted.svg create mode 100644 shared/utils.ts create mode 100644 src/controllers/auth.controller.ts create mode 100644 src/controllers/chats.controller.ts create mode 100644 src/controllers/config.controller.ts create mode 100644 src/controllers/dex.controller.ts create mode 100644 src/controllers/offers.controller.ts create mode 100644 src/controllers/orders.controller.ts create mode 100644 src/controllers/process.controller.ts create mode 100644 src/controllers/transactions.controller.ts create mode 100644 src/controllers/user.controller.ts create mode 100644 src/database.ts create mode 100644 src/interfaces/bodies/chats/CreateBody.ts create mode 100644 src/interfaces/bodies/chats/CreateMessageBody.ts create mode 100644 src/interfaces/bodies/chats/DeleteChatBody.ts create mode 100644 src/interfaces/bodies/chats/GetAllChatsBody.ts create mode 100644 src/interfaces/bodies/chats/GetChatBody.ts create mode 100644 src/interfaces/bodies/exchange-transactions/ConfirmTransactionBody.ts create mode 100644 src/interfaces/bodies/exchange-transactions/GetActiveTxByOrdersIdsBody.ts create mode 100644 src/interfaces/bodies/offers/DeleteBody.ts create mode 100644 src/interfaces/bodies/offers/GetPageBody.ts create mode 100644 src/interfaces/bodies/offers/UpdateBody.ts create mode 100644 src/interfaces/bodies/orders/ApplyOrderBody.ts create mode 100644 src/interfaces/bodies/orders/CancelOrderBody.ts create mode 100644 src/interfaces/bodies/orders/CreateOrderBody.ts create mode 100644 src/interfaces/bodies/orders/GetCandlesBody.ts create mode 100644 src/interfaces/bodies/orders/GetChartOrdersBody.ts create mode 100644 src/interfaces/bodies/orders/GetUserOrdersBody.ts create mode 100644 src/interfaces/bodies/orders/GetUserOrdersPageBody.ts create mode 100644 src/interfaces/bodies/user/AuthData.ts create mode 100644 src/interfaces/bodies/user/GetUserBody.ts create mode 100644 src/interfaces/bodies/user/SetFavouriteCurrsBody.ts create mode 100644 src/interfaces/common/Candle.ts create mode 100644 src/interfaces/common/CurrecnyType.ts create mode 100644 src/interfaces/common/Message.ts create mode 100644 src/interfaces/common/OfferType.ts create mode 100644 src/interfaces/common/PairStats.ts create mode 100644 src/interfaces/common/Period.ts create mode 100644 src/interfaces/common/Side.ts create mode 100644 src/interfaces/common/UserData.ts create mode 100644 src/interfaces/database/CandleRow.ts create mode 100644 src/interfaces/database/ChatRow.ts create mode 100644 src/interfaces/database/CurrencyRow.ts create mode 100644 src/interfaces/database/ExchangeRow.ts create mode 100644 src/interfaces/database/MessagesRow.ts create mode 100644 src/interfaces/database/OfferRow.ts create mode 100644 src/interfaces/database/OrderRow.ts create mode 100644 src/interfaces/database/TradingPairRow.ts create mode 100644 src/interfaces/database/UserRow.ts create mode 100644 src/interfaces/enum/pair.ts create mode 100644 src/interfaces/responses/ErrorResponse.ts create mode 100644 src/interfaces/responses/chats/chats.ts create mode 100644 src/interfaces/responses/config/config.ts create mode 100644 src/interfaces/responses/offers/GetStatsRes.ts create mode 100644 src/interfaces/responses/orders/ApplyTip.ts create mode 100644 src/interfaces/responses/orders/GetPairStatsRes.ts create mode 100644 src/interfaces/special/socket-data/AuthorizedData.ts create mode 100644 src/interfaces/special/socket-data/ChatSocketData.ts create mode 100644 src/interfaces/special/socket-data/DepositSocketData.ts create mode 100644 src/interfaces/special/socket-data/MessageSocketData.ts create mode 100644 src/interfaces/special/socket-data/OrderData.ts create mode 100644 src/interfaces/special/socket-data/SocketData.ts create mode 100644 src/interfaces/special/socket-data/UserSocketData.ts create mode 100644 src/methods/validateWallet.ts create mode 100644 src/middleware/middleware.ts create mode 100644 src/middleware/socket.ts create mode 100644 src/models/Candles.ts create mode 100644 src/models/Chats.ts create mode 100644 src/models/Config.ts create mode 100644 src/models/Dex.ts create mode 100644 src/models/ExchangeTransactions.ts create mode 100644 src/models/Offers.ts create mode 100644 src/models/Orders.ts create mode 100644 src/models/User.ts create mode 100644 src/routes/admin.router.ts create mode 100644 src/routes/auth.router.ts create mode 100644 src/routes/chats.router.ts create mode 100644 src/routes/config.router.ts create mode 100644 src/routes/dex.router.ts create mode 100644 src/routes/offers.router.ts create mode 100644 src/routes/orders.router.ts create mode 100644 src/routes/transactions.router.ts create mode 100644 src/routes/user.router.ts create mode 100644 src/schemes/Chat.ts create mode 100644 src/schemes/Currency.ts create mode 100644 src/schemes/Message.ts create mode 100644 src/schemes/Offer.ts create mode 100644 src/schemes/Order.ts create mode 100644 src/schemes/Pair.ts create mode 100644 src/schemes/Transaction.ts create mode 100644 src/schemes/User.ts create mode 100644 src/sequelize.ts create mode 100644 src/server.ts create mode 100644 src/socket/main.ts create mode 100644 src/workers/assetsUpdateChecker.ts create mode 100644 tsconfig.json diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..5efe132 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +submodules/ \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..dffaf9c --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,61 @@ +{ + "env": { + "es2021": true, + "node": true + }, + "extends": [ + "airbnb-base", + "plugin:@typescript-eslint/recommended", + "next/core-web-vitals", + "prettier" + ], + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint", "import"], + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module", + "project": "./tsconfig.json" + }, + "rules": { + "no-console": "off", + "no-void": "off", + "import/extensions": "off", + "no-unused-vars": [ + "warn", + { + "argsIgnorePattern": "^_" + } + ], + "func-names": "off", + "consistent-return": "off", + "no-restricted-syntax": "off", + "@typescript-eslint/indent": ["error", "tab"], + "class-methods-use-this": "off", + "@typescript-eslint/no-unused-vars": [ + "warn", + { + "argsIgnorePattern": "^_" + } + ], + "@typescript-eslint/explicit-member-accessibility": "off", + "@typescript-eslint/no-explicit-any": "error", + "lines-between-class-members": "off", + "camelcase": "off", + "no-underscore-dangle": "off", + "no-shadow": "off", + "no-await-in-loop": "off", + "radix": "off", + "no-plusplus": "off", + "no-promise-executor-return": "off", + "import/no-duplicates": "off", + "import/prefer-default-export": "off", + "import/no-cycle": "off" + }, + "settings": { + "import/resolver": { + "node": { + "extensions": [".js", ".ts"] + } + } + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..56f72c6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# local env files +.env*.local +.env + +# vercel +.vercel diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..210877e --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,3 @@ +#!/bin/sh + +npx lint-staged \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..c5bfd5b --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +node_modules +build +dist +coverage +.next +.env +*.lock +submodules/ \ No newline at end of file diff --git a/.sequelizerc b/.sequelizerc new file mode 100644 index 0000000..500594b --- /dev/null +++ b/.sequelizerc @@ -0,0 +1,5 @@ +const path = require('path'); + +module.exports = { + 'config': path.resolve('config', 'config.cjs'), +}; \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ca8a3a2 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. + +[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. + +The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. + +This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/config/config.cjs b/config/config.cjs new file mode 100644 index 0000000..4e5a54d --- /dev/null +++ b/config/config.cjs @@ -0,0 +1,16 @@ +require('dotenv').config(); + +let config = { + username: process.env.PGUSER, + password: process.env.PGPASSWORD, + database: process.env.PGDATABASE, + host: process.env.PGHOST, + port: process.env.PGPORT, + dialect: 'postgres', +}; + +module.exports = { + development: config, + test: config, + production: config, +}; diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..b05513b --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/nodemon.json b/nodemon.json new file mode 100644 index 0000000..4bdcc4b --- /dev/null +++ b/nodemon.json @@ -0,0 +1,6 @@ +{ + "verbose": true, + "ignore": ["node_modules", ".next"], + "watch": ["src/**/*", "server.js"], + "ext": "js json ts tsx" +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..226717b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,9849 @@ +{ + "name": "zano-trade-backend", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "zano-trade-backend", + "version": "0.1.0", + "dependencies": { + "axios": "^1.4.0", + "big.js": "^6.2.1", + "crypto-js": "^4.1.1", + "decimal.js": "^10.4.3", + "dotenv": "^16.0.3", + "express": "^4.18.2", + "jimp": "^0.22.8", + "jsonwebtoken": "^9.0.0", + "nanoid": "^4.0.1", + "node-fetch": "^3.3.1", + "nodemon": "^2.0.22", + "pg": "^8.10.0", + "sequelize": "^6.37.3", + "sha256": "^0.2.0", + "socket.io": "^4.6.1", + "sqlite3": "^5.1.7", + "ts-node": "^10.9.1", + "tsx": "^4.15.7", + "uuidv4": "^6.2.13" + }, + "devDependencies": { + "@types/big.js": "^6.2.0", + "@types/crypto-js": "^4.1.1", + "@types/express": "^4.17.17", + "@types/jsonwebtoken": "^9.0.2", + "@types/pg": "^8.10.2", + "@types/sha256": "^0.2.0", + "@typescript-eslint/eslint-plugin": "^5.55.0", + "cross-env": "^7.0.3", + "eslint": "^8.57.1", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-config-prettier": "^10.1.5", + "eslint-plugin-import": "^2.31.0", + "husky": "^9.1.7", + "lint-staged": "^15.5.2", + "prettier": "3.5.3", + "sequelize-cli": "^6.6.2" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT", + "optional": true + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@jimp/bmp": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.22.12.tgz", + "integrity": "sha512-aeI64HD0npropd+AR76MCcvvRaa+Qck6loCOS03CkkxGHN5/r336qTM5HPUdHKMDOGzqknuVPA8+kK1t03z12g==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12", + "bmp-js": "^0.1.0" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/core": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.22.12.tgz", + "integrity": "sha512-l0RR0dOPyzMKfjUW1uebzueFEDtCOj9fN6pyTYWWOM/VS4BciXQ1VVrJs8pO3kycGYZxncRKhCoygbNr8eEZQA==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12", + "any-base": "^1.1.0", + "buffer": "^5.2.0", + "exif-parser": "^0.1.12", + "file-type": "^16.5.4", + "isomorphic-fetch": "^3.0.0", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.6.0" + } + }, + "node_modules/@jimp/custom": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.22.12.tgz", + "integrity": "sha512-xcmww1O/JFP2MrlGUMd3Q78S3Qu6W3mYTXYuIqFq33EorgYHV/HqymHfXy9GjiCJ7OI+7lWx6nYFOzU7M4rd1Q==", + "license": "MIT", + "dependencies": { + "@jimp/core": "^0.22.12" + } + }, + "node_modules/@jimp/gif": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.22.12.tgz", + "integrity": "sha512-y6BFTJgch9mbor2H234VSjd9iwAhaNf/t3US5qpYIs0TSbAvM02Fbc28IaDETj9+4YB4676sz4RcN/zwhfu1pg==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12", + "gifwrap": "^0.10.1", + "omggif": "^1.0.9" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/jpeg": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.22.12.tgz", + "integrity": "sha512-Rq26XC/uQWaQKyb/5lksCTCxXhtY01NJeBN+dQv5yNYedN0i7iYu+fXEoRsfaJ8xZzjoANH8sns7rVP4GE7d/Q==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12", + "jpeg-js": "^0.4.4" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-blit": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.22.12.tgz", + "integrity": "sha512-xslz2ZoFZOPLY8EZ4dC29m168BtDx95D6K80TzgUi8gqT7LY6CsajWO0FAxDwHz6h0eomHMfyGX0stspBrTKnQ==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-blur": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.22.12.tgz", + "integrity": "sha512-S0vJADTuh1Q9F+cXAwFPlrKWzDj2F9t/9JAbUvaaDuivpyWuImEKXVz5PUZw2NbpuSHjwssbTpOZ8F13iJX4uw==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-circle": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.22.12.tgz", + "integrity": "sha512-SWVXx1yiuj5jZtMijqUfvVOJBwOifFn0918ou4ftoHgegc5aHWW5dZbYPjvC9fLpvz7oSlptNl2Sxr1zwofjTg==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-color": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.22.12.tgz", + "integrity": "sha512-xImhTE5BpS8xa+mAN6j4sMRWaUgUDLoaGHhJhpC+r7SKKErYDR0WQV4yCE4gP+N0gozD0F3Ka1LUSaMXrn7ZIA==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12", + "tinycolor2": "^1.6.0" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-contain": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.22.12.tgz", + "integrity": "sha512-Eo3DmfixJw3N79lWk8q/0SDYbqmKt1xSTJ69yy8XLYQj9svoBbyRpSnHR+n9hOw5pKXytHwUW6nU4u1wegHNoQ==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5", + "@jimp/plugin-scale": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-cover": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.22.12.tgz", + "integrity": "sha512-z0w/1xH/v/knZkpTNx+E8a7fnasQ2wHG5ze6y5oL2dhH1UufNua8gLQXlv8/W56+4nJ1brhSd233HBJCo01BXA==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-crop": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5", + "@jimp/plugin-scale": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-crop": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.22.12.tgz", + "integrity": "sha512-FNuUN0OVzRCozx8XSgP9MyLGMxNHHJMFt+LJuFjn1mu3k0VQxrzqbN06yIl46TVejhyAhcq5gLzqmSCHvlcBVw==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-displace": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.22.12.tgz", + "integrity": "sha512-qpRM8JRicxfK6aPPqKZA6+GzBwUIitiHaZw0QrJ64Ygd3+AsTc7BXr+37k2x7QcyCvmKXY4haUrSIsBug4S3CA==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-dither": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.22.12.tgz", + "integrity": "sha512-jYgGdSdSKl1UUEanX8A85v4+QUm+PE8vHFwlamaKk89s+PXQe7eVE3eNeSZX4inCq63EHL7cX580dMqkoC3ZLw==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-fisheye": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.22.12.tgz", + "integrity": "sha512-LGuUTsFg+fOp6KBKrmLkX4LfyCy8IIsROwoUvsUPKzutSqMJnsm3JGDW2eOmWIS/jJpPaeaishjlxvczjgII+Q==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-flip": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.22.12.tgz", + "integrity": "sha512-m251Rop7GN8W0Yo/rF9LWk6kNclngyjIJs/VXHToGQ6EGveOSTSQaX2Isi9f9lCDLxt+inBIb7nlaLLxnvHX8Q==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-rotate": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-gaussian": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.22.12.tgz", + "integrity": "sha512-sBfbzoOmJ6FczfG2PquiK84NtVGeScw97JsCC3rpQv1PHVWyW+uqWFF53+n3c8Y0P2HWlUjflEla2h/vWShvhg==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-invert": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.22.12.tgz", + "integrity": "sha512-N+6rwxdB+7OCR6PYijaA/iizXXodpxOGvT/smd/lxeXsZ/empHmFFFJ/FaXcYh19Tm04dGDaXcNF/dN5nm6+xQ==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-mask": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.22.12.tgz", + "integrity": "sha512-4AWZg+DomtpUA099jRV8IEZUfn1wLv6+nem4NRJC7L/82vxzLCgXKTxvNvBcNmJjT9yS1LAAmiJGdWKXG63/NA==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-normalize": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.22.12.tgz", + "integrity": "sha512-0So0rexQivnWgnhacX4cfkM2223YdExnJTTy6d06WbkfZk5alHUx8MM3yEzwoCN0ErO7oyqEWRnEkGC+As1FtA==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-print": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.22.12.tgz", + "integrity": "sha512-c7TnhHlxm87DJeSnwr/XOLjJU/whoiKYY7r21SbuJ5nuH+7a78EW1teOaj5gEr2wYEd7QtkFqGlmyGXY/YclyQ==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12", + "load-bmfont": "^1.4.1" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-resize": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.22.12.tgz", + "integrity": "sha512-3NyTPlPbTnGKDIbaBgQ3HbE6wXbAlFfxHVERmrbqAi8R3r6fQPxpCauA8UVDnieg5eo04D0T8nnnNIX//i/sXg==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-rotate": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.22.12.tgz", + "integrity": "sha512-9YNEt7BPAFfTls2FGfKBVgwwLUuKqy+E8bDGGEsOqHtbuhbshVGxN2WMZaD4gh5IDWvR+emmmPPWGgaYNYt1gA==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5", + "@jimp/plugin-crop": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-scale": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.22.12.tgz", + "integrity": "sha512-dghs92qM6MhHj0HrV2qAwKPMklQtjNpoYgAB94ysYpsXslhRTiPisueSIELRwZGEr0J0VUxpUY7HgJwlSIgGZw==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-shadow": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.22.12.tgz", + "integrity": "sha512-FX8mTJuCt7/3zXVoeD/qHlm4YH2bVqBuWQHXSuBK054e7wFRnRnbSLPUqAwSeYP3lWqpuQzJtgiiBxV3+WWwTg==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blur": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-threshold": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.22.12.tgz", + "integrity": "sha512-4x5GrQr1a/9L0paBC/MZZJjjgjxLYrqSmWd+e+QfAEPvmRxdRoQ5uKEuNgXnm9/weHQBTnQBQsOY2iFja+XGAw==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-color": ">=0.8.0", + "@jimp/plugin-resize": ">=0.8.0" + } + }, + "node_modules/@jimp/plugins": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.22.12.tgz", + "integrity": "sha512-yBJ8vQrDkBbTgQZLty9k4+KtUQdRjsIDJSPjuI21YdVeqZxYywifHl4/XWILoTZsjTUASQcGoH0TuC0N7xm3ww==", + "license": "MIT", + "dependencies": { + "@jimp/plugin-blit": "^0.22.12", + "@jimp/plugin-blur": "^0.22.12", + "@jimp/plugin-circle": "^0.22.12", + "@jimp/plugin-color": "^0.22.12", + "@jimp/plugin-contain": "^0.22.12", + "@jimp/plugin-cover": "^0.22.12", + "@jimp/plugin-crop": "^0.22.12", + "@jimp/plugin-displace": "^0.22.12", + "@jimp/plugin-dither": "^0.22.12", + "@jimp/plugin-fisheye": "^0.22.12", + "@jimp/plugin-flip": "^0.22.12", + "@jimp/plugin-gaussian": "^0.22.12", + "@jimp/plugin-invert": "^0.22.12", + "@jimp/plugin-mask": "^0.22.12", + "@jimp/plugin-normalize": "^0.22.12", + "@jimp/plugin-print": "^0.22.12", + "@jimp/plugin-resize": "^0.22.12", + "@jimp/plugin-rotate": "^0.22.12", + "@jimp/plugin-scale": "^0.22.12", + "@jimp/plugin-shadow": "^0.22.12", + "@jimp/plugin-threshold": "^0.22.12", + "timm": "^1.6.1" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/png": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.22.12.tgz", + "integrity": "sha512-Mrp6dr3UTn+aLK8ty/dSKELz+Otdz1v4aAXzV5q53UDD2rbB5joKVJ/ChY310B+eRzNxIovbUF1KVrUsYdE8Hg==", + "license": "MIT", + "dependencies": { + "@jimp/utils": "^0.22.12", + "pngjs": "^6.0.0" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/tiff": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.22.12.tgz", + "integrity": "sha512-E1LtMh4RyJsoCAfAkBRVSYyZDTtLq9p9LUiiYP0vPtXyxX4BiYBUYihTLSBlCQg5nF2e4OpQg7SPrLdJ66u7jg==", + "license": "MIT", + "dependencies": { + "utif2": "^4.0.1" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/types": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.22.12.tgz", + "integrity": "sha512-wwKYzRdElE1MBXFREvCto5s699izFHNVvALUv79GXNbsOVqlwlOxlWJ8DuyOGIXoLP4JW/m30YyuTtfUJgMRMA==", + "license": "MIT", + "dependencies": { + "@jimp/bmp": "^0.22.12", + "@jimp/gif": "^0.22.12", + "@jimp/jpeg": "^0.22.12", + "@jimp/png": "^0.22.12", + "@jimp/tiff": "^0.22.12", + "timm": "^1.6.1" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/utils": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", + "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.13.3" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.3.tgz", + "integrity": "sha512-AiR5uKpFxP3PjO4R19kQGIMwxyRyPuXmKEEy301V1C0+1rVjS94EZQXf1QKZYN8Q0YM+estSPhmx5JwNftv6nw==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "license": "MIT" + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "license": "MIT" + }, + "node_modules/@types/big.js": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@types/big.js/-/big.js-6.2.2.tgz", + "integrity": "sha512-e2cOW9YlVzFY2iScnGBBkplKsrn2CsObHQ2Hiw4V1sSyiGbgWL8IyqE3zFi1Pt5o1pdAtYkDAIsF3KKUPjdzaA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/crypto-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz", + "integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz", + "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", + "dev": true, + "license": "MIT", + "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.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.0.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.8.tgz", + "integrity": "sha512-WytNrFSgWO/esSH9NbpWUfTMGQwCGIKfCmNlmFDNiI5gGhgMmEA+V1AEvKLeBNvvtBnailJtkrEa2OIISwrVAA==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.8.0" + } + }, + "node_modules/@types/pg": { + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.4.tgz", + "integrity": "sha512-I6UNVBAoYbvuWkkU3oosC8yxqH21f4/Jc4DK71JLG3dT2mdlGe1z+ep/LQGXaKaOgcvUrsQoPRqfgtMcvZiJhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" + } + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/semver": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sha256": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@types/sha256/-/sha256-0.2.2.tgz", + "integrity": "sha512-uKMaDzyzfcDYGEwTgLh+hmgDMxXWyIVodY8T+qt7A+NYvikW0lmGLMGbQ7BipCB8dzXHa55C9g+Ii/3Lgt1KmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", + "license": "MIT" + }, + "node_modules/@types/validator": { + "version": "13.15.2", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.2.tgz", + "integrity": "sha512-y7pa/oEJJ4iGYBxOpfAKn5b9+xuihvzDVnC/OSvlVnGxVg0pOqmjiMafiJ1KVNQEaPZf9HsEp5icEwGg8uIe5Q==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "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==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "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==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==", + "license": "MIT" + }, + "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==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "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==", + "license": "ISC", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/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==", + "license": "MIT", + "optional": true, + "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==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/big.js": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-6.2.2.tgz", + "integrity": "sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==", + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/bigjs" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "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.13.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==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/centra": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/centra/-/centra-2.7.0.tgz", + "integrity": "sha512-PbFMgMSrmgx6uxCdm57RUos9Tc3fclMvhLSATYN39XsDV29B89zZ3KA89jmY0vwSGazyU+uerqwa6t+KaodPcg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/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==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/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==", + "license": "ISC", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true, + "license": "MIT" + }, + "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==", + "license": "ISC", + "optional": 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==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-hex": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/convert-hex/-/convert-hex-0.1.0.tgz", + "integrity": "sha512-w20BOb1PiR/sEJdS6wNrUjF5CSfscZFUp7R9NSlXH8h2wynzXVEPFPJECAnkNylZ+cvf3p7TyRUHggDmrwXT9A==" + }, + "node_modules/convert-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/convert-string/-/convert-string-0.1.0.tgz", + "integrity": "sha512-1KX9ESmtl8xpT2LN2tFnKSbV4NiarbVi8DVb39ZriijvtTklyrT+4dT1wsGMHKD3CJUjXgvJzstm9qL9ICojGA==" + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "license": "MIT" + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "license": "MIT" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", + "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", + "license": "MIT" + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT", + "optional": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "license": "Apache-2.0", + "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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dottie": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", + "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==", + "license": "MIT" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/editorconfig/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", + "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", + "license": "MIT", + "dependencies": { + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.7.2", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT", + "optional": true + }, + "node_modules/es-abstract": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dev": true, + "license": "MIT", + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" + } + }, + "node_modules/eslint-config-airbnb-base/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz", + "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true, + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==" + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-type": { + "version": "16.5.4", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", + "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", + "license": "MIT", + "dependencies": { + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.2.4", + "token-types": "^4.1.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "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==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "license": "ISC", + "dependencies": { + "minipass": "^3.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==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gauge/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==", + "license": "MIT", + "optional": true + }, + "node_modules/gauge/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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC", + "optional": true + }, + "node_modules/gauge/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==", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/gifwrap": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz", + "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==", + "license": "MIT", + "dependencies": { + "image-q": "^4.0.0", + "omggif": "^1.0.10" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "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", + "devOptional": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "license": "MIT", + "dependencies": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-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==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC", + "optional": true + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/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==", + "license": "ISC" + }, + "node_modules/image-q": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", + "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==", + "license": "MIT", + "dependencies": { + "@types/node": "16.9.1" + } + }, + "node_modules/image-q/node_modules/@types/node": { + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==", + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", + "optional": true + }, + "node_modules/inflection": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", + "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", + "engines": [ + "node >= 0.4.0" + ], + "license": "MIT" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "devOptional": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "license": "MIT", + "optional": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", + "license": "MIT" + }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT", + "optional": true + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/isomorphic-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, + "node_modules/isomorphic-fetch/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==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jimp": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.22.12.tgz", + "integrity": "sha512-R5jZaYDnfkxKJy1dwLpj/7cvyjxiclxU3F4TrI/J4j2rS0niq6YDUMoPn5hs8GDpO+OZGo7Ky057CRtWesyhfg==", + "license": "MIT", + "dependencies": { + "@jimp/custom": "^0.22.12", + "@jimp/plugins": "^0.22.12", + "@jimp/types": "^0.22.12", + "regenerator-runtime": "^0.13.3" + } + }, + "node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", + "license": "BSD-3-Clause" + }, + "node_modules/js-beautify": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz", + "integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.4", + "glob": "^10.4.2", + "js-cookie": "^3.0.5", + "nopt": "^7.2.1" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/js-beautify/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/js-beautify/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-beautify/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-beautify/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT", + "optional": true + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lint-staged": { + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.2.tgz", + "integrity": "sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.4.1", + "commander": "^13.1.0", + "debug": "^4.4.0", + "execa": "^8.0.1", + "lilconfig": "^3.1.3", + "listr2": "^8.2.5", + "micromatch": "^4.0.8", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.7.0" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/listr2": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", + "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/load-bmfont": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.2.tgz", + "integrity": "sha512-qElWkmjW9Oq1F9EI5Gt7aD9zcdHb9spJCW1L/dmPf7KzCCEJxq8nhHz5eCgI9aMf7vrG/wyaCqdsI+Iy9ZTlog==", + "license": "MIT", + "dependencies": { + "buffer-equal": "0.0.1", + "mime": "^1.3.4", + "parse-bmfont-ascii": "^1.0.3", + "parse-bmfont-binary": "^1.0.5", + "parse-bmfont-xml": "^1.1.4", + "phin": "^3.7.1", + "xhr": "^2.0.1", + "xtend": "^4.0.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "license": "ISC" + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "license": "ISC", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "dependencies": { + "dom-walk": "^0.1.0" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "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==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.48", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", + "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", + "license": "MIT", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz", + "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^14 || ^16 || >=18" + } + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.75.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz", + "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp/node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC", + "optional": true + }, + "node_modules/node-gyp/node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nodemon": { + "version": "2.0.22", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", + "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/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==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/nodemon/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==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nopt": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==", + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==", + "license": "MIT" + }, + "node_modules/parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==", + "license": "MIT" + }, + "node_modules/parse-bmfont-xml": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz", + "integrity": "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==", + "license": "MIT", + "dependencies": { + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.5.0" + } + }, + "node_modules/parse-headers": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.6.tgz", + "integrity": "sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==", + "license": "MIT" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/peek-readable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", + "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/pg": { + "version": "8.16.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz", + "integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==", + "license": "MIT", + "dependencies": { + "pg-connection-string": "^2.9.1", + "pg-pool": "^3.10.1", + "pg-protocol": "^1.10.3", + "pg-types": "2.2.0", + "pgpass": "1.0.5" + }, + "engines": { + "node": ">= 16.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.2.7" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.7.tgz", + "integrity": "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==", + "license": "MIT", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz", + "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz", + "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==", + "license": "MIT", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz", + "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/phin": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/phin/-/phin-3.7.1.tgz", + "integrity": "sha512-GEazpTWwTZaEQ9RhL7Nyz0WwqilbqgLahDM3D0hxWwmVDI52nXEybHqiN6/elwpkJBhcuj+WbBu+QfT0uhPGfQ==", + "license": "MIT", + "dependencies": { + "centra": "^2.7.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pixelmatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", + "integrity": "sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA==", + "license": "ISC", + "dependencies": { + "pngjs": "^3.0.0" + }, + "bin": { + "pixelmatch": "bin/pixelmatch" + } + }, + "node_modules/pixelmatch/node_modules/pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pngjs": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", + "license": "MIT", + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true, + "license": "ISC" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/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==", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "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/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readable-stream/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz", + "integrity": "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==", + "license": "MIT", + "dependencies": { + "readable-stream": "^4.7.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/retry-as-promised": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.1.1.tgz", + "integrity": "sha512-hMD7odLOt3LkTjcif8aRZqi/hybjpLNgSk5oF5FCowfCjok6LukpN2bDX7R5wDmbgBQFn7YoBxSagmtXHaJYJw==", + "license": "MIT" + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "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", + "devOptional": true, + "license": "ISC", + "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==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "license": "ISC" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "node_modules/send/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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/sequelize": { + "version": "6.37.7", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.7.tgz", + "integrity": "sha512-mCnh83zuz7kQxxJirtFD7q6Huy6liPanI67BSlbzSYgVNl5eXVdE2CN1FuAeZwG1SNpGsNRCV+bJAVVnykZAFA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/sequelize" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.1.8", + "@types/validator": "^13.7.17", + "debug": "^4.3.4", + "dottie": "^2.0.6", + "inflection": "^1.13.4", + "lodash": "^4.17.21", + "moment": "^2.29.4", + "moment-timezone": "^0.5.43", + "pg-connection-string": "^2.6.1", + "retry-as-promised": "^7.0.4", + "semver": "^7.5.4", + "sequelize-pool": "^7.1.0", + "toposort-class": "^1.0.1", + "uuid": "^8.3.2", + "validator": "^13.9.0", + "wkx": "^0.5.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependenciesMeta": { + "ibm_db": { + "optional": true + }, + "mariadb": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-hstore": { + "optional": true + }, + "snowflake-sdk": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/sequelize-cli": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.6.3.tgz", + "integrity": "sha512-1YYPrcSRt/bpMDDSKM5ubY1mnJ2TEwIaGZcqITw4hLtGtE64nIqaBnLtMvH8VKHg6FbWpXTiFNc2mS/BtQCXZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fs-extra": "^9.1.0", + "js-beautify": "1.15.4", + "lodash": "^4.17.21", + "picocolors": "^1.1.1", + "resolve": "^1.22.1", + "umzug": "^2.3.0", + "yargs": "^16.2.0" + }, + "bin": { + "sequelize": "lib/sequelize", + "sequelize-cli": "lib/sequelize" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sequelize-pool": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", + "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.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==", + "license": "ISC", + "optional": true + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/sha256": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/sha256/-/sha256-0.2.0.tgz", + "integrity": "sha512-kTWMJUaez5iiT9CcMv8jSq6kMhw3ST0uRdcIWl3D77s6AsLXNXRp3heeqqfu5+Dyfu4hwpQnMzhqHh8iNQxw0w==", + "dependencies": { + "convert-hex": "~0.1.0", + "convert-string": "~0.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-update-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "license": "MIT", + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socket.io": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.6.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "license": "MIT", + "dependencies": { + "debug": "~4.3.4", + "ws": "~8.17.1" + } + }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socks": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz", + "integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==", + "license": "MIT", + "optional": true, + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/sqlite3": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", + "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strtok3": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", + "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^4.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", + "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-fs": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", + "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/timm": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", + "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==", + "license": "MIT" + }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-types": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", + "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==", + "license": "MIT" + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "license": "ISC", + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsx": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.3.tgz", + "integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==", + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "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==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/umzug": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", + "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "^3.7.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", + "license": "MIT" + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utif2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz", + "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==", + "license": "MIT", + "dependencies": { + "pako": "^1.0.11" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/uuidv4": { + "version": "6.2.13", + "resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz", + "integrity": "sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT", + "dependencies": { + "@types/uuid": "8.3.4", + "uuid": "8.3.2" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/validator": { + "version": "13.15.15", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz", + "integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 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==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "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==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wide-align/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==", + "license": "MIT", + "optional": true + }, + "node_modules/wide-align/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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/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==", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xhr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", + "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", + "license": "MIT", + "dependencies": { + "global": "~4.4.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==", + "license": "MIT" + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..d87ce56 --- /dev/null +++ b/package.json @@ -0,0 +1,58 @@ +{ + "name": "zano-trade-backend", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "cross-env PORT=3000 nodemon --exec tsx ./src/server.ts", + "start": "cross-env NODE_ENV=production PORT=30289 tsx ./src/server.ts", + "format": "prettier --write .", + "format:check": "prettier --check .", + "prepare": "husky" + }, + "lint-staged": { + "*.ts": [ + "prettier --write", + "eslint --fix" + ] + }, + "dependencies": { + "axios": "^1.4.0", + "big.js": "^6.2.1", + "crypto-js": "^4.1.1", + "decimal.js": "^10.4.3", + "dotenv": "^16.0.3", + "express": "^4.18.2", + "jimp": "^0.22.8", + "jsonwebtoken": "^9.0.0", + "nanoid": "^4.0.1", + "node-fetch": "^3.3.1", + "nodemon": "^2.0.22", + "pg": "^8.10.0", + "sequelize": "^6.37.3", + "sha256": "^0.2.0", + "socket.io": "^4.6.1", + "sqlite3": "^5.1.7", + "ts-node": "^10.9.1", + "tsx": "^4.15.7", + "uuidv4": "^6.2.13" + }, + "devDependencies": { + "@types/big.js": "^6.2.0", + "@types/crypto-js": "^4.1.1", + "@types/express": "^4.17.17", + "@types/jsonwebtoken": "^9.0.2", + "@types/pg": "^8.10.2", + "@types/sha256": "^0.2.0", + "@typescript-eslint/eslint-plugin": "^5.55.0", + "cross-env": "^7.0.3", + "eslint": "^8.57.1", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-config-prettier": "^10.1.5", + "eslint-plugin-import": "^2.31.0", + "husky": "^9.1.7", + "lint-staged": "^15.5.2", + "prettier": "3.5.3", + "sequelize-cli": "^6.6.2" + } +} diff --git a/prettier.config.cjs b/prettier.config.cjs new file mode 100644 index 0000000..bc5d4b9 --- /dev/null +++ b/prettier.config.cjs @@ -0,0 +1,12 @@ +/** @type {import("prettier").Config} */ +module.exports = { + semi: true, + singleQuote: true, + trailingComma: 'all', + printWidth: 100, + tabWidth: 4, + useTabs: true, + bracketSpacing: true, + arrowParens: 'always', + endOfLine: 'lf', +}; diff --git a/public/currencies/all.svg b/public/currencies/all.svg new file mode 100644 index 0000000..c13720e --- /dev/null +++ b/public/currencies/all.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/currencies/btc.svg b/public/currencies/btc.svg new file mode 100644 index 0000000..b845627 --- /dev/null +++ b/public/currencies/btc.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/currencies/cad.svg b/public/currencies/cad.svg new file mode 100644 index 0000000..8c32e68 --- /dev/null +++ b/public/currencies/cad.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/currencies/ct.svg b/public/currencies/ct.svg new file mode 100644 index 0000000..2175fef --- /dev/null +++ b/public/currencies/ct.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/currencies/eur.svg b/public/currencies/eur.svg new file mode 100644 index 0000000..d92b0c5 --- /dev/null +++ b/public/currencies/eur.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/currencies/firo.svg b/public/currencies/firo.svg new file mode 100644 index 0000000..fcd6e62 --- /dev/null +++ b/public/currencies/firo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/currencies/jpy.svg b/public/currencies/jpy.svg new file mode 100644 index 0000000..98e67b3 --- /dev/null +++ b/public/currencies/jpy.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/currencies/trade_tsds.svg b/public/currencies/trade_tsds.svg new file mode 100644 index 0000000..f3fbf75 --- /dev/null +++ b/public/currencies/trade_tsds.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/currencies/trade_wbtc.svg b/public/currencies/trade_wbtc.svg new file mode 100644 index 0000000..d3f67aa --- /dev/null +++ b/public/currencies/trade_wbtc.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/currencies/trade_weth.svg b/public/currencies/trade_weth.svg new file mode 100644 index 0000000..18e2f20 --- /dev/null +++ b/public/currencies/trade_weth.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/public/currencies/trade_zano.svg b/public/currencies/trade_zano.svg new file mode 100644 index 0000000..162dbf6 --- /dev/null +++ b/public/currencies/trade_zano.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/currencies/tsds.svg b/public/currencies/tsds.svg new file mode 100644 index 0000000..2175fef --- /dev/null +++ b/public/currencies/tsds.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/currencies/usd.svg b/public/currencies/usd.svg new file mode 100644 index 0000000..8c32e68 --- /dev/null +++ b/public/currencies/usd.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/currencies/wbtc.svg b/public/currencies/wbtc.svg new file mode 100644 index 0000000..bd5bf8a --- /dev/null +++ b/public/currencies/wbtc.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/currencies/weth.svg b/public/currencies/weth.svg new file mode 100644 index 0000000..c40e78e --- /dev/null +++ b/public/currencies/weth.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/public/currencies/xmr.svg b/public/currencies/xmr.svg new file mode 100644 index 0000000..4a578b1 --- /dev/null +++ b/public/currencies/xmr.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/currencies/zano.svg b/public/currencies/zano.svg new file mode 100644 index 0000000..bdeb771 --- /dev/null +++ b/public/currencies/zano.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4ce2fbd9eec5a9120e7123c3ef1d550e165838ec GIT binary patch literal 197309 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

2A$4^UOHJ&ob5Oz1;prz~@s& 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� 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 g|!BMw~+#f2ZsOZo~4Yx4i?v8Q}-09 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 myn-2MbjY_Wr(`h|R&Z!3`p^D;vSLH`FyKKh&h literal 0 HcmV?d00001 diff --git a/public/ui/featured.svg b/public/ui/featured.svg new file mode 100644 index 0000000..ee0cd4e --- /dev/null +++ b/public/ui/featured.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/public/ui/whitelisted.svg b/public/ui/whitelisted.svg new file mode 100644 index 0000000..9a6e589 --- /dev/null +++ b/public/ui/whitelisted.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/shared/utils.ts b/shared/utils.ts new file mode 100644 index 0000000..d6f74c6 --- /dev/null +++ b/shared/utils.ts @@ -0,0 +1,91 @@ +import Decimal from 'decimal.js'; + +export function validateTokensInput(input: string | number, decimal_point = 12) { + let inputVal = input; + + if (typeof inputVal === 'number') { + inputVal = inputVal.toString(); + } + + if (inputVal === '') { + return { + valid: false, + error: 'Invalid input', + }; + } + + inputVal = inputVal.replace(/[^0-9.,]/g, ''); + + const MAX_NUMBER = new Decimal(2).pow(64).minus(1); + + if (decimal_point < 0 || decimal_point > 18) { + return { + valid: false, + error: 'Invalid decimal point', + }; + } + + const dotInput = inputVal.replace(/,/g, ''); + + const decimalDevider = new Decimal(10).pow(decimal_point); + + const maxAllowedNumber = MAX_NUMBER.div(decimalDevider); + + const minAllowedNumber = new Decimal(1).div(decimalDevider); + + const rounded = (() => { + if (dotInput.replace('.', '').length > 20) { + const decimalParts = dotInput.split('.'); + + if (decimalParts.length === 2 && decimalParts[1].length > 1) { + const beforeDotLength = decimalParts[0].length; + const roundedInput = new Decimal(dotInput).toFixed( + Math.max(20 - beforeDotLength, 0), + ); + + if (roundedInput.replace(/./g, '').length <= 20) { + return roundedInput; + } + } + + return false; + } + return dotInput; + })(); + + const decimalsAmount = dotInput.split('.')[1]?.length || 0; + + if (decimalsAmount > decimal_point) { + return { + valid: false, + error: 'Invalid amount - too many decimal points', + }; + } + + if (rounded === false) { + return { + valid: false, + error: 'Invalid amount - number is too big or has too many decimal points', + }; + } + + const dotInputDecimal = new Decimal(rounded); + + if (dotInputDecimal.gt(maxAllowedNumber)) { + return { + valid: false, + error: 'Invalid amount - number is too big', + }; + } + + if (dotInputDecimal.lt(minAllowedNumber)) { + return { + valid: false, + error: 'Invalid amount - number is too small', + }; + } + + return { + valid: true, + }; +} diff --git a/src/controllers/auth.controller.ts b/src/controllers/auth.controller.ts new file mode 100644 index 0000000..20dacc9 --- /dev/null +++ b/src/controllers/auth.controller.ts @@ -0,0 +1,52 @@ +import jwt from 'jsonwebtoken'; +import dotenv from 'dotenv'; +import { Request, Response } from 'express'; +import AuthData from '@/interfaces/bodies/user/AuthData.js'; +import validateWallet from '../methods/validateWallet.js'; +import userModel from '../models/User.js'; + +dotenv.config(); + +class AuthController { + async auth(req: Request, res: Response) { + try { + const userData: AuthData = req.body.data; + const { neverExpires } = req.body; + const { address, alias, signature, message } = userData; + + if (!address || !alias || !signature || !message) { + return res.status(400).send({ success: false, data: 'Invalid auth data' }); + } + + const dataValid = !!( + userData && + userData.address && + alias && + (await validateWallet(userData)) + ); + if (!dataValid) { + return res.status(400).send({ success: false, data: 'Invalid auth data' }); + } + + const success = await userModel.add(userData); + + if (success) { + const token = jwt.sign( + { ...userData }, + process.env.JWT_SECRET || '', + neverExpires ? undefined : { expiresIn: '24h' }, + ); + res.status(200).send({ success, data: token }); + } else { + res.status(500).send({ success, data: 'Internal error' }); + } + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } +} + +const authController = new AuthController(); + +export default authController; diff --git a/src/controllers/chats.controller.ts b/src/controllers/chats.controller.ts new file mode 100644 index 0000000..a3b0223 --- /dev/null +++ b/src/controllers/chats.controller.ts @@ -0,0 +1,144 @@ +import { Request, Response } from 'express'; +import chatsModel from '../models/Chats.js'; +import CreateBody from '../interfaces/bodies/chats/CreateBody.js'; +import GetChatBody from '../interfaces/bodies/chats/GetChatBody.js'; +import GetAllChatsBody from '../interfaces/bodies/chats/GetAllChatsBody.js'; +import DeleteChatBody from '../interfaces/bodies/chats/DeleteChatBody.js'; + +class ChatsController { + async create(req: Request, res: Response) { + try { + const { number } = req.body as CreateBody; + const { chatData } = req.body as CreateBody; + + const rangeAcceptable = + parseFloat(chatData.receive) >= 0 && + parseFloat(chatData.receive) <= 100000000000000000; + + if (!(number && chatData && chatData.pay && chatData.receive && rangeAcceptable)) + return res.status(400).send({ success: false, data: 'Invalid offer data' }); + + const result = await chatsModel.create(req.body as CreateBody); + + if (result.success) { + return res.status(200).send(result); + } + + if ( + result.data === 'Same user' || + result.data === 'Invalid offer data' || + result.data === 'User not registered' + ) { + return res.status(400).send(result); + } + + return res.status(500).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async getChat(req: Request, res: Response) { + try { + if (!(req.body as GetChatBody).id) + return res.status(400).send({ success: false, data: 'Invalid chat data' }); + + const result = await chatsModel.getChat(req.body as GetChatBody); + + if (result.success) { + return res.status(200).send(result); + } + + if (result.data === 'Unauthorized') { + return res.status(401).send(result); + } + + if (result.data === 'Invalid chat data' || result.data === 'User not registered') { + return res.status(400).send(result); + } + + return res.status(500).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async getChatChunk(req: Request, res: Response) { + try { + const body = req.body as GetChatBody & { chunkNumber: number }; + + if (!(body.id && body.chunkNumber)) + return res.status(400).send({ success: false, data: 'Invalid chat data' }); + + const result = await chatsModel.getChatChunk(body); + + if (result.success) { + return res.status(200).send(result); + } + + if (result.data === 'Unauthorized') { + return res.status(401).send(result); + } + + if (result.data === 'Invalid chat data' || result.data === 'User not registered') { + return res.status(400).send(result); + } + + return res.status(500).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async getAllChats(req: Request, res: Response) { + try { + const result = await chatsModel.getAllChats(req.body as GetAllChatsBody); + + if (result.success) { + return res.status(200).send(result); + } + + if (result.data === 'User not registered') { + return res.status(400).send(result); + } + + res.status(500).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async deleteChat(req: Request, res: Response) { + try { + if (!(req.body as DeleteChatBody).id) + return res.status(400).send({ success: false, data: 'Invalid chat data' }); + + const result = await chatsModel.deleteChat(req.body as DeleteChatBody); + + if (result.success) { + return res.status(200).send(result); + } + + if (result.data === 'Unauthorized') { + return res.status(401).send(result); + } + + if (result.data === 'Invalid chat data' || result.data === 'User not registered') { + return res.status(400).send(result); + } + + return res.status(500).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } +} + +const chatsController = new ChatsController(); + +export default chatsController; diff --git a/src/controllers/config.controller.ts b/src/controllers/config.controller.ts new file mode 100644 index 0000000..5220d57 --- /dev/null +++ b/src/controllers/config.controller.ts @@ -0,0 +1,18 @@ +import { Request, Response } from 'express'; +import configModel from '../models/Config.js'; + +class ConfigController { + async get(req: Request, res: Response) { + const result = await configModel.get(); + + if (!result.success) { + return res.status(500).send(result); + } + + res.status(200).send(result); + } +} + +const configController = new ConfigController(); + +export default configController; diff --git a/src/controllers/dex.controller.ts b/src/controllers/dex.controller.ts new file mode 100644 index 0000000..690401b --- /dev/null +++ b/src/controllers/dex.controller.ts @@ -0,0 +1,205 @@ +import { Request, Response } from 'express'; +import UserData from '@/interfaces/common/UserData.js'; +import Currency from '@/schemes/Currency.js'; +import Pair from '@/schemes/Pair.js'; +import { Op } from 'sequelize'; +import User from '../schemes/User.js'; +import ordersModel from '../models/Orders.js'; +import dexModel from '../models/Dex.js'; + +class DexController { + async getPairsPage(req: Request, res: Response) { + try { + const { body } = req; + const { page, searchText, whitelistedOnly, sortOption } = body; + + if (!page || typeof page !== 'number') + return res.status(400).send({ success: false, data: 'Invalid pair page data' }); + + const sort = sortOption; + const result = await dexModel.getPairsPage( + page, + (searchText || '').toString(), + !!whitelistedOnly, + sort, + ); + + if (!result.success) return res.status(500).send(result); + + res.status(200).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async getPairsPagesAmount(req: Request, res: Response) { + try { + const { body } = req; + const { searchText, whitelistedOnly } = body; + const result = await dexModel.getPairsPagesAmount( + (searchText || '').toString(), + !!whitelistedOnly, + ); + res.status(200).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async getPair(req: Request, res: Response) { + try { + if (!req.body.id) + return res.status(400).send({ success: false, data: 'Invalid pair data' }); + + const result = await dexModel.getPair(req.body.id); + + if (result.data === 'Invalid pair data') return res.status(400).send(result); + + if (result.data === 'Internal error') return res.status(500).send(result); + + res.status(200).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async registerBot(req: Request, res: Response) { + const userData = req.body.userData as UserData; + if (!userData) return res.status(400).send({ success: false, data: 'Invalid user data' }); + + const { orderId } = req.body; + + const targetOrder = await ordersModel.getOrderRow(orderId).catch(() => null); + + if (!targetOrder) + return res.status(400).send({ success: false, data: 'Invalid order data' }); + + const targetUser = await User.findOne({ + where: { + address: userData.address, + }, + }); + + if (!targetUser || targetOrder.user_id !== targetUser.id) + return res.status(400).send({ success: false, data: 'Invalid user data' }); + + const result = await dexModel.renewBotExpiration(orderId, targetUser.id); + + return res.status(200).send(result); + } + + async volumeStats(req: Request, res: Response) { + const { address, pairID, from, to } = req.body; + + if (!address || !pairID) + return res.status(400).send({ success: false, data: 'Invalid data' }); + + const fromTimestamp = typeof from === 'number' ? from : 0; + const toTimestamp = typeof to === 'number' ? to : +Date.now(); + + const result = await dexModel.volumeStats(address, pairID, fromTimestamp, toTimestamp); + return res.status(200).send(result); + } + + async getAssetsPriceRates(req: Request, res: Response) { + const { assetsIds } = req.body; + + const currencysRows = await Currency.findAll({ + where: { + asset_id: { + [Op.in]: assetsIds, + }, + }, + }); + + if (!currencysRows) { + return res.status(200).send({ + success: false, + data: 'Assets with this id doesn`t exists', + }); + } + + const currencyIds = currencysRows.map((currency) => currency.id); + + const pairsRows = ( + (await Pair.findAll({ + where: { + first_currency_id: { + [Op.in]: currencyIds, + }, + }, + include: [ + { + model: Currency, + as: 'first_currency', + required: true, + attributes: ['asset_id'], + }, + ], + })) || [] + ).map((pair) => ({ + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + asset_id: pair?.first_currency?.asset_id, + rate: pair.rate, + })); + + if (!pairsRows || pairsRows.length === 0) { + return res.status(200).send({ + success: false, + data: 'Assets with this id doesn`t exists', + }); + } + + // const priceRates = await Promise.all(pairsRows.map(async (pair) => { + // const currency = await Currency.findOne({ where: { + // id: pair.first_currency_id + // }}) + + // return { + // asset_id: currency?.asset_id, + // rate: pair.rate + // } + // })) + + return res.status(200).send({ + success: true, + priceRates: pairsRows, + }); + } + + async findPairID(req: Request, res: Response) { + const { first, second } = req.body; + + if (!first || !second) + return res.status(400).send({ success: false, data: 'Invalid data' }); + + const firstCurrency = await Currency.findOne({ where: { asset_id: first } }); + + const secondCurrency = await Currency.findOne({ where: { asset_id: second } }); + + if (!firstCurrency || !secondCurrency) + return res.status(400).send({ success: false, data: 'Invalid data' }); + + const pair = await Pair.findOne({ + where: { + first_currency_id: firstCurrency.id, + second_currency_id: secondCurrency.id, + }, + }); + + if (!pair) return res.status(404).send({ success: false, data: 'Pair not found' }); + + return res.status(200).send({ + success: true, + data: pair.id, + }); + } +} + +const dexController = new DexController(); + +export default dexController; diff --git a/src/controllers/offers.controller.ts b/src/controllers/offers.controller.ts new file mode 100644 index 0000000..11539fd --- /dev/null +++ b/src/controllers/offers.controller.ts @@ -0,0 +1,118 @@ +import { Request, Response } from 'express'; +import offersModel from '../models/Offers.js'; +import UpdateBody from '../interfaces/bodies/offers/UpdateBody.js'; +import DeleteBody from '../interfaces/bodies/offers/DeleteBody.js'; +import GetPageBody from '../interfaces/bodies/offers/GetPageBody.js'; + +class OffersController { + async update(req: Request, res: Response) { + try { + const { offerData } = req.body as UpdateBody; + const isFull = !!( + offerData && + offerData?.price && + offerData?.min && + offerData?.max && + offerData?.deposit_seller && + offerData?.deposit_buyer && + offerData?.type && + offerData?.input_currency_id && + offerData?.target_currency_id && + offerData?.deposit_currency_id + ); + + const rangeCorrect = + offerData?.min > 0 && + offerData?.min < 1000000000 && + offerData?.max > 0 && + offerData?.max < 1000000000 && + offerData?.deposit_buyer > 0 && + offerData?.deposit_buyer < 1000000000 && + offerData?.deposit_seller > 0 && + offerData?.deposit_seller < 1000000000 && + offerData?.price > 0 && + offerData?.price < 10000000000 && + offerData?.min < offerData?.max; + + if (!isFull || !rangeCorrect) + return res.status(400).send({ success: false, data: 'Invalid offer data' }); + + const result = await offersModel.update(req.body as UpdateBody); + + if (result.success) { + return res.status(200).send(result); + } + + if ( + result.data === 'User not registered' || + result.data === 'Forbidden' || + result.data === 'Offer is finished' || + result.data === 'Invalid offer data' + ) { + return res.status(400).send(result); + } + + return res.status(500).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async delete(req: Request, res: Response) { + try { + if (!req.body.offerData?.number) + return res.status(400).send({ success: false, data: 'Invalid offer data' }); + + const result = await offersModel.delete(req.body as DeleteBody); + + if (result.success) { + return res.status(200).send(result); + } + + if (result.data !== 'Internal error') { + return res.status(400).send(result); + } + + return res.status(500).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async getPage(req: Request, res: Response) { + try { + const pageData = (req.body as GetPageBody).data; + + if (!(pageData && pageData?.page && pageData?.type)) + return res.status(400).send({ success: false, data: 'Invalid page data' }); + + const result = await offersModel.getPage((req.body as GetPageBody).data); + + if (!result.success) return res.status(500).send(result); + + res.status(200).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async getStats(_: Request, res: Response) { + try { + const result = await offersModel.getStats(); + + if (!result.success) return res.status(500).send(result); + + res.status(200).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } +} + +const offersController = new OffersController(); + +export default offersController; diff --git a/src/controllers/orders.controller.ts b/src/controllers/orders.controller.ts new file mode 100644 index 0000000..3f990eb --- /dev/null +++ b/src/controllers/orders.controller.ts @@ -0,0 +1,246 @@ +import { Request, Response } from 'express'; +import Decimal from 'decimal.js'; +import candlesModel from '../models/Candles'; +import ordersModel from '../models/Orders'; +import CreateOrderBody from '../interfaces/bodies/orders/CreateOrderBody'; +import GetUserOrdersPageBody from '../interfaces/bodies/orders/GetUserOrdersPageBody'; +import GetUserOrdersBody from '../interfaces/bodies/orders/GetUserOrdersBody'; +import CancelOrderBody from '../interfaces/bodies/orders/CancelOrderBody'; +import GetCandlesBody from '../interfaces/bodies/orders/GetCandlesBody'; +import GetChartOrdersBody from '../interfaces/bodies/orders/GetChartOrdersBody'; +import ApplyOrderBody from '../interfaces/bodies/orders/ApplyOrderBody'; +import userModel from '../models/User'; +import UserData from '../interfaces/common/UserData'; +import Pair from '../schemes/Pair'; +import Currency from '../schemes/Currency'; +import { validateTokensInput } from '../../shared/utils'; + +class OrdersController { + async createOrder(req: Request, res: Response) { + try { + const { orderData } = req.body as CreateOrderBody; + + const isFull = + orderData && + orderData?.type && + orderData?.side && + orderData?.price && + orderData?.amount && + orderData?.pairId; + + const priceDecimal = new Decimal(orderData?.price || 0); + const amountDecimal = new Decimal(orderData?.amount || 0); + + const pair = await Pair.findByPk(orderData?.pairId); + + const firstCurrency = await Currency.findByPk(pair?.first_currency_id); + + const secondCurrency = await Currency.findByPk(pair?.second_currency_id); + + if (!pair || !firstCurrency || !secondCurrency) { + return res.status(400).send({ success: false, data: 'Invalid pair data' }); + } + + const firstCurrencyDecimalPoint = firstCurrency?.asset_info?.decimal_point || 12; + const secondCurrencyDecimalPoint = secondCurrency?.asset_info?.decimal_point || 12; + + const rangeCorrect = (() => { + const priceCorrect = validateTokensInput( + orderData?.price, + secondCurrencyDecimalPoint, + ).valid; + const amountCorrect = validateTokensInput( + orderData?.amount, + firstCurrencyDecimalPoint, + ).valid; + + return priceCorrect && amountCorrect; + })(); + + const priceDecimalPointCorrect = priceDecimal.toString().replace('.', '').length <= 20; + const amountDecimalPointCorrect = + amountDecimal.toString().replace('.', '').length <= 18; + + if (!priceDecimalPointCorrect || !amountDecimalPointCorrect) { + return res.status(400).send({ success: false, data: 'Invalid pair data' }); + } + + if (!isFull || !rangeCorrect) + return res.status(400).send({ success: false, data: 'Invalid order data' }); + + const result = await ordersModel.createOrder(req.body); + + if (result.data === 'Invalid order data') return res.status(400).send(result); + + if (result.data === 'Same order') return res.status(400).send(result); + + if (result.data === 'Internal error') return res.status(500).send(result); + + res.status(200).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async getOrdersPage(req: Request, res: Response) { + try { + if (!req.body.pairId) + return res.status(400).send({ success: false, data: 'Invalid pair data' }); + + const result = await ordersModel.getOrdersPage(req.body.pairId); + + if (result.data === 'Invalid pair data') return res.status(400).send(result); + + if (result.data === 'Internal error') return res.status(500).send(result); + + res.status(200).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async getUserOrdersPage(req: Request, res: Response) { + try { + if (!(req.body as GetUserOrdersPageBody).pairId) + return res.status(400).send({ success: false, data: 'Invalid pair data' }); + + const result = await ordersModel.getUserOrdersPage(req.body as GetUserOrdersPageBody); + + if (result.data === 'Invalid pair data') return res.status(400).send(result); + + if (result.data === 'Internal error') return res.status(500).send(result); + + const userAddress = (req.body.userData as UserData)?.address; + + if (userAddress) { + await userModel.resetNotificationsForPair( + (req.body.userData as UserData)?.address, + req.body.pairId, + ); + } + + res.status(200).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async getUserOrders(req: Request, res: Response) { + try { + await userModel.resetExchangeNotificationsAmount( + (req.body.userData as UserData).address, + ); + const result = await ordersModel.getUserOrders(req.body as GetUserOrdersBody); + + if (result.data === 'Internal error') return res.status(500).send(result); + + res.status(200).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async cancelOrder(req: Request, res: Response) { + try { + if (!(req.body as CancelOrderBody).orderId) + return res.status(400).send({ success: false, data: 'Invalid order data' }); + + const result = await ordersModel.cancelOrder(req.body as CancelOrderBody); + + if (result.data === 'Invalid order data') return res.status(400).send(result); + + if (result.data === 'Internal error') return res.status(500).send(result); + + res.status(200).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async getCandles(req: Request, res: Response) { + try { + const { body }: { body: GetCandlesBody } = req; + + if (!body.pairId || !body.period) + return res.status(400).send({ success: false, data: 'Invalid pair data' }); + + const result = await candlesModel.getCandles(body.pairId, body.period); + + if (result.data === 'Invalid pair data') return res.status(400).send(result); + + if (result.data === 'Internal error') return res.status(500).send(result); + + return res.status(200).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async getChartOrders(req: Request, res: Response) { + try { + const { body }: { body: GetChartOrdersBody } = req; + + if (!body.pairId) + return res.status(400).send({ success: false, data: 'Invalid pair data' }); + + const result = await ordersModel.getChartOrders(body.pairId); + + if (result.data === 'Internal error') return res.status(500).send(result); + + res.status(200).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async getPairStats(req: Request, res: Response) { + try { + const { body }: { body: GetChartOrdersBody } = req; + + if (!body.pairId) + return res.status(400).send({ success: false, data: 'Invalid pair data' }); + + const result = await ordersModel.getPairStats(body.pairId); + + if (result.data === 'Internal error') return res.status(500).send(result); + + res.status(200).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async applyOrder(req: Request, res: Response) { + try { + const { orderData } = req.body as ApplyOrderBody; + + const isFull = orderData && orderData?.id && orderData?.connected_order_id; + + if (!isFull) + return res.status(400).send({ success: false, data: 'Invalid order data' }); + + const result = await ordersModel.applyOrder(req.body); + + if (result.data === 'Invalid order data') return res.status(400).send(result); + + if (result.data === 'Internal error') return res.status(500).send(result); + + res.status(200).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } +} + +const ordersController = new OrdersController(); + +export default ordersController; diff --git a/src/controllers/process.controller.ts b/src/controllers/process.controller.ts new file mode 100644 index 0000000..cf0f3a6 --- /dev/null +++ b/src/controllers/process.controller.ts @@ -0,0 +1,67 @@ +import CreateMessageBody from '../interfaces/bodies/chats/CreateMessageBody.js'; +import ChatSocketData from '../interfaces/special/socket-data/ChatSocketData.js'; +import DepositSocketData from '../interfaces/special/socket-data/DepositSocketData.js'; +import chatsModel from '../models/Chats.js'; + +class ProcessController { + async createMessage(data: CreateMessageBody) { + try { + const isFull = + data.chat_id && + data.message && + ((data.message.type !== 'img' && + data.message.text && + data.message.text?.length <= 10000) || + (data.message.type === 'img' && data.message.url)); + + if (!isFull) return { success: false, data: 'Invalid message data' }; + + const result = await chatsModel.createMessage({ + chat_id: data.chat_id, + userData: data.userData, + message: { + ...data.message, + success: false, + fail: false, + }, + } as CreateMessageBody); + + return result; + } catch (err) { + console.log(err); + return { success: false, data: 'Unhandled error' }; + } + } + + async changeDeposit(data: DepositSocketData) { + try { + const isFull = data.chat_id && data.deposit_state; + + if (!isFull) return { success: false, data: 'Invalid deposit state data' }; + + const result = await chatsModel.changeDeposit(data); + return result; + } catch (err) { + console.log(err); + return { success: false, data: 'Unhandled error' }; + } + } + + async setWatched(data: ChatSocketData) { + try { + const isFull = data.chat_id; + + if (!isFull) return { success: false, data: 'Invalid watched data' }; + + const result = await chatsModel.setWatched(data); + return result; + } catch (err) { + console.log(err); + return { success: false, data: 'Unhandled error' }; + } + } +} + +const processController = new ProcessController(); + +export default processController; diff --git a/src/controllers/transactions.controller.ts b/src/controllers/transactions.controller.ts new file mode 100644 index 0000000..03c4945 --- /dev/null +++ b/src/controllers/transactions.controller.ts @@ -0,0 +1,75 @@ +import { Request, Response } from 'express'; +import exchangeModel from '../models/ExchangeTransactions.js'; +import ConfirmTransactionBody from '../interfaces/bodies/exchange-transactions/ConfirmTransactionBody.js'; +import GetActiveTxByOrdersIdsBody from '../interfaces/bodies/exchange-transactions/GetActiveTxByOrdersIdsBody.js'; +import Order from '../schemes/Order.js'; + +class TransactionsController { + async confirmTransaction(req: Request, res: Response) { + try { + if (!(req.body as ConfirmTransactionBody).transactionId) { + return res.status(400).json({ success: false, data: 'Invalid transaction data' }); + } + + const result = await exchangeModel.confirmTransaction( + req.body as ConfirmTransactionBody, + ); + + if ( + result.data === 'Transaction is not pending' || + result.data === 'You are not a participant of this transaction' + ) { + return res.status(400).send(result); + } + + if (result.data === 'Internal error') { + return res.status(500).send(result); + } + + return res.status(200).send(result); + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async getActiveTxByOrdersIds(req: Request, res: Response) { + try { + const body = req.body as GetActiveTxByOrdersIdsBody; + const { firstOrderId, secondOrderId, userData } = body; + + const userRow = await Order.findOne({ where: { address: userData.address } }); + + if (!userRow) { + throw new Error('JWT token of non-existent user'); + } + + const firstOrderRow = await Order.findOne({ + where: { id: firstOrderId, user_id: userRow.id }, + }); + const secondOrderRow = await Order.findOne({ + where: { id: secondOrderId, user_id: userRow.id }, + }); + + if (!firstOrderRow && !secondOrderRow) { + return res + .status(400) + .send({ success: false, data: 'None of the orders belong to this user' }); + } + + const tx = await exchangeModel.getActiveTxByOrdersIds(firstOrderId, secondOrderId); + if (!tx) { + return res.status(400).send({ success: false, data: 'Invalid order data' }); + } + + return res.status(200).send({ success: true, data: tx }); + } catch (err) { + console.log(err); + return res.status(500).send({ success: false, data: 'Internal error' }); + } + } +} + +const transactionsController = new TransactionsController(); + +export default transactionsController; diff --git a/src/controllers/user.controller.ts b/src/controllers/user.controller.ts new file mode 100644 index 0000000..beb3f93 --- /dev/null +++ b/src/controllers/user.controller.ts @@ -0,0 +1,98 @@ +import { Request, Response } from 'express'; +import configModel from '../models/Config.js'; +import userModel from '../models/User.js'; +import GetUserBody from '../interfaces/bodies/user/GetUserBody.js'; +import SetFavouriteCurrsBody from '../interfaces/bodies/user/SetFavouriteCurrsBody.js'; + +class UserController { + async getUser(req: Request, res: Response) { + try { + if (!req.body.userData?.address) + return res.status(400).send({ success: false, data: 'Invalid user data' }); + + const result = await userModel.getUser({ + address: req.body.userData.address, + } as GetUserBody); + + if (result.success) { + return res.status(200).send(result); + } + + if (result.data === 'User not registered') { + return res.status(400).send(result); + } + + return res.status(500).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async getNotificationsAmount(req: Request, res: Response) { + try { + if (!req.body.userData?.address) + return res.status(400).send({ success: false, data: 'Invalid user data' }); + + const result = await userModel.getNotificationsAmount({ + address: req.body.userData.address, + } as GetUserBody); + + if (result.success) { + return res.status(200).send(result); + } + + if (result.data === 'User not found') { + return res.status(400).send(result); + } + + return res.status(500).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } + + async setFavouriteCurrencies(req: Request, res: Response) { + try { + if (!req.body.data) + return res.status(400).send({ success: false, data: 'Invalid currencies data' }); + + try { + JSON.stringify(req.body.data); + const configGetResult = await configModel.get(); + + if (!configGetResult.success) return res.status(400).send(configGetResult); + + const { currencies } = configGetResult.data; + if ( + (req.body as SetFavouriteCurrsBody).data.find( + (e) => !currencies.find((curr) => curr.code === e), + ) + ) + throw new Error(); + } catch { + return res.status(400).send({ success: false, data: 'Invalid currencies data' }); + } + + const result = await userModel.setFavouriteCurrencies(req.body); + + if (result.success) { + return res.status(200).send(result); + } + + if (result.data === 'User not registered') { + return res.status(400).send(result); + } + + return res.status(500).send(result); + } catch (err) { + console.log(err); + res.status(500).send({ success: false, data: 'Unhandled error' }); + } + } +} + +const userController = new UserController(); + +export default userController; diff --git a/src/database.ts b/src/database.ts new file mode 100644 index 0000000..2bb47e1 --- /dev/null +++ b/src/database.ts @@ -0,0 +1,29 @@ +import 'dotenv/config'; +import pg from 'pg'; + +async function initdb() { + const pool = new pg.Pool({ + user: process.env.PGUSER, + password: process.env.PGPASSWORD, + host: process.env.PGHOST, + database: 'postgres', + port: parseInt(process.env.PGPORT || '5432', 10), + keepAlive: true, + idleTimeoutMillis: 0, + max: 100, + }); + + try { + await pool.query(`CREATE DATABASE "${process.env.PGDATABASE}" `); + } catch (error) { + if ((error as { code: string }).code === '42P04') { + console.log('Database already exists, skipping creation'); + } else { + throw error; + } + } + + await pool.end(); +} + +export default initdb; diff --git a/src/interfaces/bodies/chats/CreateBody.ts b/src/interfaces/bodies/chats/CreateBody.ts new file mode 100644 index 0000000..b1060d7 --- /dev/null +++ b/src/interfaces/bodies/chats/CreateBody.ts @@ -0,0 +1,12 @@ +import UserData from '../../common/UserData'; + +interface CreateBody { + userData: UserData; + number: string; + chatData: { + pay: string; + receive: string; + }; +} + +export default CreateBody; diff --git a/src/interfaces/bodies/chats/CreateMessageBody.ts b/src/interfaces/bodies/chats/CreateMessageBody.ts new file mode 100644 index 0000000..e0f1f84 --- /dev/null +++ b/src/interfaces/bodies/chats/CreateMessageBody.ts @@ -0,0 +1,10 @@ +import Message from '../../common/Message'; +import UserData from '../../common/UserData'; + +interface CreateMessageBody { + chat_id: string; + userData: UserData; + message: Message; +} + +export default CreateMessageBody; diff --git a/src/interfaces/bodies/chats/DeleteChatBody.ts b/src/interfaces/bodies/chats/DeleteChatBody.ts new file mode 100644 index 0000000..fb14f27 --- /dev/null +++ b/src/interfaces/bodies/chats/DeleteChatBody.ts @@ -0,0 +1,8 @@ +import UserData from '../../common/UserData'; + +interface DeleteChatBody { + userData: UserData; + id: string; +} + +export default DeleteChatBody; diff --git a/src/interfaces/bodies/chats/GetAllChatsBody.ts b/src/interfaces/bodies/chats/GetAllChatsBody.ts new file mode 100644 index 0000000..07e541c --- /dev/null +++ b/src/interfaces/bodies/chats/GetAllChatsBody.ts @@ -0,0 +1,7 @@ +import UserData from '../../common/UserData'; + +interface GetAllChatsBody { + userData: UserData; +} + +export default GetAllChatsBody; diff --git a/src/interfaces/bodies/chats/GetChatBody.ts b/src/interfaces/bodies/chats/GetChatBody.ts new file mode 100644 index 0000000..f00dda0 --- /dev/null +++ b/src/interfaces/bodies/chats/GetChatBody.ts @@ -0,0 +1,9 @@ +import UserData from '../../common/UserData'; + +interface GetChatBody { + userData: UserData; + id: string; + chat_id?: undefined; +} + +export default GetChatBody; diff --git a/src/interfaces/bodies/exchange-transactions/ConfirmTransactionBody.ts b/src/interfaces/bodies/exchange-transactions/ConfirmTransactionBody.ts new file mode 100644 index 0000000..5d7b8df --- /dev/null +++ b/src/interfaces/bodies/exchange-transactions/ConfirmTransactionBody.ts @@ -0,0 +1,8 @@ +import UserData from '../../common/UserData'; + +interface ConfirmTransactionBody { + transactionId: string; + userData: UserData; +} + +export default ConfirmTransactionBody; diff --git a/src/interfaces/bodies/exchange-transactions/GetActiveTxByOrdersIdsBody.ts b/src/interfaces/bodies/exchange-transactions/GetActiveTxByOrdersIdsBody.ts new file mode 100644 index 0000000..6847310 --- /dev/null +++ b/src/interfaces/bodies/exchange-transactions/GetActiveTxByOrdersIdsBody.ts @@ -0,0 +1,7 @@ +import UserData from '@/interfaces/common/UserData'; + +export default interface GetActiveTxByOrdersIdsBody { + userData: UserData; + firstOrderId: number; + secondOrderId: number; +} diff --git a/src/interfaces/bodies/offers/DeleteBody.ts b/src/interfaces/bodies/offers/DeleteBody.ts new file mode 100644 index 0000000..624c7d5 --- /dev/null +++ b/src/interfaces/bodies/offers/DeleteBody.ts @@ -0,0 +1,10 @@ +import UserData from '../../common/UserData'; + +interface DeleteBody { + userData: UserData; + offerData: { + number: string; + }; +} + +export default DeleteBody; diff --git a/src/interfaces/bodies/offers/GetPageBody.ts b/src/interfaces/bodies/offers/GetPageBody.ts new file mode 100644 index 0000000..a939eb7 --- /dev/null +++ b/src/interfaces/bodies/offers/GetPageBody.ts @@ -0,0 +1,18 @@ +import OfferType from '../../common/OfferType'; + +interface PageData { + type: OfferType; + page: number; + input_currency_id?: string; + target_currency_id?: string; + price?: number; + priceDescending?: boolean; +} + +interface GetPageBody { + data: PageData; +} + +export default GetPageBody; + +export { type PageData }; diff --git a/src/interfaces/bodies/offers/UpdateBody.ts b/src/interfaces/bodies/offers/UpdateBody.ts new file mode 100644 index 0000000..27c3354 --- /dev/null +++ b/src/interfaces/bodies/offers/UpdateBody.ts @@ -0,0 +1,23 @@ +import OfferType from '../../common/OfferType'; +import UserData from '../../common/UserData'; + +interface OfferData { + price: number; + min: number; + max: number; + deposit_seller: number; + deposit_buyer: number; + type: OfferType; + comment?: string; + input_currency_id: string; + target_currency_id: string; + deposit_currency_id: string; + number?: string; +} + +interface UpdateBody { + userData: UserData; + offerData: OfferData; +} + +export default UpdateBody; diff --git a/src/interfaces/bodies/orders/ApplyOrderBody.ts b/src/interfaces/bodies/orders/ApplyOrderBody.ts new file mode 100644 index 0000000..3fa5663 --- /dev/null +++ b/src/interfaces/bodies/orders/ApplyOrderBody.ts @@ -0,0 +1,14 @@ +import UserData from '../../common/UserData'; + +interface OrderData { + id: string; + connected_order_id: string; + hex_raw_proposal: string; +} + +interface ApplyOrderBody { + userData: UserData; + orderData: OrderData; +} + +export default ApplyOrderBody; diff --git a/src/interfaces/bodies/orders/CancelOrderBody.ts b/src/interfaces/bodies/orders/CancelOrderBody.ts new file mode 100644 index 0000000..369fe14 --- /dev/null +++ b/src/interfaces/bodies/orders/CancelOrderBody.ts @@ -0,0 +1,8 @@ +import UserData from '../../common/UserData'; + +interface CancelOrderBody { + orderId: string; + userData: UserData; +} + +export default CancelOrderBody; diff --git a/src/interfaces/bodies/orders/CreateOrderBody.ts b/src/interfaces/bodies/orders/CreateOrderBody.ts new file mode 100644 index 0000000..877596e --- /dev/null +++ b/src/interfaces/bodies/orders/CreateOrderBody.ts @@ -0,0 +1,18 @@ +import OfferType from '../../common/OfferType'; +import Side from '../../common/Side'; +import UserData from '../../common/UserData'; + +interface OrderData { + type: OfferType; + side: Side; + price: string; + amount: string; + pairId: string; +} + +interface CreateOrderBody { + userData: UserData; + orderData: OrderData; +} + +export default CreateOrderBody; diff --git a/src/interfaces/bodies/orders/GetCandlesBody.ts b/src/interfaces/bodies/orders/GetCandlesBody.ts new file mode 100644 index 0000000..8464acb --- /dev/null +++ b/src/interfaces/bodies/orders/GetCandlesBody.ts @@ -0,0 +1,8 @@ +import Period from '../../common/Period'; + +interface GetCandlesBody { + pairId: string; + period: Period; +} + +export default GetCandlesBody; diff --git a/src/interfaces/bodies/orders/GetChartOrdersBody.ts b/src/interfaces/bodies/orders/GetChartOrdersBody.ts new file mode 100644 index 0000000..fdfdb52 --- /dev/null +++ b/src/interfaces/bodies/orders/GetChartOrdersBody.ts @@ -0,0 +1,5 @@ +interface GetChartOrdersBody { + pairId: string; +} + +export default GetChartOrdersBody; diff --git a/src/interfaces/bodies/orders/GetUserOrdersBody.ts b/src/interfaces/bodies/orders/GetUserOrdersBody.ts new file mode 100644 index 0000000..93e5015 --- /dev/null +++ b/src/interfaces/bodies/orders/GetUserOrdersBody.ts @@ -0,0 +1,7 @@ +import UserData from '../../common/UserData'; + +interface GetUserOrdersBody { + userData: UserData; +} + +export default GetUserOrdersBody; diff --git a/src/interfaces/bodies/orders/GetUserOrdersPageBody.ts b/src/interfaces/bodies/orders/GetUserOrdersPageBody.ts new file mode 100644 index 0000000..9b84297 --- /dev/null +++ b/src/interfaces/bodies/orders/GetUserOrdersPageBody.ts @@ -0,0 +1,8 @@ +import UserData from '../../common/UserData'; + +interface GetUserOrdersPageBody { + userData: UserData; + pairId: string; +} + +export default GetUserOrdersPageBody; diff --git a/src/interfaces/bodies/user/AuthData.ts b/src/interfaces/bodies/user/AuthData.ts new file mode 100644 index 0000000..c2c5496 --- /dev/null +++ b/src/interfaces/bodies/user/AuthData.ts @@ -0,0 +1,6 @@ +export default interface AuthData { + address: string; + alias: string; + signature: string; + message: string; +} diff --git a/src/interfaces/bodies/user/GetUserBody.ts b/src/interfaces/bodies/user/GetUserBody.ts new file mode 100644 index 0000000..b4f74d8 --- /dev/null +++ b/src/interfaces/bodies/user/GetUserBody.ts @@ -0,0 +1,5 @@ +interface GetUserBody { + address: string; +} + +export default GetUserBody; diff --git a/src/interfaces/bodies/user/SetFavouriteCurrsBody.ts b/src/interfaces/bodies/user/SetFavouriteCurrsBody.ts new file mode 100644 index 0000000..8e50d29 --- /dev/null +++ b/src/interfaces/bodies/user/SetFavouriteCurrsBody.ts @@ -0,0 +1,8 @@ +import UserData from '../../common/UserData'; + +interface SetFavouriteCurrsBody { + userData: UserData; + data: string[]; +} + +export default SetFavouriteCurrsBody; diff --git a/src/interfaces/common/Candle.ts b/src/interfaces/common/Candle.ts new file mode 100644 index 0000000..a151ab2 --- /dev/null +++ b/src/interfaces/common/Candle.ts @@ -0,0 +1,9 @@ +interface Candle { + timestamp: string; + shadow_top: number | undefined; + shadow_bottom: number | undefined; + body_first: number | undefined; + body_second: number | undefined; +} + +export default Candle; diff --git a/src/interfaces/common/CurrecnyType.ts b/src/interfaces/common/CurrecnyType.ts new file mode 100644 index 0000000..de1b879 --- /dev/null +++ b/src/interfaces/common/CurrecnyType.ts @@ -0,0 +1,3 @@ +type CurrencyType = 'fiat' | 'crypto' | 'deposit'; + +export default CurrencyType; diff --git a/src/interfaces/common/Message.ts b/src/interfaces/common/Message.ts new file mode 100644 index 0000000..0704504 --- /dev/null +++ b/src/interfaces/common/Message.ts @@ -0,0 +1,12 @@ +interface Message { + type?: 'img'; + url?: string; + text?: string; + timestamp: number; + fromOwner?: boolean; + success: boolean; + fail: boolean; + system?: boolean; +} + +export default Message; diff --git a/src/interfaces/common/OfferType.ts b/src/interfaces/common/OfferType.ts new file mode 100644 index 0000000..306faa6 --- /dev/null +++ b/src/interfaces/common/OfferType.ts @@ -0,0 +1,3 @@ +type OfferType = 'buy' | 'sell'; + +export default OfferType; diff --git a/src/interfaces/common/PairStats.ts b/src/interfaces/common/PairStats.ts new file mode 100644 index 0000000..c37537b --- /dev/null +++ b/src/interfaces/common/PairStats.ts @@ -0,0 +1,7 @@ +export default interface PairStats { + rate: number; + coefficient: number; + high: number; + low: number; + volume: number; +} diff --git a/src/interfaces/common/Period.ts b/src/interfaces/common/Period.ts new file mode 100644 index 0000000..3aa1672 --- /dev/null +++ b/src/interfaces/common/Period.ts @@ -0,0 +1,3 @@ +type Period = '1h' | '1d' | '1w' | '1m'; + +export default Period; diff --git a/src/interfaces/common/Side.ts b/src/interfaces/common/Side.ts new file mode 100644 index 0000000..754d5ac --- /dev/null +++ b/src/interfaces/common/Side.ts @@ -0,0 +1,3 @@ +type Side = 'limit' | 'market'; + +export default Side; diff --git a/src/interfaces/common/UserData.ts b/src/interfaces/common/UserData.ts new file mode 100644 index 0000000..d230c37 --- /dev/null +++ b/src/interfaces/common/UserData.ts @@ -0,0 +1,8 @@ +interface UserData { + alias?: string; + address: string; + id?: undefined; + favourite_currencies?: undefined; +} + +export default UserData; diff --git a/src/interfaces/database/CandleRow.ts b/src/interfaces/database/CandleRow.ts new file mode 100644 index 0000000..e715278 --- /dev/null +++ b/src/interfaces/database/CandleRow.ts @@ -0,0 +1,11 @@ +interface CandleRow { + id: string; + pair_id: string; + timestamp: string; + shadow_top: number; + shadow_bottom: number; + body_first: number; + body_second: number; +} + +export default CandleRow; diff --git a/src/interfaces/database/ChatRow.ts b/src/interfaces/database/ChatRow.ts new file mode 100644 index 0000000..0b4a933 --- /dev/null +++ b/src/interfaces/database/ChatRow.ts @@ -0,0 +1,18 @@ +type DepositState = null | 'default' | 'deposit' | 'confirmed' | 'canceled'; + +interface ChatRow { + id: string; + offer_number: string; + buyer_id: string; + chat_history: string; + status: string; + pay: number; + receive: number; + owner_deposit: DepositState; + opponent_deposit: DepositState; + view_list: string[]; +} + +export default ChatRow; + +export { type DepositState }; diff --git a/src/interfaces/database/CurrencyRow.ts b/src/interfaces/database/CurrencyRow.ts new file mode 100644 index 0000000..7c5f929 --- /dev/null +++ b/src/interfaces/database/CurrencyRow.ts @@ -0,0 +1,11 @@ +import CurrencyType from '../common/CurrecnyType'; + +interface CurrencyRow { + id: string; + name: string; + code: string; + type: CurrencyType; + asset_id: string | null; +} + +export default CurrencyRow; diff --git a/src/interfaces/database/ExchangeRow.ts b/src/interfaces/database/ExchangeRow.ts new file mode 100644 index 0000000..ad49459 --- /dev/null +++ b/src/interfaces/database/ExchangeRow.ts @@ -0,0 +1,12 @@ +interface ExchangeRow { + id: string; + buy_order_id: string; + sell_order_id: string; + amount: number; + timestamp: string; + status: string; + creator: string; + hex_raw_proposal: string; +} + +export default ExchangeRow; diff --git a/src/interfaces/database/MessagesRow.ts b/src/interfaces/database/MessagesRow.ts new file mode 100644 index 0000000..f3fb0c8 --- /dev/null +++ b/src/interfaces/database/MessagesRow.ts @@ -0,0 +1,13 @@ +interface MessagesRow { + id: string; + type: string; + url: string | null; + text: string | null; + timestamp: string; + from_owner: boolean; + success: boolean; + fail: boolean; + system: boolean; +} + +export default MessagesRow; diff --git a/src/interfaces/database/OfferRow.ts b/src/interfaces/database/OfferRow.ts new file mode 100644 index 0000000..edb904b --- /dev/null +++ b/src/interfaces/database/OfferRow.ts @@ -0,0 +1,21 @@ +import OfferType from '../common/OfferType'; + +interface OfferRow { + id: string; + user_id: string; + price: number; + min: number; + max: number; + deposit_seller: number; + deposit_buyer: number; + type: OfferType; + input_currency_id: string; + target_currency_id: string; + comment: string | null; + number: string; + offer_status: 'default' | 'process' | 'hidden' | 'finished'; + deposit_currency_id: string; + timestamp: string; +} + +export default OfferRow; diff --git a/src/interfaces/database/OrderRow.ts b/src/interfaces/database/OrderRow.ts new file mode 100644 index 0000000..e0432af --- /dev/null +++ b/src/interfaces/database/OrderRow.ts @@ -0,0 +1,17 @@ +import OfferType from '../common/OfferType'; + +interface OrderRow { + id: string; + type: OfferType; + timestamp: string; + side: string; + price: number; + amount: number; + total: number; + pair_id: string; + user_id: string; + status: string; + left: number; +} + +export default OrderRow; diff --git a/src/interfaces/database/TradingPairRow.ts b/src/interfaces/database/TradingPairRow.ts new file mode 100644 index 0000000..3f541fe --- /dev/null +++ b/src/interfaces/database/TradingPairRow.ts @@ -0,0 +1,7 @@ +interface TradingPairRow { + id: string; + first_currency_id: string; + second_currency_id: string; +} + +export default TradingPairRow; diff --git a/src/interfaces/database/UserRow.ts b/src/interfaces/database/UserRow.ts new file mode 100644 index 0000000..f3b32bd --- /dev/null +++ b/src/interfaces/database/UserRow.ts @@ -0,0 +1,8 @@ +interface UserRow { + id: string; + alias: string; + address: string; + favourite_currencies: string[]; +} + +export default UserRow; diff --git a/src/interfaces/enum/pair.ts b/src/interfaces/enum/pair.ts new file mode 100644 index 0000000..3854f22 --- /dev/null +++ b/src/interfaces/enum/pair.ts @@ -0,0 +1,5 @@ +/* eslint-disable no-unused-vars */ +export enum PairSortOption { + VOLUME_LOW_TO_HIGH = 'VOLUME_LOW_TO_HIGH', + VOLUME_HIGH_TO_LOW = 'VOLUME_HIGH_TO_LOW', +} diff --git a/src/interfaces/responses/ErrorResponse.ts b/src/interfaces/responses/ErrorResponse.ts new file mode 100644 index 0000000..417b018 --- /dev/null +++ b/src/interfaces/responses/ErrorResponse.ts @@ -0,0 +1,6 @@ +interface ErrorResponse { + success: false; + data: string; +} + +export default ErrorResponse; diff --git a/src/interfaces/responses/chats/chats.ts b/src/interfaces/responses/chats/chats.ts new file mode 100644 index 0000000..8985dc3 --- /dev/null +++ b/src/interfaces/responses/chats/chats.ts @@ -0,0 +1,47 @@ +import Currency from '../../../schemes/Currency'; + +interface UserDataWithId { + id: number; + alias: string; + address: string; + favourite_currencies: string[] | undefined; +} + +interface ChatData { + id: number; + user_id: number; + price: number; + min: number; + max: number; + deposit_seller: number; + deposit_buyer: number; + type: string; + input_currency: Currency | null; + target_currency: Currency | null; + comment: string | null; + number: string; + offer_status: string; + deposit_currency: Currency | null; + timestamp: bigint; + creator_data: UserDataWithId; + buyer_data: UserDataWithId; + + offer_number: string; + buyer_id: number; + chunk_count: number; + status: string; + pay: number; + receive: number; + owner_deposit: string | null; + opponent_deposit: string | null; + view_list: number[]; + + favourite_currencies?: undefined; +} + +interface GetChatResponse { + success: true; + data: ChatData; +} + +export default GetChatResponse; diff --git a/src/interfaces/responses/config/config.ts b/src/interfaces/responses/config/config.ts new file mode 100644 index 0000000..d7d66e7 --- /dev/null +++ b/src/interfaces/responses/config/config.ts @@ -0,0 +1,10 @@ +import Currency from '../../../schemes/Currency'; + +interface GetConfigRes { + success: true; + data: { + currencies: Currency[]; + }; +} + +export default GetConfigRes; diff --git a/src/interfaces/responses/offers/GetStatsRes.ts b/src/interfaces/responses/offers/GetStatsRes.ts new file mode 100644 index 0000000..5104dd9 --- /dev/null +++ b/src/interfaces/responses/offers/GetStatsRes.ts @@ -0,0 +1,11 @@ +interface GetStatsRes { + success: true; + data: { + opened: number; + volume_24: number; + volume_7: number; + volume_30: number; + }; +} + +export default GetStatsRes; diff --git a/src/interfaces/responses/orders/ApplyTip.ts b/src/interfaces/responses/orders/ApplyTip.ts new file mode 100644 index 0000000..705130b --- /dev/null +++ b/src/interfaces/responses/orders/ApplyTip.ts @@ -0,0 +1,17 @@ +import UserData from '../../common/UserData'; + +interface ApplyTip { + id: number; + left: string; + price: string; + user: UserData; + timestamp?: number; + type: string; + total: string; + connected_order_id: number; + transaction: boolean; + hex_raw_proposal?: string; + isInstant?: boolean; +} + +export default ApplyTip; diff --git a/src/interfaces/responses/orders/GetPairStatsRes.ts b/src/interfaces/responses/orders/GetPairStatsRes.ts new file mode 100644 index 0000000..6291f4d --- /dev/null +++ b/src/interfaces/responses/orders/GetPairStatsRes.ts @@ -0,0 +1,16 @@ +interface PairStats { + rate: number; + coefficient: number; + high: number; + low: number; + volume: number; +} + +interface GetPairStatsRes { + success: true; + data: PairStats; +} + +export default GetPairStatsRes; + +export type { PairStats }; diff --git a/src/interfaces/special/socket-data/AuthorizedData.ts b/src/interfaces/special/socket-data/AuthorizedData.ts new file mode 100644 index 0000000..ba7fd4e --- /dev/null +++ b/src/interfaces/special/socket-data/AuthorizedData.ts @@ -0,0 +1,8 @@ +import UserData from '../../common/UserData'; + +interface AuthorizedData { + chat_id: string; + userData: UserData; +} + +export default AuthorizedData; diff --git a/src/interfaces/special/socket-data/ChatSocketData.ts b/src/interfaces/special/socket-data/ChatSocketData.ts new file mode 100644 index 0000000..1ebaf78 --- /dev/null +++ b/src/interfaces/special/socket-data/ChatSocketData.ts @@ -0,0 +1,8 @@ +import UserData from '../../common/UserData'; + +interface ChatSocketData { + chat_id: string; + userData: UserData; +} + +export default ChatSocketData; diff --git a/src/interfaces/special/socket-data/DepositSocketData.ts b/src/interfaces/special/socket-data/DepositSocketData.ts new file mode 100644 index 0000000..e269bbc --- /dev/null +++ b/src/interfaces/special/socket-data/DepositSocketData.ts @@ -0,0 +1,7 @@ +import AuthorizedData from './AuthorizedData'; + +interface DepositSocketData extends AuthorizedData { + deposit_state: string; +} + +export default DepositSocketData; diff --git a/src/interfaces/special/socket-data/MessageSocketData.ts b/src/interfaces/special/socket-data/MessageSocketData.ts new file mode 100644 index 0000000..c3a3317 --- /dev/null +++ b/src/interfaces/special/socket-data/MessageSocketData.ts @@ -0,0 +1,8 @@ +import Message from '../../common/Message'; +import AuthorizedData from './AuthorizedData'; + +interface MessageSocketData extends AuthorizedData { + message: Message; +} + +export default MessageSocketData; diff --git a/src/interfaces/special/socket-data/OrderData.ts b/src/interfaces/special/socket-data/OrderData.ts new file mode 100644 index 0000000..ee20ed2 --- /dev/null +++ b/src/interfaces/special/socket-data/OrderData.ts @@ -0,0 +1,21 @@ +import PairData from '@/interfaces/common/PairData'; +import UserData from '../../common/UserData'; + +interface OrderData { + id: number; + type: string; + timestamp: number; + side: string; + price: number; + amount: number; + total: number; + pair_id: number; + user_id?: undefined; + status: string; + left: number; + user: UserData; + pair: PairData; + immediateMatch: boolean; +} + +export default OrderData; diff --git a/src/interfaces/special/socket-data/SocketData.ts b/src/interfaces/special/socket-data/SocketData.ts new file mode 100644 index 0000000..0fe65c9 --- /dev/null +++ b/src/interfaces/special/socket-data/SocketData.ts @@ -0,0 +1,5 @@ +interface SocketData { + id: string; +} + +export default SocketData; diff --git a/src/interfaces/special/socket-data/UserSocketData.ts b/src/interfaces/special/socket-data/UserSocketData.ts new file mode 100644 index 0000000..fe8f8a6 --- /dev/null +++ b/src/interfaces/special/socket-data/UserSocketData.ts @@ -0,0 +1,5 @@ +import UserData from '@/interfaces/common/UserData'; + +export default interface UserSocketData { + userData: UserData; +} diff --git a/src/methods/validateWallet.ts b/src/methods/validateWallet.ts new file mode 100644 index 0000000..a672094 --- /dev/null +++ b/src/methods/validateWallet.ts @@ -0,0 +1,50 @@ +import AuthData from '@/interfaces/bodies/user/AuthData'; +import axios from 'axios'; + +async function validateWallet(authData: AuthData) { + async function fetchZanoApi(method: string, params: object) { + try { + return await axios + .post('http://195.201.107.230:33341/json_rpc', { + id: 0, + jsonrpc: '2.0', + method, + params, + }) + .then((res) => res.data); + } catch (error) { + console.log(error); + } + } + + const { message, address, alias, signature } = authData; + + if (!message || !alias || !signature) { + return false; + } + + const response = await fetchZanoApi('validate_signature', { + buff: Buffer.from(message).toString('base64'), + alias, + sig: signature, + }); + + const aliasOk = response?.result?.status === 'OK'; + + if (!aliasOk) { + return false; + } + + const aliasDetailsResponse = await fetchZanoApi('get_alias_details', { + alias, + }); + + const aliasDetails = aliasDetailsResponse?.result?.alias_details; + const aliasAddress = aliasDetails?.address; + + const addressOk = !!aliasAddress && aliasAddress === address; + + return aliasOk && addressOk; +} + +export default validateWallet; diff --git a/src/middleware/middleware.ts b/src/middleware/middleware.ts new file mode 100644 index 0000000..0f81c49 --- /dev/null +++ b/src/middleware/middleware.ts @@ -0,0 +1,41 @@ +import { NextFunction, Request, Response } from 'express'; +import jwt from 'jsonwebtoken'; +import User from '@/schemes/User'; +import UserData from '../interfaces/common/UserData'; + +class Middleware { + async verifyToken(req: Request, res: Response, next: NextFunction) { + try { + const userData = jwt.verify(req.body.token, process.env.JWT_SECRET || '') as UserData; + req.body.userData = userData; + next(); + } catch { + res.status(401).send({ success: false, data: 'Unauthorized (JWT)' }); + } + } + + async verifyAdmin(req: Request, res: Response, next: NextFunction) { + const userAlias = req?.body?.userData?.alias || null; + + console.log(req?.body?.userData); + + const userField = await User.findOne({ + where: { + alias: userAlias, + }, + }); + + const isAdmin = userField && userField.isAdmin; + const isOwner = process.env.OWNER_ALIAS && process.env.OWNER_ALIAS === userField?.alias; + + if (isAdmin || isOwner) { + next(); + } else { + res.status(401).send({ success: false, data: 'Unauthorized' }); + } + } +} + +const middleware = new Middleware(); + +export default middleware; diff --git a/src/middleware/socket.ts b/src/middleware/socket.ts new file mode 100644 index 0000000..116e756 --- /dev/null +++ b/src/middleware/socket.ts @@ -0,0 +1,65 @@ +import { Event } from 'socket.io'; +import jwt from 'jsonwebtoken'; +import chatsModel from '../models/Chats.js'; +import UserData from '../interfaces/common/UserData.js'; + +async function socketMiddleware(event: Event, next: (_err?: Error | undefined) => void) { + const [path, data] = event; + + const skipPaths = [ + 'in-account', + 'in-trading', + 'out-trading', + 'in-dex-notifications', + 'out-dex-notifications', + 'error', + 'leave', + 'disconnect', + ]; + + const isSkip = skipPaths.includes(path); + + if (isSkip) return next(); + + let userData: UserData; + + try { + userData = jwt.verify(data.token, process.env.JWT_SECRET || '') as UserData; + } catch { + return next(new Error('Unauthorized')); + } + + data.userData = userData; + + const result = await chatsModel.getChat({ id: data.chat_id, userData }); + + if (!result.success) return next(new Error(result.data)); + + next(); +} + +export function verifyUser(paths: string[]) { + async function middleware(event: Event, next: (_err?: Error | undefined) => void) { + const [path, data] = event; + + if (!paths.includes(path)) { + return next(); + } + + let userData; + + try { + userData = jwt.verify(data.token, process.env.JWT_SECRET || '') as UserData; + } catch { + return next(new Error('Unauthorized')); + } + + data.userData = userData; + + next(); + } + + return middleware; +} + +export default socketMiddleware; diff --git a/src/models/Candles.ts b/src/models/Candles.ts new file mode 100644 index 0000000..065a567 --- /dev/null +++ b/src/models/Candles.ts @@ -0,0 +1,179 @@ +import { Op } from 'sequelize'; +import Period from '../interfaces/common/Period.js'; +import dexModel from './Dex.js'; +import Transaction from '../schemes/Transaction.js'; +import Order from '../schemes/Order.js'; + +class CandlesModel { + async getCandles(pairId: string, period: Period) { + try { + const pairRow = await dexModel.getPairRow(parseInt(pairId, 10)); + + if (!pairRow) return { success: false, data: 'Invalid pair data' }; + + const buyOrders = await Order.findAll({ + where: { + pair_id: pairRow.id, + type: 'buy', + }, + }); + + const buyOrdersIds = buyOrders.map((order) => order.id); + + interface TransactionData { + timestamp: string; + amount: string; + id: number; + price: string; + buy_order_id: number; + } + + const transactions = (await Transaction.findAll({ + where: { + buy_order_id: { + [Op.in]: buyOrdersIds, + }, + status: 'confirmed', + }, + order: [['timestamp', 'ASC']], + attributes: ['timestamp', 'amount', 'id', 'amount', 'buy_order_id'], + }).then((transactions) => + transactions + .map((transaction) => transaction.toJSON()) + .map((transaction) => ({ + ...transaction, + price: buyOrders.find((order) => order.id === transaction.buy_order_id) + ?.price, + })), + )) as TransactionData[]; + + const aggregationPeriod = (() => { + switch (period) { + case '1h': + return 3600000; + case '1d': + return 86400000; + case '1w': + return 604800000; + case '1m': + return 2592000000; + default: + return 3600000; + } + })(); + + interface ResultCandle { + pair_id: number; + timestamp: number; + shadow_top: number; + shadow_bottom: number; + body_first: number; + body_second: number; + } + + const foundCandles = transactions.reduce((acc: ResultCandle[], transaction) => { + const currentTimestamp = parseInt(transaction.timestamp, 10); + + const lastCadle = acc[acc.length - 1]; + + if (!lastCadle) { + return [ + { + pair_id: pairRow.id, + timestamp: currentTimestamp, + shadow_top: parseFloat(transaction.price), + shadow_bottom: parseFloat(transaction.price), + body_first: parseFloat(transaction.price), + body_second: parseFloat(transaction.price), + }, + ]; + } + + if (lastCadle.timestamp + aggregationPeriod < currentTimestamp) { + // creata new candle + const prevCandleEnding = lastCadle.body_second; + return [ + ...acc, + { + pair_id: pairRow.id, + timestamp: currentTimestamp, + shadow_top: parseFloat(transaction.price), + shadow_bottom: parseFloat(transaction.price), + body_first: prevCandleEnding, + body_second: parseFloat(transaction.price), + }, + ]; + } + // add to existing candle + const newCandle = { + ...lastCadle, + shadow_top: Math.max(lastCadle.shadow_top, parseFloat(transaction.price)), + shadow_bottom: Math.min(lastCadle.shadow_bottom, parseFloat(transaction.price)), + body_second: parseFloat(transaction.price), + }; + + acc[acc.length - 1] = newCandle; + + return acc; + }, [] as ResultCandle[]); + + const endTimestamp = Date.now(); + + const completeCandles = []; + let currentTimestamp = + foundCandles[0]?.timestamp || endTimestamp - aggregationPeriod * 10; + let lastRealCandle = { + pair_id: pairRow.id, + timestamp: currentTimestamp, + shadow_top: foundCandles[0]?.body_second || 0, + shadow_bottom: foundCandles[0]?.body_second || 0, + body_first: foundCandles[0]?.body_second || 0, + body_second: foundCandles[0]?.body_second || 0, + }; + + for (let i = 0; i < foundCandles.length; i++) { + const candle = foundCandles[i]; + + // Fill gaps with "empty" candles that replicate the last real candle's values + while (currentTimestamp < candle.timestamp) { + completeCandles.push({ + pair_id: pairRow.id, + timestamp: currentTimestamp, + shadow_top: lastRealCandle.body_second, + shadow_bottom: lastRealCandle.body_second, + body_first: lastRealCandle.body_second, + body_second: lastRealCandle.body_second, + }); + currentTimestamp += aggregationPeriod; + } + + // Add the actual candle + completeCandles.push(candle); + lastRealCandle = candle; // Update last real candle to the current one + currentTimestamp = candle.timestamp + aggregationPeriod; + } + + // Fill any remaining gaps up to the current time (endTimestamp) with the last known real candle's values + while (currentTimestamp <= endTimestamp) { + completeCandles.push({ + pair_id: pairRow.id, + timestamp: currentTimestamp, + shadow_top: lastRealCandle.body_second, + shadow_bottom: lastRealCandle.body_second, + body_first: lastRealCandle.body_second, + body_second: lastRealCandle.body_second, + }); + currentTimestamp += aggregationPeriod; + } + + return { success: true, data: completeCandles || [] }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } +} + +const candlesModel = new CandlesModel(); + +export default candlesModel; diff --git a/src/models/Chats.ts b/src/models/Chats.ts new file mode 100644 index 0000000..b65abf5 --- /dev/null +++ b/src/models/Chats.ts @@ -0,0 +1,450 @@ +import { Op } from 'sequelize'; +import userModel from './User.js'; +import offersModel from './Offers.js'; +import configModel from './Config.js'; +import { runNotificationMethods } from '../socket/main.js'; +import io from '../server.js'; +import GetChatResponse from '../interfaces/responses/chats/chats.js'; +import ErrorResponse from '../interfaces/responses/ErrorResponse.js'; +import CreateBody from '../interfaces/bodies/chats/CreateBody.js'; +import GetChatBody from '../interfaces/bodies/chats/GetChatBody.js'; +import GetAllChatsBody from '../interfaces/bodies/chats/GetAllChatsBody.js'; +import DeleteChatBody from '../interfaces/bodies/chats/DeleteChatBody.js'; +import CreateMessageBody from '../interfaces/bodies/chats/CreateMessageBody.js'; +import DepositSocketData from '../interfaces/special/socket-data/DepositSocketData.js'; +import ChatSocketData from '../interfaces/special/socket-data/ChatSocketData.js'; + +import Chat from '../schemes/Chat.js'; +import User from '../schemes/User.js'; +import Message from '../schemes/Message.js'; +import Offer from '../schemes/Offer.js'; + +class Chats { + private async checkChatAccess(body: GetChatBody) { + const userRow = await userModel.getUserRow(body.userData.address); + + if (!userRow) return { success: false, data: 'User not registered' }; + + const existingChat = await Chat.findOne({ where: { id: body.id } }); + + if (!existingChat) return { success: false, data: 'Invalid chat data' }; + + const offerRow = await offersModel.getOfferRow(existingChat.offer_number); + + if (!offerRow) return { success: false, data: 'Invalid chat data' }; + + if (existingChat.buyer_id !== userRow.id && offerRow.user_id !== userRow.id) + return { success: false, data: 'Unauthorized' }; + + const inputCurrency = await configModel.getCurrencyRow(offerRow.input_currency_id); + const targetCurrency = await configModel.getCurrencyRow(offerRow.target_currency_id); + const depositCurrency = await configModel.getCurrencyRow(offerRow.deposit_currency_id); + + return { + success: true, + offerRow: { + ...offerRow?.toJSON(), + input_currency: inputCurrency, + target_currency: targetCurrency, + deposit_currency: depositCurrency, + }, + existingChat: existingChat?.toJSON() || {}, + userRow: userRow?.toJSON() || {}, + }; + } + + async create(body: CreateBody) { + try { + const userRow = await userModel.getUserRow(body.userData.address); + if (!userRow) return { success: false, data: 'User not registered' }; + + const offerRow = await offersModel.getOfferRow(body.number); + + if (!offerRow) return { success: false, data: 'Invalid offer data' }; + + if (offerRow.user_id === userRow.id) return { success: false, data: 'Same user' }; + + const receiveAmount = + offerRow.type === 'buy' + ? parseFloat(body.chatData.pay) / offerRow.price + : parseFloat(body.chatData.pay); + + if (offerRow.min > receiveAmount || offerRow.max < receiveAmount) { + return { success: false, data: 'Invalid offer data' }; + } + + const existingChat = await Chat.findOne({ + where: { + offer_number: body.number, + buyer_id: userRow.id, + status: { + [Op.not]: 'finished', + }, + }, + }); + + if (existingChat) return { success: true, data: existingChat.id }; + + const chatRow = await Chat.create({ + offer_number: body.number, + buyer_id: userRow.id, + status: 'chatting', + pay: parseFloat(body.chatData.pay), + receive: + offerRow.type === 'buy' + ? parseFloat(body.chatData.pay) / offerRow.price + : parseFloat(body.chatData.pay) * offerRow.price, + }); + + if (!chatRow) throw new Error('Chat not created (database)'); + + runNotificationMethods(io, { userData: body.userData, chat_id: chatRow.id.toString() }); + + return { success: true, data: chatRow.id }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async getChat(body: GetChatBody): Promise { + try { + const result = await this.checkChatAccess(body); + + const { offerRow, existingChat } = result; + + if (!(result.success && offerRow && existingChat)) + return { success: false, data: 'Invalid chat data' }; + + const creatorData = await User.findOne({ where: { id: offerRow.user_id } }); + const buyerData = await User.findOne({ where: { id: existingChat.buyer_id } }); + + if (!(creatorData && buyerData)) { + throw new Error('Error of getting users'); + } + + const messagesAmount = await Message.count({ where: { chat_id: existingChat.id } }); + + return { + success: true, + data: { + creator_data: { + ...(creatorData?.toJSON() || {}), + favourite_currencies: undefined, + }, + buyer_data: { ...(buyerData?.toJSON() || {}), favourite_currencies: undefined }, + ...(offerRow?.toJSON() || {}), + ...(existingChat?.toJSON() || {}), + favourite_currencies: undefined, + chunk_count: Math.ceil(messagesAmount / 20), + }, + }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async getChatChunk(body: GetChatBody & { chunkNumber: number }) { + try { + const result = await this.checkChatAccess(body); + + const { offerRow, existingChat } = result; + + if (!(result.success && offerRow && existingChat)) + return { success: false, data: 'Invalid chat data' }; + + const messages = await Message.findAll({ + where: { + chat_id: existingChat.id, + }, + order: [['timestamp', 'DESC']], + limit: 20, + offset: (body.chunkNumber - 1) * 20, + }); + + return { + success: true, + data: messages.map((e) => ({ + ...e, + fromOwner: !!e.from_owner, + timestamp: e.timestamp, + })), + }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async getAllChats(body: GetAllChatsBody) { + try { + const userRow = await userModel.getUserRow(body.userData.address); + + if (!userRow) return { success: false, data: 'User not registered' }; + + const allChats = await Chat.findAll(); + + const chats = []; + + for (const chat of allChats) { + const offerRow = await offersModel.getOfferRow(chat.offer_number); + if (offerRow && (offerRow.user_id === userRow.id || chat.buyer_id === userRow.id)) { + const inputCurrency = await configModel.getCurrencyRow( + offerRow.input_currency_id, + ); + const targetCurrency = await configModel.getCurrencyRow( + offerRow.target_currency_id, + ); + const depositCurrency = await configModel.getCurrencyRow( + offerRow.deposit_currency_id, + ); + + const creatorData = await User.findOne({ where: { id: offerRow.user_id } }); + const buyerData = await User.findOne({ where: { id: chat.buyer_id } }); + + chats.push({ + creator_data: { + ...(creatorData?.toJSON() || {}), + favourite_currencies: undefined, + id: undefined, + }, + buyer_data: { + ...(buyerData?.toJSON() || {}), + favourite_currencies: undefined, + id: undefined, + }, + ...(offerRow?.toJSON() || {}), + ...(chat?.toJSON() || {}), + chat_history: undefined, + favourite_currencies: undefined, + input_currency: inputCurrency?.toJSON(), + target_currency: targetCurrency?.toJSON(), + deposit_currency: depositCurrency?.toJSON(), + user_id: undefined, + buyer_id: undefined, + }); + } + } + + return { success: true, data: chats }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async createMessage(body: CreateMessageBody) { + try { + const result = await this.checkChatAccess({ + ...body, + chat_id: undefined, + id: body.chat_id, + }); + + const { offerRow, existingChat, userRow } = result; + + if (!(result.success && offerRow && existingChat && userRow)) + return { success: false, data: 'Invalid chat data' }; + + if (existingChat.status === 'finished') + return { success: false, data: 'Chat is finished' }; + + let newMessage; + + if (body.message.type !== 'img') { + newMessage = { + text: body.message.text || '', + timestamp: Date.now(), + from_owner: offerRow.user_id === userRow.id, + success: body.message.success, + fail: body.message.fail, + }; + } else { + newMessage = { + type: 'img', + url: body.message.url, + timestamp: Date.now(), + fromOwner: offerRow.user_id === userRow.id, + success: body.message.success, + fail: body.message.fail, + }; + } + + await Message.create({ + type: newMessage.type === 'img' ? 'img' : 'text', + url: newMessage.url || null, + text: newMessage.text || null, + timestamp: Date.now(), + from_owner: !!newMessage.fromOwner, + success: !!newMessage.success, + fail: !!newMessage.fail, + system: false, + chat_id: existingChat.id, + }); + + return { success: true, message: newMessage }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async deleteChat(body: DeleteChatBody) { + try { + const result = await this.checkChatAccess(body); + + const { existingChat } = result; + + if (!(result.success && existingChat)) return result; + + if ( + (existingChat.owner_deposit !== 'default' && existingChat.owner_deposit !== null) || + (existingChat.opponent_deposit !== 'default' && + existingChat.opponent_deposit !== null) + ) { + return { success: false, data: 'Chat cannot be deleted' }; + } + + await Chat.destroy({ where: { id: body.id } }); + + return { success: true, data: undefined }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async changeDeposit(body: DepositSocketData) { + const result = await this.checkChatAccess({ + ...body, + chat_id: undefined, + id: body.chat_id, + }); + + const { existingChat, offerRow, userRow } = result; + + if (!(result.success && existingChat && offerRow && userRow)) return result; + + const isOwner = existingChat.buyer_id !== userRow.id; + const isBuyer = isOwner === (offerRow.type === 'sell'); + + if (existingChat.status === 'finished') return { success: false, data: 'Chat is finished' }; + + let text: string | null = null; + + const secondState = isOwner ? existingChat.opponent_deposit : existingChat.owner_deposit; + + const previousState = isOwner ? existingChat.owner_deposit : existingChat.opponent_deposit; + + if ( + (previousState === 'default' || previousState === null) && + body.deposit_state === 'deposit' + ) { + text = `${isBuyer ? 'Buyer' : 'Seller'} made a deposit (${isBuyer ? offerRow.deposit_buyer : offerRow.deposit_seller} ${offerRow.deposit_currency?.name || ''})`; + } else if ( + (previousState === 'deposit' || previousState === 'canceled') && + body.deposit_state === 'confirmed' + ) { + text = `${isBuyer ? 'Buyer' : 'Seller'} confirmed the funds were received`; + } else if ( + (previousState === 'deposit' || previousState === 'confirmed') && + body.deposit_state === 'canceled' + ) { + text = `${isBuyer ? 'Buyer' : 'Seller'} canceled funds and return deposit`; + } + + if (!text) return { success: false, data: 'Invalid deposit state' }; + + if (isOwner) { + await Chat.update( + { owner_deposit: body.deposit_state }, + { where: { id: body.chat_id } }, + ); + } else { + await Chat.update( + { opponent_deposit: body.deposit_state }, + { where: { id: body.chat_id } }, + ); + } + + const messageData = await this.createMessage({ + ...body, + message: { + text, + timestamp: Date.now(), + success: body.deposit_state !== 'canceled', + fail: body.deposit_state === 'canceled', + }, + }); + + if (!messageData.success) throw new Error('Message was not created successfuly.'); + + if ( + (body.deposit_state === 'canceled' && + (secondState === 'canceled' || + secondState === 'default' || + secondState === null)) || + (body.deposit_state === 'confirmed' && secondState === 'confirmed') + ) { + await Chat.update({ status: 'finished' }, { where: { id: body.chat_id } }); + } + + if (body.deposit_state === 'confirmed' && secondState === 'confirmed') { + await Offer.update( + { offer_status: 'finished' }, + { where: { number: existingChat.offer_number } }, + ); + } else { + const offerRow = await offersModel.getOfferRow(existingChat.offer_number); + if (offerRow?.offer_status === 'default') { + await Offer.update( + { offer_status: 'process' }, + { where: { number: existingChat.offer_number } }, + ); + } + } + + return { + success: true, + message: messageData.message, + deposits_state: { + fromOwner: isOwner, + state: body.deposit_state, + }, + }; + } + + async setWatched(body: ChatSocketData) { + try { + const result = await this.checkChatAccess({ + ...body, + chat_id: undefined, + id: body.chat_id, + }); + + const { existingChat, userRow } = result; + + if (!(result.success && existingChat && userRow)) return result; + + if (existingChat.view_list?.includes?.(userRow.id)) return { success: true }; + + await Chat.update( + { + view_list: [...(existingChat.view_list || []), userRow.id], + }, + + { where: { id: body.chat_id } }, + ); + + return { success: true }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } +} + +const chatsModel = new Chats(); + +export default chatsModel; diff --git a/src/models/Config.ts b/src/models/Config.ts new file mode 100644 index 0000000..20a2464 --- /dev/null +++ b/src/models/Config.ts @@ -0,0 +1,36 @@ +import ErrorResponse from '../interfaces/responses/ErrorResponse.js'; +import GetConfigRes from '../interfaces/responses/config/config.js'; + +import Currency from '../schemes/Currency.js'; + +class ConfigModel { + async getCurrencyRow(id: number) { + const currency = await Currency.findOne({ + where: { + id, + }, + }); + + return currency; + } + + async get(): Promise { + try { + const selected = await Currency.findAll(); + + return { + success: true, + data: { + currencies: selected, + }, + }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } +} + +const configModel = new ConfigModel(); + +export default configModel; diff --git a/src/models/Dex.ts b/src/models/Dex.ts new file mode 100644 index 0000000..545e2da --- /dev/null +++ b/src/models/Dex.ts @@ -0,0 +1,301 @@ +import Sequelize, { Op, WhereOptions } from 'sequelize'; +import Decimal from 'decimal.js'; +import { PairSortOption } from '@/interfaces/enum/pair.js'; +import Currency from '../schemes/Currency.js'; +import configModel from './Config.js'; +import Pair from '../schemes/Pair.js'; +import Transaction from '../schemes/Transaction.js'; +import Order from '../schemes/Order.js'; +import User from '../schemes/User.js'; + +const PAGE_SIZE = 6; +const BOT_RENEWAL_INTERVAL = 30 * 1000; +const MIN_RENEWAL_INTERVAL = 5 * 1000; + +interface ActiveBot { + orderId: number; + userId: number; + expirationTimestamp: number; +} +class DexModel { + private activeBots: ActiveBot[]; + + constructor() { + this.activeBots = []; + + setInterval(() => { + const now = Date.now(); + + this.activeBots = this.activeBots.filter((bot) => bot.expirationTimestamp > now); + }, BOT_RENEWAL_INTERVAL); + } + + private getPairsSearchCondition(searchText: string, whitelistedOnly: boolean) { + const searchCondition: WhereOptions = { + [Op.and]: [ + { + [Op.or]: [ + Sequelize.where( + Sequelize.fn('LOWER', Sequelize.col('first_currency.name')), + { + [Op.like]: `%${searchText.toLowerCase()}%`, + }, + ), + Sequelize.where( + Sequelize.fn('LOWER', Sequelize.col('second_currency.name')), + { + [Op.like]: `%${searchText.toLowerCase()}%`, + }, + ), + Sequelize.where(Sequelize.col('first_currency.asset_id'), searchText), + Sequelize.where(Sequelize.col('second_currency.asset_id'), searchText), + ], + }, + whitelistedOnly + ? { + [Op.or]: [ + Sequelize.where(Sequelize.col('first_currency.whitelisted'), true), + Sequelize.where(Sequelize.col('second_currency.whitelisted'), true), + Sequelize.where(Sequelize.col('featured'), true), + ], + } + : {}, + ], + }; + + return searchCondition; + } + + async getPairRow(id: number) { + try { + return await Pair.findByPk(id); + } catch (error) { + console.log(error); + } + } + + async getPairsPage( + page: number, + searchText: string, + whitelistedOnly: boolean, + sortOption: PairSortOption, + ) { + try { + const searchCondition = this.getPairsSearchCondition(searchText, whitelistedOnly); + + const volumeSortDirection = + sortOption === PairSortOption.VOLUME_LOW_TO_HIGH ? 'ASC' : 'DESC'; + + const pairs = await Pair.findAll({ + attributes: [ + 'id', + 'first_currency_id', + 'second_currency_id', + 'rate', + 'coefficient', + 'high', + 'low', + 'volume', + 'featured', + ], + include: [ + { + model: Currency, + as: 'first_currency', + attributes: ['asset_id', 'code', 'id', 'name', 'type'], + }, + { + model: Currency, + as: 'second_currency', + attributes: ['asset_id', 'code', 'id', 'name', 'type'], + }, + ], + where: searchCondition, + order: [ + ['volume', volumeSortDirection], + ['id', 'ASC'], + ], + limit: PAGE_SIZE, + offset: (page - 1) * PAGE_SIZE, + subQuery: false, + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const pairsWithCurrencies: any = pairs; + + for (let i = 0; i < pairs.length; i++) { + pairsWithCurrencies[i].first_currency = await configModel.getCurrencyRow( + pairs[i].first_currency_id, + ); + pairsWithCurrencies[i].second_currency = await configModel.getCurrencyRow( + pairs[i].second_currency_id, + ); + } + + return { success: true, data: pairsWithCurrencies }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async getPairsPagesAmount(searchText: string, whitelistedOnly: boolean) { + try { + const searchCondition = this.getPairsSearchCondition(searchText, whitelistedOnly); + + const count = await Pair.count({ + include: [ + { + model: Currency, + as: 'first_currency', + attributes: ['asset_id', 'code', 'id', 'name', 'type'], + }, + { + model: Currency, + as: 'second_currency', + attributes: ['asset_id', 'code', 'id', 'name', 'type'], + }, + ], + where: searchCondition, + }); + + const result = Math.ceil(count / PAGE_SIZE); + + return { success: true, data: result }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async getPair(id: string) { + try { + const pair = await this.getPairRow(parseInt(id, 10)); + + if (!pair) return { success: false, data: 'Invalid pair data' }; + + interface PairWithCurrencies extends Pair { + first_currency?: Currency | null; + second_currency?: Currency | null; + } + + const pairWithCurrencies: Pair = pair; + + const first_currency = await configModel.getCurrencyRow(pair.first_currency_id); + const second_currency = await configModel.getCurrencyRow(pair.second_currency_id); + + const result: PairWithCurrencies = { + ...(pairWithCurrencies?.toJSON() || {}), + first_currency, + second_currency, + } as PairWithCurrencies; + + return { success: true, data: result }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async renewBotExpiration(orderId: number, userId: number) { + const existingBot = this.activeBots.find( + (bot) => bot.orderId === orderId && bot.userId === userId, + ); + + const expirationTimestamp = Date.now() + BOT_RENEWAL_INTERVAL; + + if (existingBot) { + const pastFromLastRenewal = + BOT_RENEWAL_INTERVAL + Date.now() - existingBot.expirationTimestamp; + + if (pastFromLastRenewal < MIN_RENEWAL_INTERVAL) { + return { + success: false, + data: ` + Bot renewal interval is too short. + Minimum interval is ${MIN_RENEWAL_INTERVAL / 1000} seconds. + Maximum interval is ${BOT_RENEWAL_INTERVAL / 1000} seconds. + `, + }; + } + + existingBot.expirationTimestamp = expirationTimestamp; + } else { + this.activeBots.push({ + orderId, + userId, + expirationTimestamp, + }); + } + + return { + success: true, + data: { + expirationTimestamp, + }, + }; + } + + async volumeStats(address: string, pairID: number, from: number, to: number) { + const targetUser = await User.findOne({ + where: { + address, + }, + }); + + if (!targetUser) return { success: false, data: 'User not found' }; + + const allOrders = await Order.findAll({ + where: { + user_id: targetUser.id, + pair_id: pairID, + }, + }); + + const ordersIds = allOrders.map((order) => order.id); + + const transactions = await Transaction.findAll({ + where: { + [Op.or]: [ + { + buy_order_id: { + [Op.in]: ordersIds, + }, + }, + { + sell_order_id: { + [Op.in]: ordersIds, + }, + }, + ], + timestamp: { + [Op.between]: [from, to], + }, + }, + }); + + const volume = transactions.reduce( + (acc, transaction) => new Decimal(acc).add(new Decimal(transaction.amount)), + new Decimal(0), + ); + + return { + success: true, + data: { + volume: volume.toString(), + }, + }; + } + + getActiveBots() { + return this.activeBots; + } + + isBotActive(orderId: number) { + return this.activeBots.some((bot) => bot.orderId === orderId); + } +} + +const dexModel = new DexModel(); + +export default dexModel; diff --git a/src/models/ExchangeTransactions.ts b/src/models/ExchangeTransactions.ts new file mode 100644 index 0000000..e57dd25 --- /dev/null +++ b/src/models/ExchangeTransactions.ts @@ -0,0 +1,295 @@ +import Decimal from 'decimal.js'; +import { Op } from 'sequelize'; +import { sendDeleteOrderMessage, sendUpdatePairStatsMessage } from '../socket/main.js'; +import ordersModel from './Orders.js'; +import userModel from './User.js'; +import io from '../server.js'; +import ConfirmTransactionBody from '../interfaces/bodies/exchange-transactions/ConfirmTransactionBody.js'; +import Transaction from '../schemes/Transaction'; +import Order from '../schemes/Order'; +import Pair from '../schemes/Pair.js'; + +class ExchangeModel { + private async calculatePairStats(pairId: string) { + try { + const date = new Date(); + + const lastTimestamp = date.getTime(); + + date.setHours(date.getHours() - 24); + + const firstTimestamp = date.getTime(); + + const orders = await Order.findAll({ + where: { + pair_id: pairId, + timestamp: { + [Op.gte]: firstTimestamp, + [Op.lte]: lastTimestamp, + }, + }, + order: [['timestamp', 'DESC']], + }); + + const lastOrderPrice = orders[0]?.price || NaN; + const firstOrderPrice = orders.at(-1)?.price || NaN; + + const prices = orders.map((e) => e.price); + + const data = { + rate: new Decimal(lastOrderPrice).toNumber() || 0, + coefficient: + new Decimal(lastOrderPrice).div(firstOrderPrice).minus(1).mul(100).toNumber() || + 0, + high: prices?.length ? Decimal.max(...prices).toNumber() : 0, + low: prices?.length ? Decimal.min(...prices).toNumber() : 0, + volume: 0, + }; + + const transactions = await Transaction.findAll({ + where: { + timestamp: { + [Op.gte]: firstTimestamp, + [Op.lte]: lastTimestamp, + }, + status: 'confirmed', + }, + }); + + for (const transaction of transactions) { + const buyOrder = await ordersModel.getOrderRow(transaction.buy_order_id); + const sellOrder = await ordersModel.getOrderRow(transaction.sell_order_id); + + if (buyOrder && sellOrder && buyOrder.pair_id === parseInt(pairId, 10)) { + const price = Decimal.min(buyOrder.price, sellOrder.price).toFixed(); + data.volume += new Decimal(transaction.amount).mul(price).toNumber(); + } + } + + return { success: true, data }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async returnTransactionAmount(transactionId: number) { + const transactionRow = await Transaction.findByPk(transactionId); + + if (!transactionRow) return console.error('Transaction row not found.'); + + const buyOrder = await ordersModel.getOrderRow(transactionRow.buy_order_id); + + const sellOrder = await ordersModel.getOrderRow(transactionRow.sell_order_id); + + if (!(buyOrder && sellOrder)) return console.error('Buy or sell order not found.'); + + // For debug + const leftBeforeBuyOrder = new Decimal(buyOrder.left).toNumber(); + const leftBeforeSellOrder = new Decimal(sellOrder.left).toNumber(); + // For debug + + const newBuyOrderLeft = Decimal.max( + new Decimal(buyOrder.left).add(transactionRow.amount), + buyOrder.amount, + ).toFixed(); + + const newSellOrderLeft = Decimal.max( + new Decimal(sellOrder.left).add(transactionRow.amount), + ).toFixed(); + + buyOrder.left = newBuyOrderLeft; + sellOrder.left = newSellOrderLeft; + buyOrder.status = 'active'; + sellOrder.status = 'active'; + + console.log( + ` + [Remaining debug] + Buy order left: ${buyOrder.left}, + Sell order left: ${sellOrder.left}, + Transaction amount: ${transactionRow.amount}, + Buy order left before return: ${leftBeforeBuyOrder}, + Sell order left before return: ${leftBeforeSellOrder}, + Buy order ID: ${buyOrder.id}, + Sell order ID: ${sellOrder.id} + `, + ); + + await buyOrder.save(); + await sellOrder.save(); + } + + async createTransaction( + buy_order_id: number, + sell_order_id: number, + amount: string, + creator: string, + hex_raw_proposal: string, + ) { + const timestamp = Date.now(); + + await Transaction.create({ + buy_order_id, + sell_order_id, + amount, + timestamp, + status: 'pending', + creator: creator === 'buy' ? 'buy' : 'sell', + hex_raw_proposal, + }); + } + + // async rejectTransaction(body: ConfirmTransactionBody) { + // try { + // const userData = body.userData; + // const transactionId = body.transactionId; + + // const transaction = await Transaction.findByPk(transactionId); + + // if (!transaction) { + // return { success: false, data: "Transaction doesn't exist." }; + // } + + // if (transaction.status !== "pending") { + // return { success: false, data: "Transaction is not pending" }; + // } + + // const timestamp = Date.now(); + + // const buyOrder = await ordersModel.getOrderRow(transaction.buy_order_id); + // const sellOrder = await ordersModel.getOrderRow(transaction.sell_order_id); + + // if (!(buyOrder && sellOrder)) { + // throw new Error("Buy or sell order not found."); + // } + + // if (! + // ( + // (buyOrder.user_id !== userData.id || + // sellOrder.user_id !== userData.id) + // ) + // ) { + // return { success: false, data: "You are not a participant of this transaction" }; + // } + + // await Transaction.update({ status: "rejected" }, { where: { id: transactionId } }); + + // await Order.update({ left: new Decimal(buyOrder.left).plus(transaction.amount).toFixed(), status: "active" }, { where: { id: buyOrder.id } }); + + // await Order.update({ left: new Decimal(sellOrder.left).plus(transaction.amount).toFixed(), status: "active" }, { where: { id: sellOrder.id } }); + + // } catch(err) { + // console.log(err); + // return { success: false, data: "Internal error" }; + // } + // } + + async confirmTransaction(body: ConfirmTransactionBody) { + try { + const { userData } = body; + const { transactionId } = body; + + const userRow = await userModel.getUserRow(userData.address); + + if (!userRow) { + throw new Error('User not found.'); + } + + const transaction = await Transaction.findByPk(transactionId); + + if (!transaction) { + return { success: false, data: "Transaction doesn't exist." }; + } + + if (transaction.status !== 'pending') { + return { success: false, data: 'Transaction is not pending' }; + } + + const buyOrder = await ordersModel.getOrderRow(transaction.buy_order_id); + const sellOrder = await ordersModel.getOrderRow(transaction.sell_order_id); + + if (!(buyOrder && sellOrder)) { + throw new Error('Buy or sell order not found.'); + } + + if ( + !(transaction.creator === 'sell' + ? buyOrder.user_id === userRow.id + : sellOrder.user_id === userRow.id) + ) { + return { success: false, data: 'You are not a participant of this transaction' }; + } + + await Transaction.update({ status: 'confirmed' }, { where: { id: transactionId } }); + + if (buyOrder.status === 'zero') { + await Order.update({ status: 'finished' }, { where: { id: buyOrder.id } }); + + sendDeleteOrderMessage(io, buyOrder.pair_id.toString(), buyOrder.id.toString()); + } + + if (sellOrder.status === 'zero') { + await Order.update({ status: 'finished' }, { where: { id: sellOrder.id } }); + + sendDeleteOrderMessage(io, sellOrder.pair_id.toString(), sellOrder.id.toString()); + } + + const pairId = buyOrder.pair_id.toString(); + + const statsResult = await this.calculatePairStats(pairId); + + if (!statsResult.success || typeof statsResult.data === 'string') { + throw new Error('Error while getting pair stats'); + } + + const stats = statsResult.data; + + await Pair.update( + { + rate: stats.rate, + coefficient: stats.coefficient, + high: stats.high, + low: stats.low, + volume: stats.volume, + }, + { + where: { + id: pairId, + }, + }, + ); + + sendUpdatePairStatsMessage(io, pairId, stats); + + return { success: true }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async getActiveTxByOrdersIds(firstOrderId: number, secondOrderId: number) { + const txRow = await Transaction.findOne({ + where: { + [Op.or]: [ + { + buy_order_id: firstOrderId, + sell_order_id: secondOrderId, + }, + { + buy_order_id: secondOrderId, + sell_order_id: firstOrderId, + }, + ], + status: 'pending', + }, + }); + + return txRow?.toJSON(); + } +} + +const exchangeModel = new ExchangeModel(); + +export default exchangeModel; diff --git a/src/models/Offers.ts b/src/models/Offers.ts new file mode 100644 index 0000000..b9af754 --- /dev/null +++ b/src/models/Offers.ts @@ -0,0 +1,299 @@ +import { Op } from 'sequelize'; +import DeleteBody from '../interfaces/bodies/offers/DeleteBody.js'; +import { PageData } from '../interfaces/bodies/offers/GetPageBody.js'; +import UpdateBody from '../interfaces/bodies/offers/UpdateBody.js'; +import configModel from './Config.js'; +import userModel from './User.js'; + +import Offer from '../schemes/Offer.js'; +import Currency from '../schemes/Currency.js'; +import User from '../schemes/User.js'; +import { ZANO_ASSET_ID } from '../workers/assetsUpdateChecker.js'; + +function generateOrderNumber(length: number) { + let result = ''; + const characters = '0123456789'; + const charactersLength = characters.length; + let counter = 0; + while (counter < length) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + counter += 1; + } + return result; +} + +class OffersModel { + private async checkOfferAccess(offerId: string | undefined, userId: number) { + const offerRow = await Offer.findOne({ + where: { + number: offerId, + offer_status: ['default', 'process'], + }, + }); + + if (!offerRow) return 'No offer'; + + if (offerRow.user_id !== userId) return 'Forbidden'; + + return 'Update offer'; + } + + async getOfferRow(number: string) { + const selected = await Offer.findOne({ + where: { + number, + }, + }); + + return selected; + } + + async update(body: UpdateBody) { + try { + const userRow = await userModel.getUserRow(body.userData.address); + if (!userRow) return { success: false, data: 'User not registered' }; + + let isFull = true; + + const ZanoCurrencyID = await Currency.findOne({ + where: { + asset_id: ZANO_ASSET_ID, + }, + }); + + const inputCurrency = await Currency.findOne({ + where: { + id: body.offerData.input_currency_id, + type: 'crypto', + }, + }); + + const targetCurrency = await Currency.findOne({ + where: { + id: body.offerData.target_currency_id, + type: 'fiat', + }, + }); + + const depositCurrency = await Currency.findOne({ + where: { + id: body.offerData.deposit_currency_id, + type: 'deposit', + }, + }); + + if (!inputCurrency || !targetCurrency) { + isFull = false; + } + + if ( + !depositCurrency && + parseInt(body.offerData.deposit_currency_id, 10) !== ZanoCurrencyID?.id + ) { + isFull = false; + } + + if (!isFull) return { success: false, data: 'Invalid offer data' }; + + const offerStatus = await this.checkOfferAccess(body.offerData.number, userRow.id); + + if (offerStatus === 'No offer') { + let offerNumber: string; + + // eslint-disable-next-line no-constant-condition + while (true) { + offerNumber = generateOrderNumber(20); + if (!(await this.getOfferRow(offerNumber))) break; + } + + await Offer.create({ + number: offerNumber, + price: body.offerData.price, + min: body.offerData.min, + max: body.offerData.max, + deposit_seller: body.offerData.deposit_seller, + deposit_buyer: body.offerData.deposit_buyer, + user_id: userRow.id, + timestamp: Date.now(), + type: body.offerData.type === 'buy' ? 'buy' : 'sell', + comment: body.offerData.comment || '', + input_currency_id: body.offerData.input_currency_id, + target_currency_id: body.offerData.target_currency_id, + offer_status: 'default', + deposit_currency_id: body.offerData.deposit_currency_id, + }); + + return { success: true }; + } + + return { success: false, data: 'Forbidden' }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async delete(body: DeleteBody) { + try { + const userRow = await userModel.getUserRow(body.userData.address); + if (!userRow) return { success: false, data: 'User not registered' }; + + const offerRow = await this.getOfferRow(body.offerData.number); + + if ( + !offerRow || + offerRow.offer_status === 'hidden' || + offerRow.offer_status === 'finished' || + offerRow.user_id !== userRow.id + ) { + return { success: false, data: 'Offer can not be deleted' }; + } + + if (offerRow.offer_status === 'default') { + await Offer.destroy({ + where: { + number: body.offerData.number, + }, + }); + } + + if (offerRow.offer_status === 'process') { + await Offer.update( + { + offer_status: 'hidden', + }, + { + where: { + number: body.offerData.number, + }, + }, + ); + } + + return { success: true }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async getPage(pageData: PageData) { + try { + const whereConditions = { + [Op.or]: [{ offer_status: 'default' }, { offer_status: 'process' }], + type: pageData.type, + input_currency_id: pageData.input_currency_id + ? pageData.input_currency_id + : { [Op.gt]: 0 }, + target_currency_id: pageData.target_currency_id + ? pageData.target_currency_id + : { [Op.gt]: 0 }, + price: + // eslint-disable-next-line no-self-compare + pageData.price || 0 > 0 + ? { [Op.lte]: pageData.price } + : { [Op.gt]: pageData.price }, + }; + + const count = await Offer.count({ + where: whereConditions, + }); + + const pagesCount = Math.ceil(count / 15); + + const OffersWhereConditions = { + [Op.or]: [{ offer_status: 'default' }, { offer_status: 'process' }], + type: pageData.type, + input_currency_id: pageData.input_currency_id + ? pageData.input_currency_id + : { [Op.gt]: 0 }, + target_currency_id: pageData.target_currency_id + ? pageData.target_currency_id + : { [Op.gt]: 0 }, + price: + // eslint-disable-next-line no-self-compare + pageData.price || 0 > 0 + ? { [Op.lte]: pageData.price } + : { [Op.gt]: pageData.price }, + }; + + const orderCondition = ['price', pageData.priceDescending ? 'DESC' : 'ASC']; + + const offers = await Offer.findAll({ + where: OffersWhereConditions, + + order: [ + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + orderCondition, + ], + limit: 15, + offset: (pageData.page - 1) * 15, + }); + + const offersWithUsers = []; + + for (const offer of offers) { + const user = await User.findOne({ + where: { + id: offer.user_id, + }, + }); + + const inputCurrency = await configModel.getCurrencyRow(offer.input_currency_id); + const targetCurrency = await configModel.getCurrencyRow(offer.target_currency_id); + const depositCurrency = await configModel.getCurrencyRow(offer.deposit_currency_id); + offersWithUsers.push({ + ...offer?.toJSON(), + ...user?.toJSON(), + input_currency: inputCurrency?.toJSON(), + target_currency: targetCurrency?.toJSON(), + deposit_currency: depositCurrency?.toJSON(), + }); + } + + return { success: true, data: { pages: pagesCount, offers: offersWithUsers } }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async getStats() { + async function getVolume(timestamp: number) { + const timestampThreshold = Date.now() - timestamp; + + const result = await Offer.sum('price', { + where: { + timestamp: { + [Op.gt]: timestampThreshold, + }, + }, + }); + + const totalSum = result || 0; + + return totalSum; + } + + const count = await Offer.count({ + where: { + offer_status: 'default', + }, + }); + + return { + success: true, + data: { + opened: count, + volume_24: await getVolume(86400000), + volume_7: await getVolume(604800000), + volume_30: await getVolume(2592000000), + }, + }; + } +} + +const offersModel = new OffersModel(); + +export default offersModel; diff --git a/src/models/Orders.ts b/src/models/Orders.ts new file mode 100644 index 0000000..e87c3b2 --- /dev/null +++ b/src/models/Orders.ts @@ -0,0 +1,580 @@ +import { Op } from 'sequelize'; +import Decimal from 'decimal.js'; +import configModel from './Config.js'; +import dexModel from './Dex.js'; +import userModel from './User.js'; +import exchangeModel from './ExchangeTransactions.js'; +import { + sendDeleteOrderMessage, + sendNewOrderMessage, + sendOrderNotificationCancelation, + sendOrderNotificationMessage, + sendUpdateOrderMessage, +} from '../socket/main.js'; +import io from '../server.js'; +import ApplyTip from '../interfaces/responses/orders/ApplyTip.js'; +import CreateOrderBody from '../interfaces/bodies/orders/CreateOrderBody.js'; +import GetUserOrdersPageBody from '../interfaces/bodies/orders/GetUserOrdersPageBody.js'; +import GetUserOrdersBody from '../interfaces/bodies/orders/GetUserOrdersBody.js'; +import CancelOrderBody from '../interfaces/bodies/orders/CancelOrderBody.js'; +import ApplyOrderBody from '../interfaces/bodies/orders/ApplyOrderBody.js'; +import Order from '../schemes/Order'; +import User from '../schemes/User'; +import Transaction from '../schemes/Transaction'; +import Pair from '../schemes/Pair'; +import OrderData from '../interfaces/special/socket-data/OrderData.js'; +import sequelize from '../sequelize.js'; + +class OrdersModel { + async getOrderRow(id: number) { + try { + return await Order.findByPk(id); + } catch (error) { + console.log(error); + } + } + + async getMatchedOrders(order: Order, pairId: number, requestUserId: number) { + const matchedOrders = await Order.findAll({ + where: { + pair_id: pairId, + type: order.type === 'buy' ? 'sell' : 'buy', + status: 'active', + price: { + [order.type === 'buy' ? Op.lte : Op.gte]: order.price, + }, + user_id: { + [Op.ne]: requestUserId, + }, + }, + order: [['timestamp', 'ASC']], + include: [ + { + model: Pair, + as: 'pair', + include: ['first_currency', 'second_currency'], + }, + 'user', + ], + }); + + return matchedOrders; + } + + async createOrder(body: CreateOrderBody) { + try { + const { orderData } = body; + const { userData } = body; + + const pair = await dexModel.getPairRow(parseInt(orderData.pairId, 10)); + if (!pair) return { success: false, data: 'Invalid order data' }; + + const userRow = await userModel.getUserRow(userData.address); + + if (!userRow) throw new Error('Invalid address from token.'); + + const timestamp = Date.now(); + + const newOrder = await Order.create({ + type: orderData.type === 'buy' ? 'buy' : 'sell', + timestamp, + side: orderData.side === 'limit' ? 'limit' : 'market', + price: new Decimal(orderData.price).toFixed(), + amount: orderData.amount, + total: new Decimal(orderData.price).mul(new Decimal(orderData.amount)).toFixed(), + pair_id: orderData.pairId, + user_id: userRow.id, + status: 'active', + left: new Decimal(orderData.amount).toFixed(), + }); + + if (!newOrder) throw new Error('DB error while creating new order.'); + + const newOrderUser = await userModel.getUserRow(userData.address); + const newOrderPair = await Pair.findByPk(orderData.pairId, { + include: ['first_currency', 'second_currency'], + }); + + if (!newOrderPair) throw new Error('Invalid pair id in order row.'); + if (!newOrderUser) throw new Error('Invalid address from token.'); + + const matchedOrders = await this.getMatchedOrders( + newOrder, + parseInt(orderData.pairId, 10), + userRow.id, + ); + + sendNewOrderMessage(io, orderData.pairId, { + ...(newOrder.toJSON() || {}), + user_id: undefined, + user: { + ...(newOrderUser.toJSON() || {}), + id: undefined, + favourite_currencies: undefined, + }, + pair: newOrderPair.toJSON(), + }); + + for (const matchedOrder of matchedOrders) { + const matchedOrderJSON = matchedOrder.toJSON() as OrderData; + + sendOrderNotificationMessage(io, matchedOrderJSON.user.address, { + ...(newOrder.toJSON() || {}), + user_id: undefined, + user: { + ...(newOrderUser.toJSON() || {}), + id: undefined, + favourite_currencies: undefined, + }, + pair: newOrderPair.toJSON(), + }); + } + + await Order.update( + { + hasNotification: true, + }, + { + where: { + id: { + [Op.in]: matchedOrders.map((e) => e.id), + }, + }, + }, + ); + + if (matchedOrders.length > 0) { + return { + success: true, + data: { + ...newOrder.toJSON(), + immediateMatch: true, + }, + }; + } + + return { success: true, data: newOrder.toJSON() }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async getOrdersPage(pairId: number) { + try { + const pair = await dexModel.getPairRow(pairId); + if (!pair) return { success: false, data: 'Invalid pair data' }; + + const orders = await Order.findAll({ + where: { + pair_id: pairId, + status: 'active', + }, + order: [[sequelize.literal('CAST(price AS DOUBLE PRECISION)'), 'DESC']], + }); + + const ordersWithUsers = []; + + for (const order of orders) { + const userRow = await User.findByPk(order.user_id); + + ordersWithUsers.push({ + ...(order.toJSON() || {}), + user_id: undefined, + user: { + ...(userRow?.toJSON() || {}), + id: undefined, + favourite_currencies: undefined, + }, + isInstant: dexModel.isBotActive(order.id), + }); + } + + return { success: true, data: ordersWithUsers }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + async getUserOrdersPage(body: GetUserOrdersPageBody) { + try { + const userRow = await userModel.getUserRow(body.userData.address); + + if (!userRow) throw new Error('Invalid address from token.'); + + const pair = await dexModel.getPairRow(parseInt(body.pairId, 10)); + + if (!pair) return { success: false, data: 'Invalid pair data' }; + + const orders = ( + await Order.findAll({ + where: { + user_id: userRow.id, + pair_id: body.pairId, + status: { + [Op.ne]: 'finished', + }, + }, + order: [['timestamp', 'DESC']], + }) + ) + .map((e) => e.toJSON()) + .map((e) => ({ + ...e, + isInstant: dexModel.isBotActive(e.id), + })); + + const applyTips: ApplyTip[] = []; + + for (const order of orders.reverse()) { + if (order.status !== 'zero') { + const matchedOrders = await this.getMatchedOrders( + order, + parseInt(body.pairId, 10), + userRow.id, + ); + + for (const matchedOrder of matchedOrders) { + if (!applyTips.some((e) => e.id === matchedOrder.id)) { + const opponentRow = await User.findByPk(matchedOrder.user_id); + + if (!opponentRow) throw new Error('Invalid user id in order row.'); + + applyTips.push({ + id: matchedOrder.id, + left: Decimal.min( + new Decimal(matchedOrder.left), + new Decimal(order.left), + ).toFixed(), + price: matchedOrder.price, + user: { + ...(opponentRow.toJSON() || {}), + id: undefined, + favourite_currencies: undefined, + }, + timestamp: matchedOrder.timestamp, + type: matchedOrder.type, + total: matchedOrder.total, + connected_order_id: order.id, + transaction: false, + isInstant: dexModel.isBotActive(matchedOrder.id), + }); + } + } + } + } + + for (const order of orders) { + const selectedTransactions = await Transaction.findAll({ + where: { + [order.type === 'buy' ? 'buy_order_id' : 'sell_order_id']: order.id, + status: 'pending', + creator: { + [Op.ne]: order.type === 'buy' ? 'buy' : 'sell', + }, + }, + }); + + for (const transaction of selectedTransactions) { + const matchedOrder = await this.getOrderRow( + order.type === 'buy' ? transaction.sell_order_id : transaction.buy_order_id, + ); + + const opponentRow = matchedOrder && (await User.findByPk(matchedOrder.user_id)); + + if (matchedOrder && opponentRow?.address) { + applyTips.push({ + id: transaction.id, + left: transaction.amount, + price: matchedOrder.price, + user: { + ...(opponentRow.toJSON() || {}), + id: undefined, + favourite_currencies: undefined, + }, + type: matchedOrder.type, + total: matchedOrder.total, + connected_order_id: order.id, + transaction: true, + hex_raw_proposal: transaction.hex_raw_proposal, + isInstant: dexModel.isBotActive(matchedOrder.id), + }); + } + } + } + + return { success: true, data: { orders, applyTips } }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async getUserOrders(body: GetUserOrdersBody) { + try { + const userRow = await userModel.getUserRow(body.userData.address); + + if (!userRow) throw new Error('Invalid address from token.'); + + const orders = await Order.findAll({ + where: { + user_id: userRow.id, + }, + order: [['timestamp', 'DESC']], + }); + + const ordersWithCurrencies: Order[] = orders; + + const result = []; + + for (let i = 0; i < orders.length; i++) { + const pairData = await dexModel.getPairRow(orders[i].pair_id); + + if (!pairData) throw new Error('Invalid pair id in order row.'); + + result.push({ + ...(ordersWithCurrencies[i]?.toJSON() || {}), + first_currency: await configModel.getCurrencyRow(pairData.first_currency_id), + second_currency: await configModel.getCurrencyRow(pairData.second_currency_id), + isInstant: dexModel.isBotActive(ordersWithCurrencies[i].id), + }); + } + + return { success: true, data: result }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async cancelOrder(body: CancelOrderBody) { + try { + const userRow = await userModel.getUserRow(body.userData.address); + + if (!userRow) throw new Error('Invalid address from token.'); + + const orderRow = await Order.findOne({ + where: { + id: body.orderId, + status: { + [Op.ne]: 'finished', + }, + user_id: userRow.id, + }, + }); + + if (!orderRow) { + return { success: false, data: 'Invalid order data' }; + } + + await this.cancelOrderNotifications(orderRow, userRow); + + const eps = new Decimal(1e-8); + const leftDecimal = new Decimal(orderRow.left); + const amountDecimal = new Decimal(orderRow.amount); + + // if order was partially filled + if (leftDecimal.minus(amountDecimal).abs().greaterThan(eps)) { + const connectedTransactions = await Transaction.findAll({ + where: { + [Op.or]: [{ buy_order_id: orderRow.id }, { sell_order_id: orderRow.id }], + status: 'pending', + }, + }); + + for (const transaction of connectedTransactions) { + await exchangeModel.returnTransactionAmount(transaction.id); + } + + await Order.update( + { status: 'finished' }, + { where: { id: body.orderId, user_id: userRow.id } }, + ); + } else { + await Order.destroy({ + where: { + id: body.orderId, + user_id: userRow.id, + }, + }); + } + + await Transaction.update( + { status: 'rejected' }, + { + where: { + [Op.or]: [{ buy_order_id: orderRow.id }, { sell_order_id: orderRow.id }], + [Op.not]: { + status: 'confirmed', + }, + }, + }, + ); + + sendDeleteOrderMessage(io, orderRow.pair_id.toString(), orderRow.id.toString()); + + return { success: true }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async cancelOrderNotifications(orderRow: Order, userRow: User) { + const matchedOrders = await this.getMatchedOrders(orderRow, orderRow.pair_id, -1); + + const affectedUserIDs = matchedOrders.map((e) => e.user_id); + + const affectedUsers = ( + await User.findAll({ + where: { + id: affectedUserIDs, + }, + }) + ).map((e) => e.toJSON()); + + for (const affectedUser of [...affectedUsers, userRow.toJSON()]) { + for (const element of matchedOrders.map((e) => e.toJSON())) { + sendOrderNotificationCancelation(io, affectedUser.address, element.id); + } + + sendOrderNotificationCancelation(io, affectedUser.address, orderRow.id); + } + } + + async getChartOrders(pairId: string) { + try { + const date = new Date(); + + const lastTimestamp = date.getTime(); + + date.setHours(date.getHours() - 24); + + const firstTimestamp = date.getTime(); + + const orders = await Order.findAll({ + where: { + pair_id: pairId, + timestamp: { + [Op.gte]: firstTimestamp, + [Op.lte]: lastTimestamp, + }, + }, + order: [['timestamp', 'DESC']], + }); + + return { success: true, data: orders }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async getPairStats(pairId: string) { + try { + const pair = await Pair.findOne({ + where: { + id: pairId, + }, + }); + + return { + success: true, + data: { + rate: pair?.rate || 0, + coefficient: pair?.coefficient || 0, + high: pair?.high || 0, + low: pair?.low || 0, + volume: pair?.volume || 0, + }, + }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async applyOrder(body: ApplyOrderBody) { + try { + const { userData } = body; + const { orderData } = body; + + const userRow = await userModel.getUserRow(userData.address); + + if (!userRow) throw new Error('Invalid address from token.'); + + const orderRow = await Order.findByPk(orderData.connected_order_id); + + const applyingOrderRow = await Order.findOne({ + where: { + id: orderData.id, + status: 'active', + user_id: { + [Op.ne]: userRow.id, + }, + }, + }); + + if ( + !( + orderRow && + applyingOrderRow && + orderRow.pair_id === applyingOrderRow.pair_id && + orderRow.type !== applyingOrderRow.type && + ((orderRow.type === 'buy') === orderRow.price >= applyingOrderRow.price || + orderRow.price === applyingOrderRow.price) + ) + ) { + return { success: false, data: 'Invalid order data' }; + } + + const transactionAmount = Decimal.min(orderRow.left, applyingOrderRow.left); + const isApplyingBuy = applyingOrderRow.type === 'buy'; + + await Order.update( + { left: new Decimal(orderRow.left).minus(transactionAmount).toNumber() }, + { where: { id: orderRow.id } }, + ); + + await Order.update( + { + left: new Decimal(applyingOrderRow.left).minus(transactionAmount).toNumber(), + }, + { + where: { + id: applyingOrderRow.id, + }, + }, + ); + + const eps = new Decimal(1e-10); + + if (new Decimal(orderRow.left).minus(transactionAmount).abs().lt(eps)) { + await Order.update({ status: 'zero' }, { where: { id: orderRow.id } }); + } + + if (new Decimal(applyingOrderRow.left).minus(transactionAmount).abs().lt(eps)) { + await Order.update({ status: 'zero' }, { where: { id: applyingOrderRow.id } }); + } + + await exchangeModel.createTransaction( + isApplyingBuy ? applyingOrderRow.id : orderRow.id, + isApplyingBuy ? orderRow.id : applyingOrderRow.id, + transactionAmount.toFixed(), + orderRow.type, + orderData.hex_raw_proposal, + ); + + sendUpdateOrderMessage(io, orderRow.pair_id.toString()); + + return { success: true }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } +} + +const ordersModel = new OrdersModel(); + +export default ordersModel; diff --git a/src/models/User.ts b/src/models/User.ts new file mode 100644 index 0000000..999ab65 --- /dev/null +++ b/src/models/User.ts @@ -0,0 +1,190 @@ +import { Op } from 'sequelize'; +import Offer from '../schemes/Offer'; +import GetUserBody from '../interfaces/bodies/user/GetUserBody'; +import SetFavouriteCurrsBody from '../interfaces/bodies/user/SetFavouriteCurrsBody'; +import UserData from '../interfaces/common/UserData'; +import chatsModel from './Chats'; +import configModel from './Config'; +import User from '../schemes/User'; +import Order from '../schemes/Order'; +import Pair from '../schemes/Pair'; + +class UserModel { + async getUserRow(address: string) { + const selected = User.findOne({ where: { address } }); + return selected; + } + + async add(userData: UserData) { + try { + const userRow = await this.getUserRow(userData.address); + if (userRow) return true; + + const oldAddressOfCurrentAlias = await User.findOne({ + where: { alias: userData.alias }, + }); + + if (oldAddressOfCurrentAlias) { + await User.update( + { address: userData.address }, + { where: { alias: userData.alias } }, + ); + return true; + } + + await User.create({ alias: userData.alias, address: userData.address }); + + return true; + } catch (err) { + console.log(err); + return false; + } + } + + async getUser(userData: GetUserBody) { + try { + const userRow = await this.getUserRow(userData.address); + if (!userRow) return { success: false, data: 'User not registered' }; + + const offers = await Offer.findAll({ + where: { user_id: userRow.id, offer_status: { [Op.not]: ['finished', 'hidden'] } }, + }); + + const offersWithCurrs = []; + + for (const offer of offers) { + const inputCurrency = await configModel.getCurrencyRow(offer.input_currency_id); + const targetCurrency = await configModel.getCurrencyRow(offer.target_currency_id); + const depositCurrency = await configModel.getCurrencyRow(offer.deposit_currency_id); + + const creatorRow = await User.findByPk(offer.user_id); + + if (creatorRow) { + offersWithCurrs.push({ + ...(offer?.toJSON() || {}), + input_currency: inputCurrency?.toJSON(), + target_currency: targetCurrency?.toJSON(), + deposit_currency: depositCurrency?.toJSON(), + alias: creatorRow.alias, + address: creatorRow.address, + }); + } + } + + const chats = await chatsModel.getAllChats({ userData }); + + return { + success: true, + data: { + ...userRow?.toJSON(), + offers: offersWithCurrs, + chats: chats.data, + exchange_notifications: (await this.getNotificationsAmount(userData)).data, + }, + }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async setFavouriteCurrencies(body: SetFavouriteCurrsBody) { + try { + const userRow = await this.getUserRow(body.userData.address); + if (!userRow) return { success: false, data: 'User not registered' }; + + await User.update( + { favourite_currencies: body.data }, + { where: { address: body.userData.address } }, + ); + return { success: true }; + } catch (err) { + console.log(err); + return { success: false, data: 'Internal error' }; + } + } + + async resetExchangeNotificationsAmount(address: string) { + const user = await User.findOne({ + where: { + address, + }, + }); + + await Order.update( + { + hasNotification: false, + }, + { + where: { + user_id: user?.id, + hasNotification: true, + }, + }, + ); + } + + async getNotificationsAmount(userData: GetUserBody) { + const user = await User.findOne({ + where: { + address: userData.address, + }, + }); + + if (!user) { + return { success: false, data: 'User not found' }; + } + + const amount = await Order.count({ + where: { + user_id: user.id, + hasNotification: true, + }, + }); + + return { success: true, data: amount }; + } + + async resetNotificationsForPair(address: string, pair_id: number) { + const user = await User.findOne({ + where: { + address, + }, + }); + + const pair = await Pair.findOne({ + where: { + id: pair_id, + }, + }); + + if (!user || !pair) { + return { success: false, data: 'User or Pair not found' }; + } + + const orderToUpdate = await Order.findOne({ + where: { + user_id: user.id, + pair_id: pair.id, + }, + }); + + if (orderToUpdate) { + orderToUpdate.hasNotification = false; + await orderToUpdate.save(); + } + + // await Order.update({ + // hasNotification: false + // }, { + // where: { + // user_id: user.id, + // pair_id: pair_id, + // } + // }); + } +} + +const userModel = new UserModel(); + +export default userModel; diff --git a/src/routes/admin.router.ts b/src/routes/admin.router.ts new file mode 100644 index 0000000..7823787 --- /dev/null +++ b/src/routes/admin.router.ts @@ -0,0 +1,103 @@ +import middleware from '@/middleware/middleware'; +import Currency from '@/schemes/Currency'; +import Pair from '@/schemes/Pair'; +import User from '@/schemes/User'; +import express from 'express'; + +const adminRouter = express.Router(); + +adminRouter.use(middleware.verifyToken, middleware.verifyAdmin); + +adminRouter.post('/check-admin', (req, res) => { + res.send({ success: true, data: 'You are an admin' }); +}); + +adminRouter.post('/get-admins', async (req, res) => { + const owner = await User.findOne({ where: { alias: process.env.OWNER_ALIAS } }); + + const admins = await User.findAll({ + where: { + isAdmin: true, + }, + }); + + const preparedAdmins = admins.map((admin) => ({ + id: admin.id, + alias: admin.alias, + isOwner: admin.id === owner?.id, + })); + + res.send({ success: true, data: preparedAdmins }); +}); + +adminRouter.post('/delete-admin', async (req, res) => { + const admin = await User.findOne({ where: { id: req.body.id || null } }); + + if (!admin) { + return res.send({ success: false, message: 'Admin not found' }); + } + + if (admin.alias === process.env.OWNER_ALIAS) { + return res.send({ success: false, message: "You can't delete owner" }); + } + + await admin.update({ isAdmin: false }); + + res.send({ success: true, message: 'Admin deleted' }); +}); + +adminRouter.post('/add-admin', async (req, res) => { + const admin = await User.findOne({ where: { alias: req.body.alias || null } }); + + if (!admin) { + return res.send({ success: false, message: 'Admin not found' }); + } + + await admin.update({ isAdmin: true }); + + res.send({ success: true, message: 'Admin updated' }); +}); + +adminRouter.post('/get-featured', async (req, res) => { + const pairs = await Pair.findAll({ + where: { + featured: true, + }, + include: [ + { + model: Currency, + as: 'first_currency', + }, + ], + }); + + res.send({ success: true, data: pairs }); +}); + +adminRouter.post('/delete-featured', async (req, res) => { + const pair = await Pair.findOne({ where: { id: req.body.id } }); + + if (!pair) { + return res.send({ success: false, message: 'Pair not found' }); + } + + await pair.update({ featured: false }); + + res.send({ success: true, message: 'Pair deleted' }); +}); + +adminRouter.post('/add-featured', async (req, res) => { + const currency = await Currency.findOne({ where: { asset_id: req.body.asset_id } }); + + const pair = await Pair.findOne({ where: { first_currency_id: currency?.id || null } }); + + if (!pair) { + return res.send({ success: false, message: 'Pair not found' }); + } + + await pair.update({ featured: true }); + + res.send({ success: true, message: 'Pair updated' }); +}); + +export default adminRouter; diff --git a/src/routes/auth.router.ts b/src/routes/auth.router.ts new file mode 100644 index 0000000..77dfc5b --- /dev/null +++ b/src/routes/auth.router.ts @@ -0,0 +1,8 @@ +import express from 'express'; +import authController from '../controllers/auth.controller.js'; + +const authRouter = express.Router(); + +authRouter.post('/auth', authController.auth); + +export default authRouter; diff --git a/src/routes/chats.router.ts b/src/routes/chats.router.ts new file mode 100644 index 0000000..5ef184f --- /dev/null +++ b/src/routes/chats.router.ts @@ -0,0 +1,23 @@ +import express from 'express'; +import chatsController from '../controllers/chats.controller.js'; +import middleware from '../middleware/middleware.js'; + +const chatsRouter = express.Router(); + +chatsRouter.use( + [ + '/chats/create', + '/chats/get-chat', + '/chats/get-all-chats', + '/chats/delete-chat', + '/chats/get-chat-chunk', + ], + middleware.verifyToken, +); +chatsRouter.post('/chats/create', chatsController.create); +chatsRouter.post('/chats/get-chat', chatsController.getChat); +chatsRouter.post('/chats/get-chat-chunk', chatsController.getChatChunk); +chatsRouter.post('/chats/get-all-chats', chatsController.getAllChats); +chatsRouter.post('/chats/delete-chat', chatsController.deleteChat); + +export default chatsRouter; diff --git a/src/routes/config.router.ts b/src/routes/config.router.ts new file mode 100644 index 0000000..b730178 --- /dev/null +++ b/src/routes/config.router.ts @@ -0,0 +1,8 @@ +import express from 'express'; +import configController from '../controllers/config.controller.js'; + +const configRouter = express.Router(); + +configRouter.get('/config', configController.get); + +export default configRouter; diff --git a/src/routes/dex.router.ts b/src/routes/dex.router.ts new file mode 100644 index 0000000..ca0b6c7 --- /dev/null +++ b/src/routes/dex.router.ts @@ -0,0 +1,15 @@ +import express from 'express'; +import dexController from '../controllers/dex.controller.js'; +import middleware from '../middleware/middleware.js'; + +const dexRouter = express.Router(); + +dexRouter.post('/dex/get-pairs-page', dexController.getPairsPage); +dexRouter.post('/dex/get-pairs-pages-amount', dexController.getPairsPagesAmount); +dexRouter.post('/dex/get-pair', dexController.getPair); +dexRouter.post('/dex/renew-bot', middleware.verifyToken, dexController.registerBot); +dexRouter.post('/dex/volume-stats', dexController.volumeStats); +dexRouter.post('/dex/get-assets-price-rates', dexController.getAssetsPriceRates); +dexRouter.post('/dex/find-pair', dexController.findPairID); + +export default dexRouter; diff --git a/src/routes/offers.router.ts b/src/routes/offers.router.ts new file mode 100644 index 0000000..6ae84cc --- /dev/null +++ b/src/routes/offers.router.ts @@ -0,0 +1,14 @@ +import express from 'express'; +import offersController from '../controllers/offers.controller.js'; +import middleware from '../middleware/middleware.js'; + +const offersRouter = express.Router(); + +offersRouter.use(['/offers/update', '/offers/delete', '/offers/get-one'], middleware.verifyToken); +// offersRouter.post("/offers/get-all", offersController.getAll); +offersRouter.post('/offers/get-page', offersController.getPage); +offersRouter.post('/offers/update', offersController.update); +offersRouter.post('/offers/delete', offersController.delete); +offersRouter.get('/offers/get-stats', offersController.getStats); + +export default offersRouter; diff --git a/src/routes/orders.router.ts b/src/routes/orders.router.ts new file mode 100644 index 0000000..5c9883a --- /dev/null +++ b/src/routes/orders.router.ts @@ -0,0 +1,28 @@ +import express from 'express'; +import middleware from '../middleware/middleware.js'; +import ordersController from '../controllers/orders.controller.js'; + +const ordersRouter = express.Router(); + +ordersRouter.use( + [ + '/orders/create', + '/orders/get-user-page', + '/orders/get', + '/orders/cancel', + '/orders/apply-order', + ], + middleware.verifyToken, +); + +ordersRouter.post('/orders/create', ordersController.createOrder); +ordersRouter.post('/orders/get-page', ordersController.getOrdersPage); +ordersRouter.post('/orders/get-user-page', ordersController.getUserOrdersPage); +ordersRouter.post('/orders/get', ordersController.getUserOrders); +ordersRouter.post('/orders/cancel', ordersController.cancelOrder); +ordersRouter.post('/orders/get-candles', ordersController.getCandles); +ordersRouter.post('/orders/get-chart-orders', ordersController.getChartOrders); +ordersRouter.post('/orders/get-pair-stats', ordersController.getPairStats); +ordersRouter.post('/orders/apply-order', ordersController.applyOrder); + +export default ordersRouter; diff --git a/src/routes/transactions.router.ts b/src/routes/transactions.router.ts new file mode 100644 index 0000000..6197017 --- /dev/null +++ b/src/routes/transactions.router.ts @@ -0,0 +1,15 @@ +import express from 'express'; +import transactionsController from '../controllers/transactions.controller.js'; +import middleware from '../middleware/middleware.js'; + +const transactionsRouter = express.Router(); + +transactionsRouter.use('/transactions/*', middleware.verifyToken); + +transactionsRouter.post('/transactions/confirm', transactionsController.confirmTransaction); +transactionsRouter.post( + '/transactions/get-active-tx-by-orders-ids', + transactionsController.getActiveTxByOrdersIds, +); + +export default transactionsRouter; diff --git a/src/routes/user.router.ts b/src/routes/user.router.ts new file mode 100644 index 0000000..7e9ec44 --- /dev/null +++ b/src/routes/user.router.ts @@ -0,0 +1,12 @@ +import express from 'express'; +import userController from '../controllers/user.controller.js'; +import middleware from '../middleware/middleware.js'; + +const userRouter = express.Router(); + +userRouter.use('/user', middleware.verifyToken); +userRouter.post('/user/get-user', userController.getUser); +userRouter.post('/user/get-notifications-amount', userController.getNotificationsAmount); +userRouter.post('/user/set-favourite-currencies', userController.setFavouriteCurrencies); + +export default userRouter; diff --git a/src/schemes/Chat.ts b/src/schemes/Chat.ts new file mode 100644 index 0000000..6b9d6cb --- /dev/null +++ b/src/schemes/Chat.ts @@ -0,0 +1,86 @@ +import { Model, DataTypes } from 'sequelize'; +import sequelize from '../sequelize'; +import Message from './Message'; + +class Chat extends Model { + declare readonly id: number; + + declare offer_number: string; + + declare user_id: number; + + declare buyer_id: number; + + declare status: string; + + declare pay: number; + + declare receive: number; + + declare owner_deposit: string; + + declare opponent_deposit: string; + + declare view_list: number[]; + + declare readonly createdAt: Date; + + declare readonly updatedAt: Date; +} + +Chat.init( + { + id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, + offer_number: { + type: DataTypes.STRING, + allowNull: false, + }, + user_id: { + type: DataTypes.INTEGER, + allowNull: false, + }, + buyer_id: { + type: DataTypes.INTEGER, + allowNull: false, + }, + status: { + type: DataTypes.STRING, + allowNull: false, + }, + pay: { + type: DataTypes.DOUBLE, + allowNull: false, + }, + receive: { + type: DataTypes.DOUBLE, + allowNull: false, + }, + owner_deposit: { + type: DataTypes.STRING, + allowNull: false, + }, + opponent_deposit: { + type: DataTypes.STRING, + allowNull: false, + }, + view_list: { + type: DataTypes.ARRAY(DataTypes.INTEGER), + allowNull: false, + }, + }, + { + sequelize, + modelName: 'Chat', + timestamps: true, + }, +); + +Chat.hasMany(Message, { + foreignKey: 'chat_id', + as: 'messages', + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + hooks: true, +}); + +export default Chat; diff --git a/src/schemes/Currency.ts b/src/schemes/Currency.ts new file mode 100644 index 0000000..60cb1cb --- /dev/null +++ b/src/schemes/Currency.ts @@ -0,0 +1,112 @@ +import { Model, DataTypes } from 'sequelize'; +import sequelize from '../sequelize'; +import Pair from './Pair'; + +export interface Asset { + asset_id: string; + logo: string; + price_url: string; + ticker: string; + full_name: string; + total_max_supply: bigint; + current_supply: bigint; + decimal_point: number; + meta_info: string; +} + +class Currency extends Model { + declare readonly id: number; + + declare name: string; + + declare code: string; + + declare type: string; + + declare asset_id: string; + + declare auto_parsed: boolean; + + declare asset_info?: Asset; + + declare whitelisted: boolean; + + declare readonly createdAt: Date; + + declare readonly updatedAt: Date; +} + +Currency.init( + { + id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, + name: { + type: DataTypes.STRING, + allowNull: false, + }, + code: { + type: DataTypes.STRING, + allowNull: false, + }, + type: { + type: DataTypes.STRING, + allowNull: false, + }, + asset_id: { + type: DataTypes.STRING, + allowNull: false, + }, + auto_parsed: { + type: DataTypes.BOOLEAN, + allowNull: false, + }, + asset_info: { + type: DataTypes.JSONB, + allowNull: true, + }, + whitelisted: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + }, + { + sequelize, + modelName: 'Currency', + timestamps: true, + }, +); + +Currency.hasMany(Pair, { + foreignKey: 'first_currency_id', + as: 'first_currency', + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + hooks: true, + constraints: false, +}); + +Currency.hasMany(Pair, { + foreignKey: 'second_currency_id', + as: 'second_currency', + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + hooks: true, + constraints: false, +}); + +Pair.belongsTo(Currency, { + foreignKey: 'first_currency_id', + as: 'first_currency', + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + hooks: true, +}); +Pair.belongsTo(Currency, { + foreignKey: 'second_currency_id', + as: 'second_currency', + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + hooks: true, +}); + +export default Currency; diff --git a/src/schemes/Message.ts b/src/schemes/Message.ts new file mode 100644 index 0000000..3563405 --- /dev/null +++ b/src/schemes/Message.ts @@ -0,0 +1,77 @@ +import { Model, DataTypes } from 'sequelize'; +import sequelize from '../sequelize'; + +class Message extends Model { + declare readonly id: number; + + declare type: string; + + declare url: string; + + declare text: string; + + declare timestamp: number; + + declare from_owner: boolean; + + declare success: boolean; + + declare fail: boolean; + + declare system: boolean; + + declare chat_id: number; + + declare readonly createdAt: Date; + + declare readonly updatedAt: Date; +} + +Message.init( + { + id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, + type: { + type: DataTypes.STRING, + allowNull: false, + }, + url: { + type: DataTypes.STRING, + allowNull: true, + }, + text: { + type: DataTypes.STRING, + allowNull: true, + }, + timestamp: { + type: DataTypes.BIGINT, + allowNull: false, + }, + from_owner: { + type: DataTypes.BOOLEAN, + allowNull: false, + }, + success: { + type: DataTypes.BOOLEAN, + allowNull: false, + }, + fail: { + type: DataTypes.BOOLEAN, + allowNull: false, + }, + system: { + type: DataTypes.BOOLEAN, + allowNull: false, + }, + chat_id: { + type: DataTypes.INTEGER, + allowNull: false, + }, + }, + { + sequelize, + modelName: 'Message', + timestamps: true, + }, +); + +export default Message; diff --git a/src/schemes/Offer.ts b/src/schemes/Offer.ts new file mode 100644 index 0000000..5f9667c --- /dev/null +++ b/src/schemes/Offer.ts @@ -0,0 +1,118 @@ +import { Model, DataTypes } from 'sequelize'; +import sequelize from '../sequelize'; +import Chat from './Chat'; + +class Offer extends Model { + declare readonly id: number; + + declare price: number; + + declare min: number; + + declare max: number; + + declare deposit_seller: number; + + declare deposit_buyer: number; + + declare user_id: number; + + declare type: string; + + declare comment: string; + + declare input_currency_id: number; + + declare target_currency_id: number; + + declare number: string; + + declare offer_status: string; + + declare deposit_currency_id: number; + + declare timestamp: bigint; + + declare readonly createdAt: Date; + + declare readonly updatedAt: Date; +} + +Offer.init( + { + id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, + price: { + type: DataTypes.DOUBLE, + allowNull: false, + }, + min: { + type: DataTypes.DOUBLE, + allowNull: false, + }, + max: { + type: DataTypes.DOUBLE, + allowNull: false, + }, + deposit_seller: { + type: DataTypes.DOUBLE, + allowNull: false, + }, + deposit_buyer: { + type: DataTypes.DOUBLE, + allowNull: false, + }, + user_id: { + type: DataTypes.INTEGER, + allowNull: false, + }, + type: { + type: DataTypes.STRING, + allowNull: false, + }, + comment: { + type: DataTypes.STRING, + allowNull: false, + }, + input_currency_id: { + type: DataTypes.INTEGER, + allowNull: false, + }, + target_currency_id: { + type: DataTypes.INTEGER, + allowNull: false, + }, + number: { + type: DataTypes.STRING, + allowNull: false, + unique: true, + }, + offer_status: { + type: DataTypes.STRING, + allowNull: false, + }, + deposit_currency_id: { + type: DataTypes.INTEGER, + allowNull: false, + }, + timestamp: { + type: DataTypes.BIGINT, + allowNull: false, + }, + }, + { + sequelize, + modelName: 'Offer', + timestamps: true, + }, +); + +Offer.hasMany(Chat, { + foreignKey: 'offer_number', + sourceKey: 'number', + as: 'chats', + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + hooks: true, +}); + +export default Offer; diff --git a/src/schemes/Order.ts b/src/schemes/Order.ts new file mode 100644 index 0000000..36e722f --- /dev/null +++ b/src/schemes/Order.ts @@ -0,0 +1,119 @@ +import { Model, DataTypes } from 'sequelize'; +import sequelize from '../sequelize'; +import Transaction from './Transaction'; +import Pair from './Pair'; + +class Order extends Model { + declare readonly id: number; + + declare type: string; + + declare timestamp: number; + + declare side: string; + + declare price: string; + + declare amount: string; + + declare total: string; + + declare pair_id: number; + + declare user_id: number; + + declare status: string; + + declare left: string; + + declare hasNotification: boolean; + + declare readonly createdAt: Date; + + declare readonly updatedAt: Date; +} + +Order.init( + { + id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, + type: { + type: DataTypes.STRING, + allowNull: false, + }, + timestamp: { + type: DataTypes.BIGINT, + allowNull: false, + }, + side: { + type: DataTypes.STRING, + allowNull: false, + }, + price: { + type: DataTypes.STRING, + allowNull: false, + }, + amount: { + type: DataTypes.STRING, + allowNull: false, + }, + total: { + type: DataTypes.STRING, + allowNull: false, + }, + pair_id: { + type: DataTypes.INTEGER, + allowNull: false, + }, + user_id: { + type: DataTypes.INTEGER, + allowNull: false, + }, + status: { + type: DataTypes.STRING, + allowNull: false, + }, + left: { + type: DataTypes.STRING, + allowNull: false, + }, + hasNotification: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + }, + { + sequelize, + modelName: 'Order', + timestamps: true, + }, +); + +Order.hasMany(Transaction, { + foreignKey: 'buy_order_id', + as: 'buy_orders', + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + hooks: true, + constraints: false, +}); + +Order.hasMany(Transaction, { + foreignKey: 'sell_order_id', + as: 'sell_orders', + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + hooks: true, + constraints: false, +}); + +Order.belongsTo(Pair, { + foreignKey: 'pair_id', + as: 'pair', + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + hooks: true, + constraints: false, +}); + +export default Order; diff --git a/src/schemes/Pair.ts b/src/schemes/Pair.ts new file mode 100644 index 0000000..47b89d2 --- /dev/null +++ b/src/schemes/Pair.ts @@ -0,0 +1,69 @@ +import { Model, DataTypes } from 'sequelize'; +import sequelize from '../sequelize'; + +class Pair extends Model { + declare readonly id: number; + + declare first_currency_id: number; + + declare second_currency_id: number; + + declare rate?: number; + + declare coefficient?: number; + + declare high?: number; + + declare low?: number; + + declare volume: number; + + declare featured: boolean; + + declare readonly createdAt: Date; + + declare readonly updatedAt: Date; +} + +Pair.init( + { + id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, + first_currency_id: { + type: DataTypes.INTEGER, + allowNull: false, + }, + second_currency_id: { + type: DataTypes.INTEGER, + allowNull: false, + }, + rate: { + type: DataTypes.DOUBLE, + }, + coefficient: { + type: DataTypes.DOUBLE, + }, + high: { + type: DataTypes.DOUBLE, + }, + low: { + type: DataTypes.DOUBLE, + }, + volume: { + type: DataTypes.DOUBLE, + defaultValue: 0, + allowNull: false, + }, + featured: { + type: DataTypes.BOOLEAN, + defaultValue: false, + allowNull: false, + }, + }, + { + sequelize, + modelName: 'Pair', + timestamps: true, + }, +); + +export default Pair; diff --git a/src/schemes/Transaction.ts b/src/schemes/Transaction.ts new file mode 100644 index 0000000..0b8fdcd --- /dev/null +++ b/src/schemes/Transaction.ts @@ -0,0 +1,65 @@ +import { Model, DataTypes } from 'sequelize'; +import sequelize from '../sequelize'; + +class Transaction extends Model { + declare readonly id: number; + + declare buy_order_id: number; + + declare sell_order_id: number; + + declare amount: string; + + declare timestamp: number; + + declare status: string; + + declare creator: string; + + declare hex_raw_proposal: string; + + declare readonly createdAt: Date; + + declare readonly updatedAt: Date; +} + +Transaction.init( + { + id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, + buy_order_id: { + type: DataTypes.INTEGER, + allowNull: false, + }, + sell_order_id: { + type: DataTypes.INTEGER, + allowNull: false, + }, + amount: { + type: DataTypes.STRING, + allowNull: false, + }, + timestamp: { + type: DataTypes.BIGINT, + allowNull: false, + }, + status: { + type: DataTypes.STRING, + allowNull: false, + }, + creator: { + type: DataTypes.STRING, + allowNull: false, + }, + hex_raw_proposal: { + type: DataTypes.TEXT, + allowNull: false, + }, + }, + { + sequelize, + modelName: 'Transaction', + timestamps: true, + }, +); + +export default Transaction; diff --git a/src/schemes/User.ts b/src/schemes/User.ts new file mode 100644 index 0000000..20b8997 --- /dev/null +++ b/src/schemes/User.ts @@ -0,0 +1,79 @@ +import { Model, DataTypes } from 'sequelize'; +import sequelize from '../sequelize'; + +import Offer from './Offer'; +import Order from './Order'; + +class User extends Model { + declare readonly id: number; + + declare alias: string; + + declare address: string; + + declare favourite_currencies?: string[]; + + declare isAdmin: boolean; + + declare readonly createdAt: Date; + + declare readonly updatedAt: Date; +} + +User.init( + { + id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, + alias: { + type: DataTypes.STRING, + allowNull: false, + unique: true, + }, + address: { + type: DataTypes.STRING, + allowNull: false, + unique: true, + }, + favourite_currencies: { + type: DataTypes.ARRAY(DataTypes.STRING), + allowNull: true, + defaultValue: [], + }, + isAdmin: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + }, + { + sequelize, + modelName: 'User', + timestamps: true, + }, +); + +User.hasMany(Offer, { + foreignKey: 'user_id', + as: 'offers', + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + hooks: true, +}); + +User.hasMany(Order, { + foreignKey: 'user_id', + as: 'orders', + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + hooks: true, +}); + +Order.belongsTo(User, { + foreignKey: 'user_id', + as: 'user', + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + hooks: true, + constraints: false, +}); + +export default User; diff --git a/src/sequelize.ts b/src/sequelize.ts new file mode 100644 index 0000000..4f03e17 --- /dev/null +++ b/src/sequelize.ts @@ -0,0 +1,13 @@ +import { Sequelize } from 'sequelize'; + +const sequelize = new Sequelize({ + dialect: 'postgres', + password: process.env.PGPASSWORD, + host: process.env.PGHOST, + username: process.env.PGUSER, + port: parseInt(process.env.PGPORT || '5432', 10), + database: process.env.PGDATABASE, + logging: false, +}); + +export default sequelize; diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..ffa545c --- /dev/null +++ b/src/server.ts @@ -0,0 +1,94 @@ +import express from 'express'; +import http from 'http'; +import { Server } from 'socket.io'; + +import authRouter from './routes/auth.router.js'; +import offersRouter from './routes/offers.router.js'; +import userRouter from './routes/user.router.js'; +import middleware from './middleware/middleware.js'; +import configRouter from './routes/config.router.js'; +import chatsRouter from './routes/chats.router.js'; +import dexRouter from './routes/dex.router.js'; +import ordersRouter from './routes/orders.router.js'; +import transactionsRouter from './routes/transactions.router.js'; +import adminRouter from './routes/admin.router.js'; + +import { socketStart } from './socket/main.js'; +import assetsUpdateChecker, { ZANO_ASSET_ID } from './workers/assetsUpdateChecker.js'; +import initdb from './database.js'; +import sequelize from './sequelize.js'; +import Currency, { Asset } from './schemes/Currency.js'; +import User from './schemes/User.js'; + +const PORT = process.env.PORT || 3000; + +const app = express(); +const server = http.createServer(app); +const io = new Server(server); + +// Log uncaught exceptions and unhandled promise rejections +process.on('uncaughtException', (err) => { + console.error('Uncaught Exception:', err); +}); + +process.on('unhandledRejection', (reason, promise) => { + console.error('Unhandled Rejection at:', promise, 'reason:', reason); +}); + +(async () => { + await initdb(); + await sequelize.authenticate(); + await sequelize.sync(); + + const zanoRow = await Currency.findOne({ where: { asset_id: ZANO_ASSET_ID } }); + + if (!zanoRow) { + await Currency.create({ + name: 'ZANO', + code: 'zano', + type: 'crypto', + asset_id: ZANO_ASSET_ID, + auto_parsed: false, + asset_info: { + decimal_point: 12, + }, + }); + } else if (!zanoRow.asset_info) { + zanoRow.asset_info = { + decimal_point: 12, + } as Asset; + await zanoRow.save(); + } + + if (process.env.OWNER_ALIAS) { + await User.update({ isAdmin: true }, { where: { alias: process.env.OWNER_ALIAS } }); + } + + assetsUpdateChecker.run(); + + socketStart(io); + + app.use(express.json()); + app.use(express.urlencoded({ extended: true })); + + app.use('/api', [ + authRouter, + offersRouter, + userRouter, + configRouter, + chatsRouter, + dexRouter, + ordersRouter, + transactionsRouter, + ]); + + app.use('/api/admin', adminRouter); + + app.post('/api/check-auth', middleware.verifyToken, async (req, res) => + res.send({ success: true, userData: req.body.userData }) + ); + + server.listen(PORT, () => console.log(`Server is running on port ${PORT}`)); +})(); + +export default io; diff --git a/src/socket/main.ts b/src/socket/main.ts new file mode 100644 index 0000000..b875309 --- /dev/null +++ b/src/socket/main.ts @@ -0,0 +1,180 @@ +import { Server } from 'socket.io'; +import UserSocketData from '@/interfaces/special/socket-data/UserSocketData.js'; +import { PairStats } from '@/interfaces/responses/orders/GetPairStatsRes.js'; +import chatsModel from '../models/Chats.js'; +import processController from '../controllers/process.controller.js'; +import socketMiddleware, { verifyUser } from '../middleware/socket.js'; +import ChatSocketData from '../interfaces/special/socket-data/ChatSocketData.js'; +import SocketData from '../interfaces/special/socket-data/SocketData.js'; +import DepositSocketData from '../interfaces/special/socket-data/DepositSocketData.js'; +import MessageSocketData from '../interfaces/special/socket-data/MessageSocketData.js'; +import AuthorizedData from '../interfaces/special/socket-data/AuthorizedData.js'; +import OrderData from '../interfaces/special/socket-data/OrderData.js'; + +type ProcessResult = + | { + success: boolean; + offerRow: unknown; + existingChat: unknown; + userRow: unknown; + data?: undefined; + } + | { + success: boolean; + message?: { + text: string; + timestamp: number; + from_owner: boolean; + success: boolean; + fail: boolean; + type?: string; + url?: string; + fromOwner?: boolean; + }; + deposits_state: Record; + } + | { + success: boolean; + [key: string]: unknown; + }; + +async function runNotificationMethods( + io: Server, + data: AuthorizedData, + result: ProcessResult | undefined = undefined, +) { + if (result) { + io.to(`chat${data.chat_id}`).emit('new-message', result); + } + + io.to(`chat${data.chat_id}`).emit('check-connection'); + + const chatAnswer = await chatsModel.getChat({ ...data, chat_id: undefined, id: data.chat_id }); + + if (!chatAnswer.success) return; + + const chatData = chatAnswer.data; + + const socketSet = + io.sockets.adapter.rooms.get(`user${chatData.creator_data.id}`) || new Set(); + + const userSockets = [ + ...new Set([ + ...socketSet, + ...(io.sockets.adapter.rooms.get(`user${chatData.buyer_data.id}`) || []), + ]), + ]; + + const chatSockets = [...(io.sockets.adapter.rooms.get(`chat${data.chat_id}`) || [])]; + + const sendSockets = userSockets.filter((e) => !chatSockets.includes(e)); + + for (const iterator of sendSockets) { + io.to(iterator).emit('refresh-request'); + } +} + +function socketStart(io: Server) { + io.on('connection', (socket) => { + socket.use(socketMiddleware); + socket.use(verifyUser(['in-dex-notifications', 'out-dex-notifications'])); + + socket.on('in-account', (data: SocketData) => { + socket.join(`user${data.id}`); + }); + + socket.on('in-trading', (data: SocketData) => { + socket.join(`trade${data.id}`); + }); + + socket.on('out-trading', (data: SocketData) => { + socket.leave(`trade${data.id}`); + }); + + socket.on('in-dex-notifications', (data: UserSocketData) => { + socket.join(`dex-notifications${data.userData.address}`); + }); + + socket.on('out-dex-notifications', (data: UserSocketData) => { + socket.leave(`dex-notifications${data.userData.address}`); + }); + + socket.on('join', async (data: ChatSocketData) => { + socket.join(`chat${data.chat_id}`); + await processController.setWatched(data); + }); + + socket.on('change-deposit', async (data: DepositSocketData) => { + const result = await processController.changeDeposit(data); + + if (!result.success) return result; + + await runNotificationMethods(io, data, result); + }); + + socket.on('create-message', async (data: MessageSocketData) => { + const result = await processController.createMessage(data); + if (!result.success) return result; + + await runNotificationMethods(io, data, result); + }); + + socket.on('submit-watched', async (data: ChatSocketData) => { + await processController.setWatched(data); + }); + + socket.on('error', (err) => { + console.log(err.message); + }); + + socket.on('leave', () => { + const rooms = [...io.sockets.adapter.rooms.keys()]; + for (const room of rooms) { + if (room.includes('chat')) { + socket.leave(room); + } + } + }); + + socket.on('disconnect', () => { + socket.rooms.forEach((e) => { + socket.leave(e); + }); + }); + }); +} + +function sendNewOrderMessage(io: Server, pairId: string, orderData: OrderData) { + io.to(`trade${pairId}`).emit('new-order', { orderData }); +} + +function sendOrderNotificationMessage(io: Server, address: string, orderData: OrderData) { + io.to(`dex-notifications${address}`).emit('order-notification', { orderData }); +} + +function sendOrderNotificationCancelation(io: Server, address: string, orderId: number) { + io.to(`dex-notifications${address}`).emit('order-notification-cancelation', { orderId }); +} + +function sendDeleteOrderMessage(io: Server, pairId: string, orderId: string) { + io.to(`trade${pairId}`).emit('delete-order', { orderId }); +} + +function sendUpdateOrderMessage(io: Server, pairId: string) { + io.to(`trade${pairId}`).emit('update-orders'); +} + +function sendUpdatePairStatsMessage(io: Server, pairId: string, pairStats: PairStats) { + io.to(`trade${pairId}`).emit('update-pair-stats', { pairStats }); +} + +export { + socketStart, + sendNewOrderMessage, + sendDeleteOrderMessage, + runNotificationMethods, + sendUpdateOrderMessage, + sendOrderNotificationMessage, + sendUpdatePairStatsMessage, + sendOrderNotificationCancelation, +}; diff --git a/src/workers/assetsUpdateChecker.ts b/src/workers/assetsUpdateChecker.ts new file mode 100644 index 0000000..e3487e5 --- /dev/null +++ b/src/workers/assetsUpdateChecker.ts @@ -0,0 +1,138 @@ +import { Op } from 'sequelize'; +import Currency, { Asset } from '../schemes/Currency'; +import Pair from '../schemes/Pair'; +import sequelize from '../sequelize'; + +export const ZANO_ASSET_ID = 'd6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a'; +const CHECKING_INTERVAL = 60 * 60 * 1000; // 1 hr +const amountPerIteration = 100; + +async function fetchWhitelisted() { + return fetch(`https://api.zano.org/assets_whitelist.json`) + .then((res) => res.json()) + .then((res) => res.assets); +} + +async function fetchAssets(from: number, to: number) { + return fetch(`https://explorer.zano.org/api/get_assets/${from}/${to}`) + .then((res) => res.json()) + .catch((err) => { + console.log(err); + return []; + }); +} + +class AssetsUpdateChecker { + public async run() { + console.log( + `Assets update checker is running. Checking interval: ${CHECKING_INTERVAL / 1000} sec.`, + ); + + async function check() { + try { + console.log(`[${new Date()}] Getting assets list...`); + + const assets: Asset[] = []; + + let iterator = 0; + + // eslint-disable-next-line no-constant-condition + while (true) { + const newAssets = await fetchAssets(iterator, iterator + amountPerIteration); + if (!newAssets.length) break; + assets.push(...newAssets); + iterator += amountPerIteration; + } + + console.log(`[${new Date()}] Got assets list`); + + const whitelistedAssetsIds: string[] = (await fetchWhitelisted()).map( + (e: Asset) => e.asset_id, + ); + + console.log(`[${new Date()}] Got whitelisted assets list`); + + for (const asset of assets) { + const existingCurrency = await Currency.findOne({ + where: { asset_id: asset.asset_id }, + }); + + if (existingCurrency) { + if (!existingCurrency.asset_info) { + existingCurrency.asset_info = asset; + await existingCurrency.save(); + } + } else { + await Currency.create({ + name: asset.ticker, + code: asset.ticker.toLowerCase(), + type: 'crypto', + asset_id: asset.asset_id, + auto_parsed: true, + asset_info: asset, + }); + + const first_currency_id = await Currency.findOne({ + where: { asset_id: asset.asset_id }, + }).then((res) => res?.id); + + const zano_id = await Currency.findOne({ + where: { asset_id: ZANO_ASSET_ID }, + }).then((res) => res?.id); + + const pairAlreadyExists = !!(await Pair.findOne({ + where: { first_currency_id, second_currency_id: zano_id }, + })); + + if (!pairAlreadyExists) { + await Pair.create({ first_currency_id, second_currency_id: zano_id }); + } + } + } + + await sequelize.transaction(async (transaction) => { + await Currency.update( + { whitelisted: true }, + { + where: { + whitelisted: false, + asset_id: whitelistedAssetsIds, + }, + transaction, + }, + ); + + await Currency.update( + { whitelisted: false }, + { + where: { + whitelisted: true, + asset_id: { + [Op.not]: whitelistedAssetsIds, + }, + }, + transaction, + }, + ); + }); + } catch (error) { + console.log(error); + } + } + + /* eslint-disable no-constant-condition */ + while (true) { + await check(); + console.log( + `[${new Date()}] Assets update check is done. Next check in ${CHECKING_INTERVAL / 1000} sec.`, + ); + + await new Promise((resolve) => setTimeout(resolve, CHECKING_INTERVAL)); + } + /* eslint-enable no-constant-condition */ + } +} + +const assetsUpdateChecker = new AssetsUpdateChecker(); + +export default assetsUpdateChecker; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..8da0f81 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,109 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + }, + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "ES6" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "ESNext" /* Specify what module code is generated. */, // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + "allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */, + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */ /* Type Checking */, + "strict": true /* Enable all strict type-checking options. */, // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */, + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "noEmit": true, + "incremental": true, + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve" + }, + "ts-node": { + "esm": true, + "experimentalSpecifierResolution": "node" + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": ["node_modules"] +}