From ad0e31bf55f97d970cc7c0cfba178c6db1633b39 Mon Sep 17 00:00:00 2001 From: beerpiss Date: Tue, 21 Nov 2023 21:22:03 +0700 Subject: [PATCH] Initial commit --- .editorconfig | 8 + .eslintignore | 4 + .eslintrc | 48 + .gitignore | 153 + @types/express/index.d.ts | 14 + drizzle.config.ts | 6 + package.json | 57 + pnpm-lock.yaml | 4071 +++++++++++++++++ src/external/db/db.ts | 10 + .../db/drizzle/0000_ambitious_gorilla_man.sql | 48 + .../db/drizzle/0001_modern_stryfe.sql | 29 + .../db/drizzle/meta/0000_snapshot.json | 317 ++ .../db/drizzle/meta/0001_snapshot.json | 494 ++ src/external/db/drizzle/meta/_journal.json | 20 + src/external/db/schemas/aimedb.ts | 67 + src/external/db/schemas/allnet.ts | 56 + src/external/db/schemas/base.ts | 16 + src/external/db/schemas/index.ts | 3 + src/lib/logger/logger.ts | 195 + src/lib/setup/config.ts | 66 + src/main.ts | 19 + src/servers/aimedb/handlers/aime-account.ts | 164 + src/servers/aimedb/handlers/aime-log.ts | 124 + src/servers/aimedb/handlers/campaign.ts | 36 + .../aimedb/handlers/felica-conversion.ts | 271 ++ src/servers/aimedb/handlers/index.ts | 56 + src/servers/aimedb/handlers/status-check.ts | 11 + src/servers/aimedb/index.ts | 178 + src/servers/aimedb/types/aime-account.ts | 30 + src/servers/aimedb/types/aime-log.ts | 41 + src/servers/aimedb/types/campaign.ts | 47 + src/servers/aimedb/types/felica-conversion.ts | 40 + src/servers/aimedb/types/handlers.ts | 31 + src/servers/aimedb/types/header.ts | 12 + src/servers/aimedb/utils/access-code.ts | 53 + src/servers/aimedb/utils/crypto.ts | 230 + src/servers/aimedb/utils/felica.ts | 20 + src/servers/aimedb/utils/misc.ts | 70 + src/servers/allnet/index.ts | 77 + src/servers/allnet/middleware/dfi.ts | 64 + .../allnet/middleware/request-logger.ts | 56 + src/servers/allnet/router/router.ts | 12 + .../allnet/router/sys/servlet/Alive/router.ts | 13 + .../sys/servlet/DownloadOrder/router.ts | 25 + .../router/sys/servlet/PowerOn/router.ts | 226 + .../allnet/router/sys/servlet/router.ts | 12 + src/servers/allnet/types/download-order.ts | 22 + src/servers/allnet/types/power-on.ts | 278 ++ src/servers/index.ts | 2 + src/types/misc.ts | 1 + src/utils/misc.ts | 13 + tsconfig.build.json | 15 + tsconfig.json | 110 + 53 files changed, 8041 insertions(+) create mode 100644 .editorconfig create mode 100644 .eslintignore create mode 100644 .eslintrc create mode 100644 .gitignore create mode 100644 @types/express/index.d.ts create mode 100644 drizzle.config.ts create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 src/external/db/db.ts create mode 100644 src/external/db/drizzle/0000_ambitious_gorilla_man.sql create mode 100644 src/external/db/drizzle/0001_modern_stryfe.sql create mode 100644 src/external/db/drizzle/meta/0000_snapshot.json create mode 100644 src/external/db/drizzle/meta/0001_snapshot.json create mode 100644 src/external/db/drizzle/meta/_journal.json create mode 100644 src/external/db/schemas/aimedb.ts create mode 100644 src/external/db/schemas/allnet.ts create mode 100644 src/external/db/schemas/base.ts create mode 100644 src/external/db/schemas/index.ts create mode 100644 src/lib/logger/logger.ts create mode 100644 src/lib/setup/config.ts create mode 100644 src/main.ts create mode 100644 src/servers/aimedb/handlers/aime-account.ts create mode 100644 src/servers/aimedb/handlers/aime-log.ts create mode 100644 src/servers/aimedb/handlers/campaign.ts create mode 100644 src/servers/aimedb/handlers/felica-conversion.ts create mode 100644 src/servers/aimedb/handlers/index.ts create mode 100644 src/servers/aimedb/handlers/status-check.ts create mode 100644 src/servers/aimedb/index.ts create mode 100644 src/servers/aimedb/types/aime-account.ts create mode 100644 src/servers/aimedb/types/aime-log.ts create mode 100644 src/servers/aimedb/types/campaign.ts create mode 100644 src/servers/aimedb/types/felica-conversion.ts create mode 100644 src/servers/aimedb/types/handlers.ts create mode 100644 src/servers/aimedb/types/header.ts create mode 100644 src/servers/aimedb/utils/access-code.ts create mode 100644 src/servers/aimedb/utils/crypto.ts create mode 100644 src/servers/aimedb/utils/felica.ts create mode 100644 src/servers/aimedb/utils/misc.ts create mode 100644 src/servers/allnet/index.ts create mode 100644 src/servers/allnet/middleware/dfi.ts create mode 100644 src/servers/allnet/middleware/request-logger.ts create mode 100644 src/servers/allnet/router/router.ts create mode 100644 src/servers/allnet/router/sys/servlet/Alive/router.ts create mode 100644 src/servers/allnet/router/sys/servlet/DownloadOrder/router.ts create mode 100644 src/servers/allnet/router/sys/servlet/PowerOn/router.ts create mode 100644 src/servers/allnet/router/sys/servlet/router.ts create mode 100644 src/servers/allnet/types/download-order.ts create mode 100644 src/servers/allnet/types/power-on.ts create mode 100644 src/servers/index.ts create mode 100644 src/types/misc.ts create mode 100644 src/utils/misc.ts create mode 100644 tsconfig.build.json create mode 100644 tsconfig.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8358d42 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = tab +trim_trailing_whitespace = true \ No newline at end of file diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..f305b10 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +node_modules +js +package.json +*.config.* \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..d39773a --- /dev/null +++ b/.eslintrc @@ -0,0 +1,48 @@ +{ + "plugins": [ + "cadence" + ], + "extends": [ + "plugin:cadence/recommended" + ], + "root": true, + "rules": {}, + "overrides": [ + { + "files": [ + "**/*.ts" + ], + "rules": { + // broken + "lines-around-comment": "off", + + // TENPORARILY OFF AS THEY'RE BROKEN. + "@typescript-eslint/no-unsafe-assignment": "off", + "@typescript-eslint/no-unsafe-return": "off", + "@typescript-eslint/no-unsafe-argument": "off", + "@typescript-eslint/no-unsafe-member-access": "off", + "@typescript-eslint/no-unsafe-property-computation": "off", + "@typescript-eslint/no-unsafe-call": "off", + "@typescript-eslint/strict-boolean-expressions": "off" + } + }, + { + "files": [ + "**/*.test.ts" + ], + "rules": { + // Our test files break these rules *all* the time, and there's + // no point refactoring. Our tests deliberately play with the + // dynamic nature of TS to more accurately test arbitrary input. + "@typescript-eslint/no-floating-promises": "off", + "@typescript-eslint/no-unsafe-member-access": "off", + "@typescript-eslint/no-unsafe-assignment": "off", + "@typescript-eslint/no-unsafe-return": "off", + "@typescript-eslint/no-unsafe-argument": "off", + "@typescript-eslint/no-unsafe-call": "off", + // we abuse this one for faking data, but we really shouldn't. + "@typescript-eslint/consistent-type-assertions": "warn" + } + } + ] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a29e4e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,153 @@ +# Created by https://www.toptal.com/developers/gitignore/api/node +# Edit at https://www.toptal.com/developers/gitignore?templates=node + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +### Node Patch ### +# Serverless Webpack directories +.webpack/ + +# Optional stylelint cache + +# SvelteKit build / generate output +.svelte-kit + +# End of https://www.toptal.com/developers/gitignore/api/node + +*.sqlite3 +*.sqlite3-shm +*.sqlite3-wal + +config.json5 + +js +.tsbuildinfo \ No newline at end of file diff --git a/@types/express/index.d.ts b/@types/express/index.d.ts new file mode 100644 index 0000000..261378e --- /dev/null +++ b/@types/express/index.d.ts @@ -0,0 +1,14 @@ +declare global { + namespace Express { + interface Request { + /** + * This is a type-safe variant of "req.safeBody". + * "req.safeBody" is 'any' by default, which makes it exceptionally difficult + * to use in our codebase (due to the strict cadence rules.) + */ + safeBody: Record; + } + } +} + +export {}; diff --git a/drizzle.config.ts b/drizzle.config.ts new file mode 100644 index 0000000..73eb976 --- /dev/null +++ b/drizzle.config.ts @@ -0,0 +1,6 @@ +import type { Config } from "drizzle-kit"; + +export default { + schema: "./src/external/db/schemas/", + out: "./src/external/db/drizzle", +} satisfies Config; diff --git a/package.json b/package.json new file mode 100644 index 0000000..2ee69e4 --- /dev/null +++ b/package.json @@ -0,0 +1,57 @@ +{ + "name": "kozukata-toa", + "version": "0.1.0", + "description": "An ALL.Net network service emulator.", + "main": "./js/main.js", + "files": [ + "/js" + ], + "private": true, + "scripts": { + "build": "tsc --project tsconfig.build.json", + "typecheck": "tsc --project tsconfig.build.json --noEmit", + "start": "pnpm build && pnpm start-no-build", + "start-no-build": "node js/main.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "beerpsi", + "license": "0BSD", + "engines": { + "node": "16", + "pnpm": "7" + }, + "dependencies": { + "better-sqlite3": "^9.1.1", + "dotenv": "^16.3.1", + "drizzle-orm": "^0.29.0", + "express": "^4.18.2", + "express-async-errors": "^3.1.1", + "fletcher": "^0.0.3", + "iconv-lite": "^0.6.3", + "json5": "^2.2.3", + "luxon": "^3.4.4", + "micro-packed": "^0.3.2", + "raw-body": "^2.5.2", + "safe-json-stringify": "^1.2.0", + "tsconfig-paths": "^4.2.0", + "typed-struct": "^2.3.0", + "winston": "^3.11.0", + "winston-daily-rotate-file": "^4.7.1", + "zod": "^3.22.4", + "zod-validation-error": "^2.1.0" + }, + "devDependencies": { + "@types/better-sqlite3": "^7.6.7", + "@types/express": "^4.17.21", + "@types/iconv": "^3.0.4", + "@types/luxon": "^3.3.4", + "@types/node": "16", + "@types/safe-json-stringify": "^1.1.5", + "@typescript-eslint/eslint-plugin": "5.47.1", + "@typescript-eslint/parser": "5.47.1", + "drizzle-kit": "^0.20.4", + "eslint": "8.18.0", + "eslint-plugin-cadence": "^0.1.0", + "typescript": "4.9.4" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..41ba580 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,4071 @@ +lockfileVersion: 5.4 + +specifiers: + '@types/better-sqlite3': ^7.6.7 + '@types/express': ^4.17.21 + '@types/iconv': ^3.0.4 + '@types/luxon': ^3.3.4 + '@types/node': '16' + '@types/safe-json-stringify': ^1.1.5 + '@typescript-eslint/eslint-plugin': 5.47.1 + '@typescript-eslint/parser': 5.47.1 + better-sqlite3: ^9.1.1 + dotenv: ^16.3.1 + drizzle-kit: ^0.20.4 + drizzle-orm: ^0.29.0 + eslint: 8.18.0 + eslint-plugin-cadence: ^0.1.0 + express: ^4.18.2 + express-async-errors: ^3.1.1 + fletcher: ^0.0.3 + iconv-lite: ^0.6.3 + json5: ^2.2.3 + luxon: ^3.4.4 + micro-packed: ^0.3.2 + raw-body: ^2.5.2 + safe-json-stringify: ^1.2.0 + tsconfig-paths: ^4.2.0 + typed-struct: ^2.3.0 + typescript: 4.9.4 + winston: ^3.11.0 + winston-daily-rotate-file: ^4.7.1 + zod: ^3.22.4 + zod-validation-error: ^2.1.0 + +dependencies: + better-sqlite3: 9.1.1 + dotenv: 16.3.1 + drizzle-orm: 0.29.0_j2ohppjkndt27e4oczafq6gzg4 + express: 4.18.2 + express-async-errors: 3.1.1_express@4.18.2 + fletcher: 0.0.3 + iconv-lite: 0.6.3 + json5: 2.2.3 + luxon: 3.4.4 + micro-packed: 0.3.2 + raw-body: 2.5.2 + safe-json-stringify: 1.2.0 + tsconfig-paths: 4.2.0 + typed-struct: 2.3.0_iconv-lite@0.6.3 + winston: 3.11.0 + winston-daily-rotate-file: 4.7.1_winston@3.11.0 + zod: 3.22.4 + zod-validation-error: 2.1.0_zod@3.22.4 + +devDependencies: + '@types/better-sqlite3': 7.6.7 + '@types/express': 4.17.21 + '@types/iconv': 3.0.4 + '@types/luxon': 3.3.4 + '@types/node': 16.18.62 + '@types/safe-json-stringify': 1.1.5 + '@typescript-eslint/eslint-plugin': 5.47.1_o6yrxajvsx2b7l3udqdd2yq4ii + '@typescript-eslint/parser': 5.47.1_4njjt2tu6ubn7rwbgcnueihm54 + drizzle-kit: 0.20.4 + eslint: 8.18.0 + eslint-plugin-cadence: 0.1.0_4njjt2tu6ubn7rwbgcnueihm54 + typescript: 4.9.4 + +packages: + + /@aashutoshrathi/word-wrap/1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + + /@babel/code-frame/7.22.13: + resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.22.20 + chalk: 2.4.2 + dev: true + + /@babel/helper-validator-identifier/7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/highlight/7.22.20: + resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@cloudflare/kv-asset-handler/0.2.0: + resolution: {integrity: sha512-MVbXLbTcAotOPUj0pAMhVtJ+3/kFkwJqc5qNOleOZTv6QkZZABDMS21dSrSlVswEHwrpWC03e4fWytjqKvuE2A==} + dependencies: + mime: 3.0.0 + dev: true + + /@cloudflare/workerd-darwin-64/1.20231030.0: + resolution: {integrity: sha512-J4PQ9utPxLya9yHdMMx3AZeC5M/6FxcoYw6jo9jbDDFTy+a4Gslqf4Im9We3aeOEdPXa3tgQHVQOSelJSZLhIw==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@cloudflare/workerd-darwin-arm64/1.20231030.0: + resolution: {integrity: sha512-WSJJjm11Del4hSneiNB7wTXGtBXI4QMCH9l5qf4iT5PAW8cESGcCmdHtWDWDtGAAGcvmLT04KNvmum92vRKKQQ==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@cloudflare/workerd-linux-64/1.20231030.0: + resolution: {integrity: sha512-2HUeRTvoCC17fxE0qdBeR7J9dO8j4A8ZbdcvY8pZxdk+zERU6+N03RTbk/dQMU488PwiDvcC3zZqS4gwLfVT8g==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@cloudflare/workerd-linux-arm64/1.20231030.0: + resolution: {integrity: sha512-4/GK5zHh+9JbUI6Z5xTCM0ZmpKKHk7vu9thmHjUxtz+o8Ne9DoD7DlDvXQWgMF6XGaTubDWyp3ttn+Qv8jDFuQ==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@cloudflare/workerd-windows-64/1.20231030.0: + resolution: {integrity: sha512-fb/Jgj8Yqy3PO1jLhk7mTrHMkR8jklpbQFud6rL/aMAn5d6MQbaSrYOCjzkKGp0Zng8D2LIzSl+Fc0C9Sggxjg==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@colors/colors/1.6.0: + resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} + engines: {node: '>=0.1.90'} + dev: false + + /@dabh/diagnostics/2.0.3: + resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} + dependencies: + colorspace: 1.1.4 + enabled: 2.0.0 + kuler: 2.0.0 + dev: false + + /@drizzle-team/studio/0.0.27: + resolution: {integrity: sha512-vkgflb8g/7WCdVCuxWE6tCzjZB0q4lLIK6mwH1aleNRqIGOhEWq/E2I8HmKquz1v0GRDHLFd19ZzrVSITt2Uqg==} + dev: true + + /@esbuild-kit/core-utils/3.3.2: + resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} + dependencies: + esbuild: 0.18.20 + source-map-support: 0.5.21 + dev: true + + /@esbuild-kit/esm-loader/2.6.5: + resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==} + dependencies: + '@esbuild-kit/core-utils': 3.3.2 + get-tsconfig: 4.7.2 + dev: true + + /@esbuild-plugins/node-globals-polyfill/0.2.3_esbuild@0.17.19: + resolution: {integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==} + peerDependencies: + esbuild: '*' + dependencies: + esbuild: 0.17.19 + dev: true + + /@esbuild-plugins/node-modules-polyfill/0.2.2_esbuild@0.17.19: + resolution: {integrity: sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==} + peerDependencies: + esbuild: '*' + dependencies: + esbuild: 0.17.19 + escape-string-regexp: 4.0.0 + rollup-plugin-node-polyfills: 0.2.1 + dev: true + + /@esbuild/android-arm/0.17.19: + resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm/0.18.20: + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64/0.17.19: + resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64/0.18.20: + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64/0.17.19: + resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64/0.18.20: + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64/0.17.19: + resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64/0.18.20: + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64/0.17.19: + resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64/0.18.20: + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64/0.17.19: + resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64/0.18.20: + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64/0.17.19: + resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64/0.18.20: + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm/0.17.19: + resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm/0.18.20: + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64/0.17.19: + resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64/0.18.20: + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32/0.17.19: + resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32/0.18.20: + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64/0.17.19: + resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64/0.18.20: + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el/0.17.19: + resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el/0.18.20: + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64/0.17.19: + resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64/0.18.20: + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64/0.17.19: + resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64/0.18.20: + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x/0.17.19: + resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x/0.18.20: + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64/0.17.19: + resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64/0.18.20: + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64/0.17.19: + resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64/0.18.20: + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64/0.17.19: + resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64/0.18.20: + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64/0.17.19: + resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64/0.18.20: + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64/0.17.19: + resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64/0.18.20: + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32/0.17.19: + resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32/0.18.20: + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64/0.17.19: + resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64/0.18.20: + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint/eslintrc/1.4.1: + resolution: {integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.23.0 + ignore: 5.3.0 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@fastify/busboy/2.1.0: + resolution: {integrity: sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==} + engines: {node: '>=14'} + dev: true + + /@humanwhocodes/config-array/0.9.5: + resolution: {integrity: sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/object-schema/1.2.1: + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + dev: true + + /@nodelib/fs.scandir/2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat/2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk/1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@scure/base/1.1.3: + resolution: {integrity: sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q==} + dev: false + + /@types/better-sqlite3/7.6.7: + resolution: {integrity: sha512-+c2YGPWY5831v3uj2/X0HRTK94u1GXU3sCnLqu7AKlxlSfawswnAiJR//TFzSL5azWsLQkG/uS+YnnqHtuZxPw==} + dependencies: + '@types/node': 16.18.62 + + /@types/body-parser/1.19.5: + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + dependencies: + '@types/connect': 3.4.38 + '@types/node': 16.18.62 + dev: true + + /@types/connect/3.4.38: + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + dependencies: + '@types/node': 16.18.62 + dev: true + + /@types/estree/1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: true + + /@types/express-serve-static-core/4.17.41: + resolution: {integrity: sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==} + dependencies: + '@types/node': 16.18.62 + '@types/qs': 6.9.10 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + dev: true + + /@types/express/4.17.21: + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 4.17.41 + '@types/qs': 6.9.10 + '@types/serve-static': 1.15.5 + dev: true + + /@types/http-errors/2.0.4: + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + dev: true + + /@types/iconv/3.0.4: + resolution: {integrity: sha512-bk+twLWL20lSbLw65vMUK1oy9dVEDMytQczaxqQs6p1MjY0ogiOidSLPsbfyQ04HxN9spZ9FPYkXZuCyw5C7Nw==} + dependencies: + '@types/node': 16.18.62 + dev: true + + /@types/json-schema/7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: true + + /@types/json5/0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + + /@types/luxon/3.3.4: + resolution: {integrity: sha512-H9OXxv4EzJwE75aTPKpiGXJq+y4LFxjpsdgKwSmr503P5DkWc3AG7VAFYrFNVvqemT5DfgZJV9itYhqBHSGujA==} + dev: true + + /@types/mime/1.3.5: + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + dev: true + + /@types/mime/3.0.4: + resolution: {integrity: sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==} + dev: true + + /@types/node-forge/1.3.9: + resolution: {integrity: sha512-meK88cx/sTalPSLSoCzkiUB4VPIFHmxtXm5FaaqRDqBX2i/Sy8bJ4odsan0b20RBjPh06dAQ+OTTdnyQyhJZyQ==} + dependencies: + '@types/node': 16.18.62 + dev: true + + /@types/node/16.18.62: + resolution: {integrity: sha512-/zbPnIBkef8sT+6vw6BxdvU3dCxRI0v6rBu/6IvXnRNtOPILucigqhUBPYxtQ/8JdAna0JLTAcNTCDmQ77QYkQ==} + + /@types/normalize-package-data/2.4.4: + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + dev: true + + /@types/qs/6.9.10: + resolution: {integrity: sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==} + dev: true + + /@types/range-parser/1.2.7: + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + dev: true + + /@types/safe-json-stringify/1.1.5: + resolution: {integrity: sha512-wQ1unJoajjDOP7bkg7FHOYelVp6BSsuBIFSvifNKeiMHegXWa6vddoqM/dHTVkX8bn9fJcor4Hukff9AtFybcA==} + dev: true + + /@types/semver/7.5.5: + resolution: {integrity: sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==} + dev: true + + /@types/send/0.17.4: + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + dependencies: + '@types/mime': 1.3.5 + '@types/node': 16.18.62 + dev: true + + /@types/serve-static/1.15.5: + resolution: {integrity: sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==} + dependencies: + '@types/http-errors': 2.0.4 + '@types/mime': 3.0.4 + '@types/node': 16.18.62 + dev: true + + /@types/triple-beam/1.3.5: + resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + dev: false + + /@typescript-eslint/eslint-plugin/5.47.1_o6yrxajvsx2b7l3udqdd2yq4ii: + resolution: {integrity: sha512-r4RZ2Jl9kcQN7K/dcOT+J7NAimbiis4sSM9spvWimsBvDegMhKLA5vri2jG19PmIPbDjPeWzfUPQ2hjEzA4Nmg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/parser': 5.47.1_4njjt2tu6ubn7rwbgcnueihm54 + '@typescript-eslint/scope-manager': 5.47.1 + '@typescript-eslint/type-utils': 5.47.1_4njjt2tu6ubn7rwbgcnueihm54 + '@typescript-eslint/utils': 5.47.1_4njjt2tu6ubn7rwbgcnueihm54 + debug: 4.3.4 + eslint: 8.18.0 + ignore: 5.3.0 + natural-compare-lite: 1.4.0 + regexpp: 3.2.0 + semver: 7.5.4 + tsutils: 3.21.0_typescript@4.9.4 + typescript: 4.9.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser/5.47.1_4njjt2tu6ubn7rwbgcnueihm54: + resolution: {integrity: sha512-9Vb+KIv29r6GPu4EboWOnQM7T+UjpjXvjCPhNORlgm40a9Ia9bvaPJswvtae1gip2QEeVeGh6YquqAzEgoRAlw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 5.47.1 + '@typescript-eslint/types': 5.47.1 + '@typescript-eslint/typescript-estree': 5.47.1_typescript@4.9.4 + debug: 4.3.4 + eslint: 8.18.0 + typescript: 4.9.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager/5.47.1: + resolution: {integrity: sha512-9hsFDsgUwrdOoW1D97Ewog7DYSHaq4WKuNs0LHF9RiCmqB0Z+XRR4Pf7u7u9z/8CciHuJ6yxNws1XznI3ddjEw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.47.1 + '@typescript-eslint/visitor-keys': 5.47.1 + dev: true + + /@typescript-eslint/type-utils/5.47.1_4njjt2tu6ubn7rwbgcnueihm54: + resolution: {integrity: sha512-/UKOeo8ee80A7/GJA427oIrBi/Gd4osk/3auBUg4Rn9EahFpevVV1mUK8hjyQD5lHPqX397x6CwOk5WGh1E/1w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 5.47.1_typescript@4.9.4 + '@typescript-eslint/utils': 5.47.1_4njjt2tu6ubn7rwbgcnueihm54 + debug: 4.3.4 + eslint: 8.18.0 + tsutils: 3.21.0_typescript@4.9.4 + typescript: 4.9.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types/5.47.1: + resolution: {integrity: sha512-CmALY9YWXEpwuu6377ybJBZdtSAnzXLSQcxLSqSQSbC7VfpMu/HLVdrnVJj7ycI138EHqocW02LPJErE35cE9A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@typescript-eslint/typescript-estree/5.47.1_typescript@4.9.4: + resolution: {integrity: sha512-4+ZhFSuISAvRi2xUszEj0xXbNTHceV9GbH9S8oAD2a/F9SW57aJNQVOCxG8GPfSWH/X4eOPdMEU2jYVuWKEpWA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.47.1 + '@typescript-eslint/visitor-keys': 5.47.1 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + tsutils: 3.21.0_typescript@4.9.4 + typescript: 4.9.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils/5.47.1_4njjt2tu6ubn7rwbgcnueihm54: + resolution: {integrity: sha512-l90SdwqfmkuIVaREZ2ykEfCezepCLxzWMo5gVfcJsJCaT4jHT+QjgSkYhs5BMQmWqE9k3AtIfk4g211z/sTMVw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.5 + '@typescript-eslint/scope-manager': 5.47.1 + '@typescript-eslint/types': 5.47.1 + '@typescript-eslint/typescript-estree': 5.47.1_typescript@4.9.4 + eslint: 8.18.0 + eslint-scope: 5.1.1 + eslint-utils: 3.0.0_eslint@8.18.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys/5.47.1: + resolution: {integrity: sha512-rF3pmut2JCCjh6BLRhNKdYjULMb1brvoaiWDlHfLNVgmnZ0sBVJrs3SyaKE1XoDDnJuAx/hDQryHYmPUuNq0ig==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.47.1 + eslint-visitor-keys: 3.4.3 + dev: true + + /accepts/1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + + /acorn-jsx/5.3.2_acorn@8.11.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.11.2 + dev: true + + /acorn-walk/8.3.0: + resolution: {integrity: sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn/8.11.2: + resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /ajv/6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ansi-regex/5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles/3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles/4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /anymatch/3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /argparse/2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /array-buffer-byte-length/1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.5 + is-array-buffer: 3.0.2 + dev: true + + /array-flatten/1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: false + + /array-includes/3.1.7: + resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + is-string: 1.0.7 + dev: true + + /array-union/2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array.prototype.flat/1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + dev: true + + /arraybuffer.prototype.slice/1.0.2: + resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + is-array-buffer: 3.0.2 + is-shared-array-buffer: 1.0.2 + dev: true + + /as-table/1.0.55: + resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} + dependencies: + printable-characters: 1.0.42 + dev: true + + /async/3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + dev: false + + /available-typed-arrays/1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: true + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /base64-js/1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: false + + /better-sqlite3/9.1.1: + resolution: {integrity: sha512-FhW7bS7cXwkB2SFnPJrSGPmQerVSCzwBgmQ1cIRcYKxLsyiKjljzCbyEqqhYXo5TTBqt5BISiBj2YE2Sy2ynaA==} + requiresBuild: true + dependencies: + bindings: 1.5.0 + prebuild-install: 7.1.1 + dev: false + + /binary-extensions/2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /bindings/1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + dependencies: + file-uri-to-path: 1.0.0 + dev: false + + /bl/4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: false + + /blake3-wasm/2.1.5: + resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} + dev: true + + /body-parser/1.20.1: + resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.1 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion/2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces/3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /buffer-from/1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /buffer/5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + + /builtin-modules/3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + dev: true + + /bytes/3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: false + + /call-bind/1.0.5: + resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} + dependencies: + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + set-function-length: 1.1.1 + + /callsites/3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase/7.0.1: + resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} + engines: {node: '>=14.16'} + dev: true + + /capnp-ts/0.7.0: + resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==} + dependencies: + debug: 4.3.4 + tslib: 2.6.2 + transitivePeerDependencies: + - supports-color + dev: true + + /chalk/2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk/4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chalk/5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + + /chokidar/3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /chownr/1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + dev: false + + /ci-info/3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + dev: true + + /clean-regexp/1.0.0: + resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} + engines: {node: '>=4'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /cli-color/2.0.3: + resolution: {integrity: sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==} + engines: {node: '>=0.10'} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-iterator: 2.0.3 + memoizee: 0.4.15 + timers-ext: 0.1.7 + dev: true + + /color-convert/1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + + /color-convert/2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name/1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + /color-name/1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + /color-string/1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + dev: false + + /color/3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + dependencies: + color-convert: 1.9.3 + color-string: 1.9.1 + dev: false + + /colorspace/1.1.4: + resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} + dependencies: + color: 3.2.1 + text-hex: 1.0.0 + dev: false + + /commander/9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + dev: true + + /concat-map/0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /content-disposition/0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /content-type/1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: false + + /cookie-signature/1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + dev: false + + /cookie/0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + + /cross-spawn/7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /d/1.0.1: + resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} + dependencies: + es5-ext: 0.10.62 + type: 1.2.0 + dev: true + + /data-uri-to-buffer/2.0.2: + resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} + dev: true + + /debug/2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + + /debug/3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: true + + /debug/4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /decompress-response/6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + dependencies: + mimic-response: 3.1.0 + dev: false + + /deep-extend/0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + dev: false + + /deep-is/0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /define-data-property/1.1.1: + resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + + /define-properties/1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + has-property-descriptors: 1.0.1 + object-keys: 1.1.1 + dev: true + + /depd/2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: false + + /destroy/1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: false + + /detect-libc/2.0.2: + resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} + engines: {node: '>=8'} + dev: false + + /difflib/0.2.4: + resolution: {integrity: sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==} + dependencies: + heap: 0.2.7 + dev: true + + /dir-glob/3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine/2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /doctrine/3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /dotenv/16.3.1: + resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} + engines: {node: '>=12'} + dev: false + + /dreamopt/0.8.0: + resolution: {integrity: sha512-vyJTp8+mC+G+5dfgsY+r3ckxlz+QMX40VjPQsZc5gxVAxLmi64TBoVkP54A/pRAXMXsbu2GMMBrZPxNv23waMg==} + engines: {node: '>=0.4.0'} + dependencies: + wordwrap: 1.0.0 + dev: true + + /drizzle-kit/0.20.4: + resolution: {integrity: sha512-pfaryOMS4jtQ6PNIanggsXqZnl34nMeoFd6Mmc9mZA+amSym0izLTuOO3xnivPT2BDsDVOoPhrC47QzKij7fRA==} + hasBin: true + dependencies: + '@drizzle-team/studio': 0.0.27 + '@esbuild-kit/esm-loader': 2.6.5 + camelcase: 7.0.1 + chalk: 5.3.0 + commander: 9.5.0 + esbuild: 0.18.20 + esbuild-register: 3.5.0_esbuild@0.18.20 + glob: 8.1.0 + hanji: 0.0.5 + json-diff: 0.9.0 + minimatch: 7.4.6 + wrangler: 3.16.0 + zod: 3.22.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /drizzle-orm/0.29.0_j2ohppjkndt27e4oczafq6gzg4: + resolution: {integrity: sha512-AC+CuW4GezVjsZDGU9u9B4HyikudOyYVhjm6he3Xn1D6Kky7bHGKob97MMX2piO+t9b6UuajLzlii/T/lu1qwA==} + peerDependencies: + '@aws-sdk/client-rds-data': '>=3' + '@cloudflare/workers-types': '>=3' + '@libsql/client': '*' + '@neondatabase/serverless': '>=0.1' + '@opentelemetry/api': ^1.4.1 + '@planetscale/database': '>=1' + '@types/better-sqlite3': '*' + '@types/pg': '*' + '@types/sql.js': '*' + '@vercel/postgres': '*' + better-sqlite3: '>=7' + bun-types: '*' + knex: '*' + kysely: '*' + mysql2: '>=2' + pg: '>=8' + postgres: '>=3' + sql.js: '>=1' + sqlite3: '>=5' + peerDependenciesMeta: + '@aws-sdk/client-rds-data': + optional: true + '@cloudflare/workers-types': + optional: true + '@libsql/client': + optional: true + '@neondatabase/serverless': + optional: true + '@opentelemetry/api': + optional: true + '@planetscale/database': + optional: true + '@types/better-sqlite3': + optional: true + '@types/pg': + optional: true + '@types/sql.js': + optional: true + '@vercel/postgres': + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + dependencies: + '@types/better-sqlite3': 7.6.7 + better-sqlite3: 9.1.1 + dev: false + + /ee-first/1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: false + + /enabled/2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + dev: false + + /encodeurl/1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: false + + /end-of-stream/1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: false + + /error-ex/1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es-abstract/1.22.3: + resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + arraybuffer.prototype.slice: 1.0.2 + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + es-set-tostringtag: 2.0.2 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.2 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + internal-slot: 1.0.6 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.12 + is-weakref: 1.0.2 + object-inspect: 1.13.1 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.5.1 + safe-array-concat: 1.0.1 + safe-regex-test: 1.0.0 + string.prototype.trim: 1.2.8 + string.prototype.trimend: 1.0.7 + string.prototype.trimstart: 1.0.7 + typed-array-buffer: 1.0.0 + typed-array-byte-length: 1.0.0 + typed-array-byte-offset: 1.0.0 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.13 + dev: true + + /es-set-tostringtag/2.0.2: + resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + has-tostringtag: 1.0.0 + hasown: 2.0.0 + dev: true + + /es-shim-unscopables/1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + dependencies: + hasown: 2.0.0 + dev: true + + /es-to-primitive/1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /es5-ext/0.10.62: + resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} + engines: {node: '>=0.10'} + requiresBuild: true + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.3 + next-tick: 1.1.0 + dev: true + + /es6-iterator/2.0.3: + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-symbol: 3.1.3 + dev: true + + /es6-symbol/3.1.3: + resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==} + dependencies: + d: 1.0.1 + ext: 1.7.0 + dev: true + + /es6-weak-map/2.0.3: + resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-iterator: 2.0.3 + es6-symbol: 3.1.3 + dev: true + + /esbuild-register/3.5.0_esbuild@0.18.20: + resolution: {integrity: sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==} + peerDependencies: + esbuild: '>=0.12 <1' + dependencies: + debug: 4.3.4 + esbuild: 0.18.20 + transitivePeerDependencies: + - supports-color + dev: true + + /esbuild/0.17.19: + resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.17.19 + '@esbuild/android-arm64': 0.17.19 + '@esbuild/android-x64': 0.17.19 + '@esbuild/darwin-arm64': 0.17.19 + '@esbuild/darwin-x64': 0.17.19 + '@esbuild/freebsd-arm64': 0.17.19 + '@esbuild/freebsd-x64': 0.17.19 + '@esbuild/linux-arm': 0.17.19 + '@esbuild/linux-arm64': 0.17.19 + '@esbuild/linux-ia32': 0.17.19 + '@esbuild/linux-loong64': 0.17.19 + '@esbuild/linux-mips64el': 0.17.19 + '@esbuild/linux-ppc64': 0.17.19 + '@esbuild/linux-riscv64': 0.17.19 + '@esbuild/linux-s390x': 0.17.19 + '@esbuild/linux-x64': 0.17.19 + '@esbuild/netbsd-x64': 0.17.19 + '@esbuild/openbsd-x64': 0.17.19 + '@esbuild/sunos-x64': 0.17.19 + '@esbuild/win32-arm64': 0.17.19 + '@esbuild/win32-ia32': 0.17.19 + '@esbuild/win32-x64': 0.17.19 + dev: true + + /esbuild/0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + dev: true + + /escape-html/1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: false + + /escape-string-regexp/1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp/4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-config-prettier/8.5.0_eslint@8.18.0: + resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.18.0 + dev: true + + /eslint-import-resolver-node/0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + dependencies: + debug: 3.2.7 + is-core-module: 2.13.1 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-module-utils/2.8.0_odthlc52mpsxuinnutnp2vkhfy: + resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 5.47.1_4njjt2tu6ubn7rwbgcnueihm54 + debug: 3.2.7 + eslint: 8.18.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-cadence/0.1.0_4njjt2tu6ubn7rwbgcnueihm54: + resolution: {integrity: sha512-/GB4lqnqzwXjNAO6EqJkMxN8Pl7MpD7kl2eFaET4ukrWi3G7ZKPrpfgGbqJu/4HToekajH67eo1IsC2wgYphnQ==} + engines: {node: 12.x || 14.x || >= 16} + peerDependencies: + eslint: '>=8.18' + dependencies: + '@types/estree': 1.0.5 + '@typescript-eslint/eslint-plugin': 5.47.1_o6yrxajvsx2b7l3udqdd2yq4ii + '@typescript-eslint/parser': 5.47.1_4njjt2tu6ubn7rwbgcnueihm54 + eslint: 8.18.0 + eslint-config-prettier: 8.5.0_eslint@8.18.0 + eslint-plugin-eslint-plugin: 4.1.0_eslint@8.18.0 + eslint-plugin-import: 2.26.0_dg2veh6zarj4tmy5glsvhfd7a4 + eslint-plugin-node: 11.1.0_eslint@8.18.0 + eslint-plugin-prettier: 4.2.1_x6fw7nles57xitjng4tpluwafe + eslint-plugin-unicorn: 43.0.1_eslint@8.18.0 + prettier: 2.8.1 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + - typescript + dev: true + + /eslint-plugin-es/3.0.1_eslint@8.18.0: + resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=4.19.1' + dependencies: + eslint: 8.18.0 + eslint-utils: 2.1.0 + regexpp: 3.2.0 + dev: true + + /eslint-plugin-eslint-plugin/4.1.0_eslint@8.18.0: + resolution: {integrity: sha512-QJVw+WYXJuG2469gx5G929bz7crfxySDlK1i569FkuT6dpeHDeP7MmDrKaswCx17snG25LRFD6wmVX+AO5x7Qg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + eslint: 8.18.0 + eslint-utils: 3.0.0_eslint@8.18.0 + estraverse: 5.3.0 + dev: true + + /eslint-plugin-import/2.26.0_dg2veh6zarj4tmy5glsvhfd7a4: + resolution: {integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 5.47.1_4njjt2tu6ubn7rwbgcnueihm54 + array-includes: 3.1.7 + array.prototype.flat: 1.3.2 + debug: 2.6.9 + doctrine: 2.1.0 + eslint: 8.18.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.0_odthlc52mpsxuinnutnp2vkhfy + has: 1.0.4 + is-core-module: 2.13.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.values: 1.1.7 + resolve: 1.22.8 + tsconfig-paths: 3.14.2 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-node/11.1.0_eslint@8.18.0: + resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=5.16.0' + dependencies: + eslint: 8.18.0 + eslint-plugin-es: 3.0.1_eslint@8.18.0 + eslint-utils: 2.1.0 + ignore: 5.3.0 + minimatch: 3.1.2 + resolve: 1.22.8 + semver: 6.3.1 + dev: true + + /eslint-plugin-prettier/4.2.1_x6fw7nles57xitjng4tpluwafe: + resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + eslint: '>=7.28.0' + eslint-config-prettier: '*' + prettier: '>=2.0.0' + peerDependenciesMeta: + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.18.0 + eslint-config-prettier: 8.5.0_eslint@8.18.0 + prettier: 2.8.1 + prettier-linter-helpers: 1.0.0 + dev: true + + /eslint-plugin-unicorn/43.0.1_eslint@8.18.0: + resolution: {integrity: sha512-wYvF6q0RRTKw6gzbKy5bbazWUrBEPIto2S9U6eSF+tsHgtgE+CwQ6Bww1W2Ie9TRED01QkZRN79c5aVMFgrFYw==} + engines: {node: '>=14.18'} + peerDependencies: + eslint: '>=8.18.0' + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + ci-info: 3.9.0 + clean-regexp: 1.0.0 + eslint: 8.18.0 + eslint-utils: 3.0.0_eslint@8.18.0 + esquery: 1.5.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + lodash: 4.17.21 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + safe-regex: 2.1.1 + semver: 7.5.4 + strip-indent: 3.0.0 + dev: true + + /eslint-scope/5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /eslint-scope/7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-utils/2.1.0: + resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} + engines: {node: '>=6'} + dependencies: + eslint-visitor-keys: 1.3.0 + dev: true + + /eslint-utils/3.0.0_eslint@8.18.0: + resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} + engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} + peerDependencies: + eslint: '>=5' + dependencies: + eslint: 8.18.0 + eslint-visitor-keys: 2.1.0 + dev: true + + /eslint-visitor-keys/1.3.0: + resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} + engines: {node: '>=4'} + dev: true + + /eslint-visitor-keys/2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + dev: true + + /eslint-visitor-keys/3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint/8.18.0: + resolution: {integrity: sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint/eslintrc': 1.4.1 + '@humanwhocodes/config-array': 0.9.5 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-utils: 3.0.0_eslint@8.18.0 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + functional-red-black-tree: 1.0.1 + glob-parent: 6.0.2 + globals: 13.23.0 + ignore: 5.3.0 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.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 + regexpp: 3.2.0 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + v8-compile-cache: 2.4.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree/9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.2 + acorn-jsx: 5.3.2_acorn@8.11.2 + eslint-visitor-keys: 3.4.3 + dev: true + + /esquery/1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse/4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse/4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse/5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /estree-walker/0.6.1: + resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} + dev: true + + /esutils/2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /etag/1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: false + + /event-emitter/0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + dev: true + + /exit-hook/2.2.1: + resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} + engines: {node: '>=6'} + dev: true + + /expand-template/2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + dev: false + + /express-async-errors/3.1.1_express@4.18.2: + resolution: {integrity: sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==} + peerDependencies: + express: ^4.16.2 + dependencies: + express: 4.18.2 + dev: false + + /express/4.18.2: + resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.1 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.11.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /ext/1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + dependencies: + type: 2.7.2 + dev: true + + /fast-deep-equal/3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-diff/1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + dev: true + + /fast-glob/3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify/2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein/2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq/1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /fecha/4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + dev: false + + /file-entry-cache/6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.2.0 + dev: true + + /file-stream-rotator/0.6.1: + resolution: {integrity: sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==} + dependencies: + moment: 2.29.4 + dev: false + + /file-uri-to-path/1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + dev: false + + /fill-range/7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /finalhandler/1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /find-up/4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /flat-cache/3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.9 + keyv: 4.5.4 + rimraf: 3.0.2 + dev: true + + /flatted/3.2.9: + resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + dev: true + + /fletcher/0.0.3: + resolution: {integrity: sha512-cyn1RJWoQDCM9A7CLVbYTN0TcQZ7GoN5hMDZAoIaRXD6PO0UjvRlQbrNzAbAJb7MX7rgUGNx5PMMexKL6gD/eQ==} + dev: false + + /fn.name/1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + dev: false + + /for-each/0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /forwarded/0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: false + + /fresh/0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: false + + /fs-constants/1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + dev: false + + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents/2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind/1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + /function.prototype.name/1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + functions-have-names: 1.2.3 + dev: true + + /functional-red-black-tree/1.0.1: + resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} + dev: true + + /functions-have-names/1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /get-intrinsic/1.2.2: + resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} + dependencies: + function-bind: 1.1.2 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + + /get-source/2.0.12: + resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} + dependencies: + data-uri-to-buffer: 2.0.2 + source-map: 0.6.1 + dev: true + + /get-symbol-description/1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + dev: true + + /get-tsconfig/4.7.2: + resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} + dependencies: + resolve-pkg-maps: 1.0.0 + dev: true + + /github-from-package/0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + dev: false + + /glob-parent/5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent/6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-to-regexp/0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + dev: true + + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob/8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + dev: true + + /globals/13.23.0: + resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globalthis/1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + dev: true + + /globby/11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.0 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /gopd/1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.2 + + /hanji/0.0.5: + resolution: {integrity: sha512-Abxw1Lq+TnYiL4BueXqMau222fPSPMFtya8HdpWsz/xVAhifXou71mPh/kY2+08RgFcVccjG3uZHs6K5HAe3zw==} + dependencies: + lodash.throttle: 4.1.1 + sisteransi: 1.0.5 + dev: true + + /has-bigints/1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag/3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag/4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors/1.0.1: + resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} + dependencies: + get-intrinsic: 1.2.2 + + /has-proto/1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + + /has-symbols/1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + /has-tostringtag/1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /has/1.0.4: + resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} + engines: {node: '>= 0.4.0'} + dev: true + + /hasown/2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + + /heap/0.2.7: + resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} + dev: true + + /hosted-git-info/2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + + /http-errors/2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: false + + /iconv-lite/0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /iconv-lite/0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /ieee754/1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false + + /ignore/5.3.0: + resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} + engines: {node: '>= 4'} + dev: true + + /import-fresh/3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /imurmurhash/0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /indent-string/4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + /ini/1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: false + + /internal-slot/1.0.6: + resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + hasown: 2.0.0 + side-channel: 1.0.4 + dev: true + + /ipaddr.js/1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: false + + /is-array-buffer/3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: true + + /is-arrayish/0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-arrayish/0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + dev: false + + /is-bigint/1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-binary-path/2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-boolean-object/1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: true + + /is-builtin-module/3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + dependencies: + builtin-modules: 3.3.0 + dev: true + + /is-callable/1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module/2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.0 + dev: true + + /is-date-object/1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-extglob/2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-glob/4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-negative-zero/2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object/1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-number/7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-promise/2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + dev: true + + /is-regex/1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: true + + /is-shared-array-buffer/1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.5 + dev: true + + /is-stream/2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: false + + /is-string/1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-symbol/1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array/1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.13 + dev: true + + /is-weakref/1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.5 + dev: true + + /isarray/2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe/2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /js-tokens/4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-yaml/4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /json-buffer/3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-diff/0.9.0: + resolution: {integrity: sha512-cVnggDrVkAAA3OvFfHpFEhOnmcsUpleEKq4d4O8sQWWSH40MBrWstKigVB1kGrgLWzuom+7rRdaCsnBD6VyObQ==} + hasBin: true + dependencies: + cli-color: 2.0.3 + difflib: 0.2.4 + dreamopt: 0.8.0 + dev: true + + /json-parse-even-better-errors/2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-schema-traverse/0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify/1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json5/1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /json5/2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: false + + /keyv/4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + + /kuler/2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + dev: false + + /levn/0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /lines-and-columns/1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /locate-path/5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /lodash.merge/4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash.throttle/4.1.1: + resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + dev: true + + /lodash/4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + + /logform/2.6.0: + resolution: {integrity: sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==} + engines: {node: '>= 12.0.0'} + dependencies: + '@colors/colors': 1.6.0 + '@types/triple-beam': 1.3.5 + fecha: 4.2.3 + ms: 2.1.3 + safe-stable-stringify: 2.4.3 + triple-beam: 1.4.1 + dev: false + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + + /lru-queue/0.1.0: + resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} + dependencies: + es5-ext: 0.10.62 + dev: true + + /luxon/3.4.4: + resolution: {integrity: sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==} + engines: {node: '>=12'} + dev: false + + /magic-string/0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + dependencies: + sourcemap-codec: 1.4.8 + dev: true + + /media-typer/0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: false + + /memoizee/0.4.15: + resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-weak-map: 2.0.3 + event-emitter: 0.3.5 + is-promise: 2.2.2 + lru-queue: 0.1.0 + next-tick: 1.1.0 + timers-ext: 0.1.7 + dev: true + + /merge-descriptors/1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + dev: false + + /merge2/1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /methods/1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: false + + /micro-packed/0.3.2: + resolution: {integrity: sha512-D1Bq0/lVOzdxhnX5vylCxZpdw5LylH7Vd81py0DfRsKUP36XYpwvy8ZIsECVo3UfnoROn8pdKqkOzL7Cd82sGA==} + dependencies: + '@scure/base': 1.1.3 + dev: false + + /micromatch/4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /mime-db/1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types/2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mime/1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /mime/3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + dev: true + + /mimic-response/3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + dev: false + + /min-indent/1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: true + + /miniflare/3.20231030.0: + resolution: {integrity: sha512-iCg1dNauUG+kNp7jizcNmV/1XFItuTDvD/6xIC34PrszgKxYCbBO2R72y5NEDJTwaqr5ohQI/320wuJ8GEe7nQ==} + engines: {node: '>=16.13'} + hasBin: true + dependencies: + acorn: 8.11.2 + acorn-walk: 8.3.0 + capnp-ts: 0.7.0 + exit-hook: 2.2.1 + glob-to-regexp: 0.4.1 + source-map-support: 0.5.21 + stoppable: 1.1.0 + undici: 5.27.2 + workerd: 1.20231030.0 + ws: 8.14.2 + youch: 3.3.3 + zod: 3.22.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /minimatch/3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch/5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch/7.4.6: + resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimist/1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + /mkdirp-classic/0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + dev: false + + /moment/2.29.4: + resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==} + dev: false + + /ms/2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + /ms/2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /ms/2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + /mustache/4.2.0: + resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} + hasBin: true + dev: true + + /nanoid/3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /napi-build-utils/1.0.2: + resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} + dev: false + + /natural-compare-lite/1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + dev: true + + /natural-compare/1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /negotiator/0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: false + + /next-tick/1.1.0: + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} + dev: true + + /node-abi/3.51.0: + resolution: {integrity: sha512-SQkEP4hmNWjlniS5zdnfIXTk1x7Ome85RDzHlTbBtzE97Gfwz/Ipw4v/Ryk20DWIy3yCNVLVlGKApCnmvYoJbA==} + engines: {node: '>=10'} + dependencies: + semver: 7.5.4 + dev: false + + /node-forge/1.3.1: + resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + engines: {node: '>= 6.13.0'} + dev: true + + /normalize-package-data/2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.8 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /object-hash/2.2.0: + resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} + engines: {node: '>= 6'} + dev: false + + /object-inspect/1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + + /object-keys/1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign/4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.values/1.1.7: + resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /on-finished/2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: false + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + + /one-time/1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + dependencies: + fn.name: 1.1.0 + dev: false + + /optionator/0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /p-limit/2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-locate/4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-try/2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /parent-module/1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-json/5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.22.13 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parseurl/1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: false + + /path-exists/4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key/3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-to-regexp/0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + dev: false + + /path-to-regexp/6.2.1: + resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} + dev: true + + /path-type/4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /picomatch/2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pluralize/8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + dev: true + + /prebuild-install/7.1.1: + resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + detect-libc: 2.0.2 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 1.0.2 + node-abi: 3.51.0 + pump: 3.0.0 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.1 + tunnel-agent: 0.6.0 + dev: false + + /prelude-ls/1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-linter-helpers/1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.3.0 + dev: true + + /prettier/2.8.1: + resolution: {integrity: sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + + /printable-characters/1.0.42: + resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} + dev: true + + /proxy-addr/2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: false + + /pump/3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: false + + /punycode/2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + dev: true + + /qs/6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: false + + /queue-microtask/1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /range-parser/1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: false + + /raw-body/2.5.1: + resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /raw-body/2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /rc/1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + dev: false + + /read-pkg-up/7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + dev: true + + /read-pkg/5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + dev: true + + /readable-stream/3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + + /readdirp/3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /regexp-tree/0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + dev: true + + /regexp.prototype.flags/1.5.1: + resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + set-function-name: 2.0.1 + dev: true + + /regexpp/3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + dev: true + + /resolve-from/4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-pkg-maps/1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + dev: true + + /resolve.exports/2.0.2: + resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} + engines: {node: '>=10'} + dev: true + + /resolve/1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /reusify/1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf/3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rollup-plugin-inject/3.0.2: + resolution: {integrity: sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==} + deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject. + dependencies: + estree-walker: 0.6.1 + magic-string: 0.25.9 + rollup-pluginutils: 2.8.2 + dev: true + + /rollup-plugin-node-polyfills/0.2.1: + resolution: {integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==} + dependencies: + rollup-plugin-inject: 3.0.2 + dev: true + + /rollup-pluginutils/2.8.2: + resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} + dependencies: + estree-walker: 0.6.1 + dev: true + + /run-parallel/1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /safe-array-concat/1.0.1: + resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + + /safe-buffer/5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safe-json-stringify/1.2.0: + resolution: {integrity: sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==} + dev: false + + /safe-regex-test/1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-regex: 1.1.4 + dev: true + + /safe-regex/2.1.1: + resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==} + dependencies: + regexp-tree: 0.1.27 + dev: true + + /safe-stable-stringify/2.4.3: + resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} + engines: {node: '>=10'} + dev: false + + /safer-buffer/2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + + /selfsigned/2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} + engines: {node: '>=10'} + dependencies: + '@types/node-forge': 1.3.9 + node-forge: 1.3.1 + dev: true + + /semver/5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + dev: true + + /semver/6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /semver/7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + + /send/0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + 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 + transitivePeerDependencies: + - supports-color + dev: false + + /serve-static/1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + dev: false + + /set-function-length/1.1.1: + resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + + /set-function-name/2.0.1: + resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.1 + dev: true + + /setprototypeof/1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: false + + /shebang-command/2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex/3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel/1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + object-inspect: 1.13.1 + + /simple-concat/1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + dev: false + + /simple-get/4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + dev: false + + /simple-swizzle/0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + dependencies: + is-arrayish: 0.3.2 + dev: false + + /sisteransi/1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: true + + /slash/3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /source-map-support/0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /sourcemap-codec/1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + dev: true + + /spdx-correct/3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.16 + dev: true + + /spdx-exceptions/2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true + + /spdx-expression-parse/3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.16 + dev: true + + /spdx-license-ids/3.0.16: + resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} + dev: true + + /stack-trace/0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + dev: false + + /stacktracey/2.1.8: + resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} + dependencies: + as-table: 1.0.55 + get-source: 2.0.12 + dev: true + + /statuses/2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: false + + /stoppable/1.1.0: + resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} + engines: {node: '>=4', npm: '>=6'} + dev: true + + /string.prototype.trim/1.2.8: + resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string.prototype.trimend/1.0.7: + resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string.prototype.trimstart/1.0.7: + resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string_decoder/1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /strip-ansi/6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-bom/3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + /strip-indent/3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + dev: true + + /strip-json-comments/2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + dev: false + + /strip-json-comments/3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /supports-color/5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color/7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag/1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /tar-fs/2.1.1: + resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 2.2.0 + dev: false + + /tar-stream/2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: false + + /text-hex/1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + dev: false + + /text-table/0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /timers-ext/0.1.7: + resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==} + dependencies: + es5-ext: 0.10.62 + next-tick: 1.1.0 + dev: true + + /to-regex-range/5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /toidentifier/1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: false + + /triple-beam/1.4.1: + resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} + engines: {node: '>= 14.0.0'} + dev: false + + /tsconfig-paths/3.14.2: + resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tsconfig-paths/4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: false + + /tslib/1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + + /tslib/2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: true + + /tsutils/3.21.0_typescript@4.9.4: + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + 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' + dependencies: + tslib: 1.14.1 + typescript: 4.9.4 + dev: true + + /tunnel-agent/0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /type-check/0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest/0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest/0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + dev: true + + /type-fest/0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + dev: true + + /type-is/1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: false + + /type/1.2.0: + resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} + dev: true + + /type/2.7.2: + resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} + dev: true + + /typed-array-buffer/1.0.0: + resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-length/1.0.0: + resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-offset/1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-length/1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + is-typed-array: 1.1.12 + dev: true + + /typed-struct/2.3.0_iconv-lite@0.6.3: + resolution: {integrity: sha512-pPinkWRYs1d9EqBc0aREOoeDOhvuGsAWKgQQA6/ZbPuUheTAdxunXlCzzOZ/ncItpXpIK5PPHLbqj2E9c6c67w==} + engines: {node: '>=12'} + peerDependencies: + debug: ^4.3.3 + iconv-lite: ^0.6.3 + peerDependenciesMeta: + debug: + optional: true + iconv-lite: + optional: true + dependencies: + iconv-lite: 0.6.3 + dev: false + + /typescript/4.9.4: + resolution: {integrity: sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /unbox-primitive/1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.5 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /undici/5.27.2: + resolution: {integrity: sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==} + engines: {node: '>=14.0'} + dependencies: + '@fastify/busboy': 2.1.0 + dev: true + + /unpipe/1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: false + + /uri-js/4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.1 + dev: true + + /util-deprecate/1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false + + /utils-merge/1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: false + + /v8-compile-cache/2.4.0: + resolution: {integrity: sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==} + dev: true + + /validate-npm-package-license/3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + dev: true + + /vary/1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: false + + /which-boxed-primitive/1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-typed-array/1.1.13: + resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: true + + /which/2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /winston-daily-rotate-file/4.7.1_winston@3.11.0: + resolution: {integrity: sha512-7LGPiYGBPNyGHLn9z33i96zx/bd71pjBn9tqQzO3I4Tayv94WPmBNwKC7CO1wPHdP9uvu+Md/1nr6VSH9h0iaA==} + engines: {node: '>=8'} + peerDependencies: + winston: ^3 + dependencies: + file-stream-rotator: 0.6.1 + object-hash: 2.2.0 + triple-beam: 1.4.1 + winston: 3.11.0 + winston-transport: 4.6.0 + dev: false + + /winston-transport/4.6.0: + resolution: {integrity: sha512-wbBA9PbPAHxKiygo7ub7BYRiKxms0tpfU2ljtWzb3SjRjv5yl6Ozuy/TkXf00HTAt+Uylo3gSkNwzc4ME0wiIg==} + engines: {node: '>= 12.0.0'} + dependencies: + logform: 2.6.0 + readable-stream: 3.6.2 + triple-beam: 1.4.1 + dev: false + + /winston/3.11.0: + resolution: {integrity: sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==} + engines: {node: '>= 12.0.0'} + dependencies: + '@colors/colors': 1.6.0 + '@dabh/diagnostics': 2.0.3 + async: 3.2.5 + is-stream: 2.0.1 + logform: 2.6.0 + one-time: 1.0.0 + readable-stream: 3.6.2 + safe-stable-stringify: 2.4.3 + stack-trace: 0.0.10 + triple-beam: 1.4.1 + winston-transport: 4.6.0 + dev: false + + /wordwrap/1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + dev: true + + /workerd/1.20231030.0: + resolution: {integrity: sha512-+FSW+d31f8RrjHanFf/R9A+Z0csf3OtsvzdPmAKuwuZm/5HrBv83cvG9fFeTxl7/nI6irUUXIRF9xcj/NomQzQ==} + engines: {node: '>=16'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20231030.0 + '@cloudflare/workerd-darwin-arm64': 1.20231030.0 + '@cloudflare/workerd-linux-64': 1.20231030.0 + '@cloudflare/workerd-linux-arm64': 1.20231030.0 + '@cloudflare/workerd-windows-64': 1.20231030.0 + dev: true + + /wrangler/3.16.0: + resolution: {integrity: sha512-MIx35sSdFKE3hnfWB6xWUnrt3OiyKK+PQnc9kFLjksLESX0tLmEk1gdvThYHliY90kkelS+nbH48SUGTFAI5BA==} + engines: {node: '>=16.17.0'} + hasBin: true + dependencies: + '@cloudflare/kv-asset-handler': 0.2.0 + '@esbuild-plugins/node-globals-polyfill': 0.2.3_esbuild@0.17.19 + '@esbuild-plugins/node-modules-polyfill': 0.2.2_esbuild@0.17.19 + blake3-wasm: 2.1.5 + chokidar: 3.5.3 + esbuild: 0.17.19 + miniflare: 3.20231030.0 + nanoid: 3.3.7 + path-to-regexp: 6.2.1 + resolve.exports: 2.0.2 + selfsigned: 2.4.1 + source-map: 0.6.1 + source-map-support: 0.5.21 + xxhash-wasm: 1.0.2 + optionalDependencies: + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + /ws/8.14.2: + resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==} + 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 + dev: true + + /xxhash-wasm/1.0.2: + resolution: {integrity: sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==} + dev: true + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + /youch/3.3.3: + resolution: {integrity: sha512-qSFXUk3UZBLfggAW3dJKg0BMblG5biqSF8M34E06o5CSsZtH92u9Hqmj2RzGiHDi64fhe83+4tENFP2DB6t6ZA==} + dependencies: + cookie: 0.5.0 + mustache: 4.2.0 + stacktracey: 2.1.8 + dev: true + + /zod-validation-error/2.1.0_zod@3.22.4: + resolution: {integrity: sha512-VJh93e2wb4c3tWtGgTa0OF/dTt/zoPCPzXq4V11ZjxmEAFaPi/Zss1xIZdEB5RD8GD00U0/iVXgqkF77RV7pdQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.18.0 + dependencies: + zod: 3.22.4 + dev: false + + /zod/3.22.4: + resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} diff --git a/src/external/db/db.ts b/src/external/db/db.ts new file mode 100644 index 0000000..c73dd9d --- /dev/null +++ b/src/external/db/db.ts @@ -0,0 +1,10 @@ +import Database from "better-sqlite3"; +import { drizzle } from "drizzle-orm/better-sqlite3"; +import { migrate } from "drizzle-orm/better-sqlite3/migrator"; +import { Config } from "lib/setup/config"; + +const sqlite = new Database(Config.DATABASE_PATH); + +export const db = drizzle(sqlite); + +migrate(db, { migrationsFolder: "src/external/db/drizzle" }); diff --git a/src/external/db/drizzle/0000_ambitious_gorilla_man.sql b/src/external/db/drizzle/0000_ambitious_gorilla_man.sql new file mode 100644 index 0000000..1b50588 --- /dev/null +++ b/src/external/db/drizzle/0000_ambitious_gorilla_man.sql @@ -0,0 +1,48 @@ +CREATE TABLE `aimedb_felica_card_lookup` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `idm` text(16) NOT NULL, + `access_code` text(20) NOT NULL +); +--> statement-breakpoint +CREATE TABLE `aimedb_felica_mobile_lookup` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `idm` text(16) NOT NULL, + `access_code` text(20) NOT NULL +); +--> statement-breakpoint +CREATE TABLE `allnet_arcade` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `name` text(60) DEFAULT 'Random arcade at nowhere', + `nickname` text(40) DEFAULT 'Please send help', + `country` text(3) DEFAULT 'JPN', + `region_id` integer DEFAULT 1, + `region_name0` text(48) DEFAULT 'W', + `region_name1` text(48) DEFAULT '', + `region_name2` text(48) DEFAULT '', + `region_name3` text(48) DEFAULT '', + `utc_offset` real DEFAULT 9 +); +--> statement-breakpoint +CREATE TABLE `allnet_arcade_ip` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `arcade_id` integer, + `ip` text(15), + FOREIGN KEY (`arcade_id`) REFERENCES `allnet_arcade`(`id`) ON UPDATE no action ON DELETE no action +); +--> statement-breakpoint +CREATE TABLE `allnet_machine` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `arcade_id` integer, + `serial` text(11), + `game` text(5), + `can_venue_hop` integer, + `last_authenticated` integer, + FOREIGN KEY (`arcade_id`) REFERENCES `allnet_arcade`(`id`) ON UPDATE no action ON DELETE no action +); +--> statement-breakpoint +CREATE UNIQUE INDEX `aimedb_felica_card_lookup_idm_unique` ON `aimedb_felica_card_lookup` (`idm`);--> statement-breakpoint +CREATE UNIQUE INDEX `aimedb_felica_card_lookup_access_code_unique` ON `aimedb_felica_card_lookup` (`access_code`);--> statement-breakpoint +CREATE UNIQUE INDEX `aimedb_felica_mobile_lookup_idm_unique` ON `aimedb_felica_mobile_lookup` (`idm`);--> statement-breakpoint +CREATE UNIQUE INDEX `aimedb_felica_mobile_lookup_access_code_unique` ON `aimedb_felica_mobile_lookup` (`access_code`);--> statement-breakpoint +CREATE UNIQUE INDEX `allnet_arcade_ip_ip_unique` ON `allnet_arcade_ip` (`ip`);--> statement-breakpoint +CREATE UNIQUE INDEX `allnet_machine_serial_unique` ON `allnet_machine` (`serial`); \ No newline at end of file diff --git a/src/external/db/drizzle/0001_modern_stryfe.sql b/src/external/db/drizzle/0001_modern_stryfe.sql new file mode 100644 index 0000000..d57778e --- /dev/null +++ b/src/external/db/drizzle/0001_modern_stryfe.sql @@ -0,0 +1,29 @@ +CREATE TABLE `aimedb_card` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `user_id` integer, + `access_code` text(20) NOT NULL, + `created_date` integer NOT NULL, + `last_login_date` integer NOT NULL, + `is_locked` integer DEFAULT false NOT NULL, + `is_banned` integer DEFAULT false NOT NULL, + FOREIGN KEY (`user_id`) REFERENCES `aimedb_user`(`id`) ON UPDATE no action ON DELETE no action +); +--> statement-breakpoint +CREATE TABLE `aimedb_user` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `created_date` integer NOT NULL, + `last_login_date` integer NOT NULL, + `suspend_expiration_date` integer +); +--> statement-breakpoint +CREATE TABLE `event_log` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `timestamp` integer NOT NULL, + `system` text NOT NULL, + `type` text NOT NULL, + `severity` text NOT NULL, + `message` text, + `details` text +); +--> statement-breakpoint +CREATE UNIQUE INDEX `aimedb_card_access_code_unique` ON `aimedb_card` (`access_code`); \ No newline at end of file diff --git a/src/external/db/drizzle/meta/0000_snapshot.json b/src/external/db/drizzle/meta/0000_snapshot.json new file mode 100644 index 0000000..e813d6a --- /dev/null +++ b/src/external/db/drizzle/meta/0000_snapshot.json @@ -0,0 +1,317 @@ +{ + "version": "5", + "dialect": "sqlite", + "id": "a691ce52-7207-49ee-8450-d679c38b147a", + "prevId": "00000000-0000-0000-0000-000000000000", + "tables": { + "aimedb_felica_card_lookup": { + "name": "aimedb_felica_card_lookup", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "idm": { + "name": "idm", + "type": "text(16)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "access_code": { + "name": "access_code", + "type": "text(20)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "aimedb_felica_card_lookup_idm_unique": { + "name": "aimedb_felica_card_lookup_idm_unique", + "columns": [ + "idm" + ], + "isUnique": true + }, + "aimedb_felica_card_lookup_access_code_unique": { + "name": "aimedb_felica_card_lookup_access_code_unique", + "columns": [ + "access_code" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "aimedb_felica_mobile_lookup": { + "name": "aimedb_felica_mobile_lookup", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "idm": { + "name": "idm", + "type": "text(16)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "access_code": { + "name": "access_code", + "type": "text(20)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "aimedb_felica_mobile_lookup_idm_unique": { + "name": "aimedb_felica_mobile_lookup_idm_unique", + "columns": [ + "idm" + ], + "isUnique": true + }, + "aimedb_felica_mobile_lookup_access_code_unique": { + "name": "aimedb_felica_mobile_lookup_access_code_unique", + "columns": [ + "access_code" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "allnet_arcade": { + "name": "allnet_arcade", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text(60)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'Random arcade at nowhere'" + }, + "nickname": { + "name": "nickname", + "type": "text(40)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'Please send help'" + }, + "country": { + "name": "country", + "type": "text(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'JPN'" + }, + "region_id": { + "name": "region_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 1 + }, + "region_name0": { + "name": "region_name0", + "type": "text(48)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'W'" + }, + "region_name1": { + "name": "region_name1", + "type": "text(48)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "region_name2": { + "name": "region_name2", + "type": "text(48)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "region_name3": { + "name": "region_name3", + "type": "text(48)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "utc_offset": { + "name": "utc_offset", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 9 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "allnet_arcade_ip": { + "name": "allnet_arcade_ip", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "arcade_id": { + "name": "arcade_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ip": { + "name": "ip", + "type": "text(15)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "allnet_arcade_ip_ip_unique": { + "name": "allnet_arcade_ip_ip_unique", + "columns": [ + "ip" + ], + "isUnique": true + } + }, + "foreignKeys": { + "allnet_arcade_ip_arcade_id_allnet_arcade_id_fk": { + "name": "allnet_arcade_ip_arcade_id_allnet_arcade_id_fk", + "tableFrom": "allnet_arcade_ip", + "tableTo": "allnet_arcade", + "columnsFrom": [ + "arcade_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "allnet_machine": { + "name": "allnet_machine", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "arcade_id": { + "name": "arcade_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "serial": { + "name": "serial", + "type": "text(11)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "game": { + "name": "game", + "type": "text(5)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "can_venue_hop": { + "name": "can_venue_hop", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_authenticated": { + "name": "last_authenticated", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "allnet_machine_serial_unique": { + "name": "allnet_machine_serial_unique", + "columns": [ + "serial" + ], + "isUnique": true + } + }, + "foreignKeys": { + "allnet_machine_arcade_id_allnet_arcade_id_fk": { + "name": "allnet_machine_arcade_id_allnet_arcade_id_fk", + "tableFrom": "allnet_machine", + "tableTo": "allnet_arcade", + "columnsFrom": [ + "arcade_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/src/external/db/drizzle/meta/0001_snapshot.json b/src/external/db/drizzle/meta/0001_snapshot.json new file mode 100644 index 0000000..a7cfd14 --- /dev/null +++ b/src/external/db/drizzle/meta/0001_snapshot.json @@ -0,0 +1,494 @@ +{ + "version": "5", + "dialect": "sqlite", + "id": "ca3c0d34-cebd-4ea7-806e-f4eb141e586b", + "prevId": "a691ce52-7207-49ee-8450-d679c38b147a", + "tables": { + "aimedb_card": { + "name": "aimedb_card", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "access_code": { + "name": "access_code", + "type": "text(20)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_date": { + "name": "created_date", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_login_date": { + "name": "last_login_date", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_locked": { + "name": "is_locked", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "is_banned": { + "name": "is_banned", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + } + }, + "indexes": { + "aimedb_card_access_code_unique": { + "name": "aimedb_card_access_code_unique", + "columns": [ + "access_code" + ], + "isUnique": true + } + }, + "foreignKeys": { + "aimedb_card_user_id_aimedb_user_id_fk": { + "name": "aimedb_card_user_id_aimedb_user_id_fk", + "tableFrom": "aimedb_card", + "tableTo": "aimedb_user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "aimedb_felica_card_lookup": { + "name": "aimedb_felica_card_lookup", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "idm": { + "name": "idm", + "type": "text(16)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "access_code": { + "name": "access_code", + "type": "text(20)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "aimedb_felica_card_lookup_idm_unique": { + "name": "aimedb_felica_card_lookup_idm_unique", + "columns": [ + "idm" + ], + "isUnique": true + }, + "aimedb_felica_card_lookup_access_code_unique": { + "name": "aimedb_felica_card_lookup_access_code_unique", + "columns": [ + "access_code" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "aimedb_felica_mobile_lookup": { + "name": "aimedb_felica_mobile_lookup", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "idm": { + "name": "idm", + "type": "text(16)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "access_code": { + "name": "access_code", + "type": "text(20)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "aimedb_felica_mobile_lookup_idm_unique": { + "name": "aimedb_felica_mobile_lookup_idm_unique", + "columns": [ + "idm" + ], + "isUnique": true + }, + "aimedb_felica_mobile_lookup_access_code_unique": { + "name": "aimedb_felica_mobile_lookup_access_code_unique", + "columns": [ + "access_code" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "aimedb_user": { + "name": "aimedb_user", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "created_date": { + "name": "created_date", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_login_date": { + "name": "last_login_date", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "suspend_expiration_date": { + "name": "suspend_expiration_date", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "allnet_arcade": { + "name": "allnet_arcade", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text(60)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'Random arcade at nowhere'" + }, + "nickname": { + "name": "nickname", + "type": "text(40)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'Please send help'" + }, + "country": { + "name": "country", + "type": "text(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'JPN'" + }, + "region_id": { + "name": "region_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 1 + }, + "region_name0": { + "name": "region_name0", + "type": "text(48)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'W'" + }, + "region_name1": { + "name": "region_name1", + "type": "text(48)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "region_name2": { + "name": "region_name2", + "type": "text(48)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "region_name3": { + "name": "region_name3", + "type": "text(48)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "utc_offset": { + "name": "utc_offset", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 9 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "allnet_arcade_ip": { + "name": "allnet_arcade_ip", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "arcade_id": { + "name": "arcade_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ip": { + "name": "ip", + "type": "text(15)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "allnet_arcade_ip_ip_unique": { + "name": "allnet_arcade_ip_ip_unique", + "columns": [ + "ip" + ], + "isUnique": true + } + }, + "foreignKeys": { + "allnet_arcade_ip_arcade_id_allnet_arcade_id_fk": { + "name": "allnet_arcade_ip_arcade_id_allnet_arcade_id_fk", + "tableFrom": "allnet_arcade_ip", + "tableTo": "allnet_arcade", + "columnsFrom": [ + "arcade_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "allnet_machine": { + "name": "allnet_machine", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "arcade_id": { + "name": "arcade_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "serial": { + "name": "serial", + "type": "text(11)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "game": { + "name": "game", + "type": "text(5)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "can_venue_hop": { + "name": "can_venue_hop", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_authenticated": { + "name": "last_authenticated", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "allnet_machine_serial_unique": { + "name": "allnet_machine_serial_unique", + "columns": [ + "serial" + ], + "isUnique": true + } + }, + "foreignKeys": { + "allnet_machine_arcade_id_allnet_arcade_id_fk": { + "name": "allnet_machine_arcade_id_allnet_arcade_id_fk", + "tableFrom": "allnet_machine", + "tableTo": "allnet_arcade", + "columnsFrom": [ + "arcade_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "event_log": { + "name": "event_log", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "timestamp": { + "name": "timestamp", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "system": { + "name": "system", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "severity": { + "name": "severity", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "details": { + "name": "details", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/src/external/db/drizzle/meta/_journal.json b/src/external/db/drizzle/meta/_journal.json new file mode 100644 index 0000000..4b27e44 --- /dev/null +++ b/src/external/db/drizzle/meta/_journal.json @@ -0,0 +1,20 @@ +{ + "version": "5", + "dialect": "sqlite", + "entries": [ + { + "idx": 0, + "version": "5", + "when": 1700532948929, + "tag": "0000_ambitious_gorilla_man", + "breakpoints": true + }, + { + "idx": 1, + "version": "5", + "when": 1700570200478, + "tag": "0001_modern_stryfe", + "breakpoints": true + } + ] +} \ No newline at end of file diff --git a/src/external/db/schemas/aimedb.ts b/src/external/db/schemas/aimedb.ts new file mode 100644 index 0000000..6c970e1 --- /dev/null +++ b/src/external/db/schemas/aimedb.ts @@ -0,0 +1,67 @@ +import { integer, sqliteTable, text, unique } from "drizzle-orm/sqlite-core"; + +export const felicaCardLookup = sqliteTable( + "aimedb_felica_card_lookup", + { + id: integer("id").primaryKey({ autoIncrement: true }), + idm: text("idm", { length: 16 }).notNull(), + accessCode: text("access_code", { length: 20 }).notNull(), + }, + (t) => ({ + unqIdm: unique().on(t.idm), + unqAc: unique().on(t.accessCode), + }) +); + +export type FelicaCardLookup = typeof felicaMobileLookup.$inferSelect; +export type NewFelicaCardLookup = typeof felicaMobileLookup.$inferSelect; + +export const felicaMobileLookup = sqliteTable( + "aimedb_felica_mobile_lookup", + { + id: integer("id").primaryKey({ autoIncrement: true }), + idm: text("idm", { length: 16 }).notNull(), + accessCode: text("access_code", { length: 20 }).notNull(), + }, + (t) => ({ + unqIdm: unique().on(t.idm), + unqAc: unique().on(t.accessCode), + }) +); + +export type FelicaMobileLookup = typeof felicaMobileLookup.$inferSelect; +export type NewFelicaMobileLookup = typeof felicaMobileLookup.$inferInsert; + +export const user = sqliteTable("aimedb_user", { + id: integer("id").primaryKey({ autoIncrement: true }), + createdDate: integer("created_date", { mode: "timestamp" }) + .notNull() + .$default(() => new Date()), + lastLoginDate: integer("last_login_date", { mode: "timestamp" }) + .notNull() + .$default(() => new Date()), + suspendExpirationDate: integer("suspend_expiration_date", { mode: "timestamp" }), +}); + +export type AimeUser = typeof user.$inferSelect; +export type NewAimeUser = typeof user.$inferInsert; + +export const card = sqliteTable( + "aimedb_card", + { + id: integer("id").primaryKey({ autoIncrement: true }), + userId: integer("user_id").references(() => user.id), + accessCode: text("access_code", { length: 20 }).notNull(), + createdDate: integer("created_date", { mode: "timestamp" }) + .notNull() + .$default(() => new Date()), + lastLoginDate: integer("last_login_date", { mode: "timestamp" }) + .notNull() + .$default(() => new Date()), + isLocked: integer("is_locked", { mode: "boolean" }).default(false).notNull(), + isBanned: integer("is_banned", { mode: "boolean" }).default(false).notNull(), + }, + (t) => ({ + unqAc: unique().on(t.accessCode), + }) +); diff --git a/src/external/db/schemas/allnet.ts b/src/external/db/schemas/allnet.ts new file mode 100644 index 0000000..4a640c9 --- /dev/null +++ b/src/external/db/schemas/allnet.ts @@ -0,0 +1,56 @@ +/** + * In theory you should be able to just modify the imports here if you want to + * use a different database driver. + */ +import { integer, text, real, sqliteTable } from "drizzle-orm/sqlite-core"; + +export const arcade = sqliteTable("allnet_arcade", { + id: integer("id").primaryKey({ autoIncrement: true }), + + name: text("name", { length: 60 }).default("Random arcade at nowhere"), + nickname: text("nickname", { length: 40 }).default("Please send help"), + country: text("country", { length: 3 }).default("JPN"), + + /** + * Largest to smallest units of administrative division + */ + regionId: integer("region_id").default(1), + regionName0: text("region_name0", { length: 48 }).default("W"), + regionName1: text("region_name1", { length: 48 }).default(""), + regionName2: text("region_name2", { length: 48 }).default(""), + regionName3: text("region_name3", { length: 48 }).default(""), + + /** + * Client timezone. There's probably no arcades that span + * 2 timezones, right...? + */ + utcOffset: real("utc_offset").default(9), +}); + +export type Arcade = typeof arcade.$inferSelect; +export type NewArcade = typeof arcade.$inferInsert; + +export const arcadeIp = sqliteTable("allnet_arcade_ip", { + id: integer("id").primaryKey({ autoIncrement: true }), + + arcade_id: integer("arcade_id").references(() => arcade.id), + ip: text("ip", { length: 15 }).unique(), +}); + +export type ArcadeIp = typeof arcadeIp.$inferSelect; +export type NewArcadeIp = typeof arcadeIp.$inferInsert; + +export const machine = sqliteTable("allnet_machine", { + id: integer("id").primaryKey({ autoIncrement: true }), + arcade_id: integer("arcade_id").references(() => arcade.id), + + serial: text("serial", { length: 11 }).unique(), + game: text("game", { length: 5 }), + + canVenueHop: integer("can_venue_hop", { mode: "boolean" }), + + lastAuthenticated: integer("last_authenticated", { mode: "timestamp" }), +}); + +export type Machine = typeof machine.$inferSelect; +export type NewMachine = typeof machine.$inferInsert; diff --git a/src/external/db/schemas/base.ts b/src/external/db/schemas/base.ts new file mode 100644 index 0000000..5862679 --- /dev/null +++ b/src/external/db/schemas/base.ts @@ -0,0 +1,16 @@ +import { integer, text, sqliteTable } from "drizzle-orm/sqlite-core"; + +export const eventLog = sqliteTable("event_log", { + id: integer("id").primaryKey({ autoIncrement: true }), + timestamp: integer("timestamp", { mode: "timestamp" }) + .notNull() + .$default(() => new Date()), + system: text("system").notNull(), + type: text("type").notNull(), + severity: text("severity").notNull(), + message: text("message"), + details: text("details", { mode: "json" }), +}); + +export type EventLog = typeof eventLog.$inferSelect; +export type NewEventLog = typeof eventLog.$inferInsert; diff --git a/src/external/db/schemas/index.ts b/src/external/db/schemas/index.ts new file mode 100644 index 0000000..eeab0b1 --- /dev/null +++ b/src/external/db/schemas/index.ts @@ -0,0 +1,3 @@ +export * from "./aimedb"; +export * from "./allnet"; +export * from "./base"; diff --git a/src/lib/logger/logger.ts b/src/lib/logger/logger.ts new file mode 100644 index 0000000..68588a9 --- /dev/null +++ b/src/lib/logger/logger.ts @@ -0,0 +1,195 @@ +import { Config } from "lib/setup/config"; +import SafeJSONStringify from "safe-json-stringify"; +import { EscapeStringRegexp } from "utils/misc"; +import winston, { format, transports } from "winston"; +import "winston-daily-rotate-file"; + +const level = process.env.LOG_LEVEL ?? Config.LOGGER_CONFIG.LOG_LEVEL; + +const formatExcessProperties = (meta: Record, limit = false) => { + let i = 0; + + for (const [key, val] of Object.entries(meta)) { + // this is probably fine + // eslint-disable-next-line cadence/no-instanceof + if (val instanceof Error) { + meta[key] = { message: val.message, stack: val.stack }; + } + + i++; + } + + if (!i) { + return ""; + } + + const content = SafeJSONStringify(meta); + + return ` ${limit ? StrCap(content) : content}`; +}; + +const formatExcessPropertiesNoStack = ( + meta: Record, + omitKeys: Array = [], + limit = false +) => { + const realMeta: Record = {}; + + for (const [key, val] of Object.entries(meta)) { + if (omitKeys.includes(key)) { + continue; + } + + // this is probably fine + // eslint-disable-next-line cadence/no-instanceof + if (val instanceof Error) { + realMeta[key] = { message: val.message }; + } else if (!key.startsWith("__") && !key.startsWith("!")) { + realMeta[key] = val; + } + } + + if (Object.keys(realMeta).length === 0) { + return ""; + } + + const content = SafeJSONStringify(realMeta); + + return ` ${limit ? StrCap(content) : content}`; +}; + +function StrCap(string: string) { + if (string.length > 300) { + return `${string.slice(0, 297)}...`; + } + + return string; +} + +const printf = format.printf( + ({ level, message, context = "toa-root", timestamp, ...meta }) => + `${timestamp} [${ + Array.isArray(context) ? context.join(" | ") : context + }] ${level}: ${message}${formatExcessProperties(meta)}` +); + +const consolePrintf = format.printf( + ({ level, message, context = "toa-root", timestamp, hideFromConsole, ...meta }) => + `${timestamp} [${ + Array.isArray(context) ? context.join(" | ") : context + }] ${level}: ${message}${formatExcessPropertiesNoStack( + meta, + hideFromConsole as Array, + true + )}` +); + +winston.addColors({ + crit: ["bgRed", "black"], + error: ["red"], + warn: ["yellow"], + info: ["blue"], + verbose: ["cyan"], + debug: ["white"], +}); + +const baseFormatter = format.combine( + format.timestamp({ + format: "YYYY-MM-DD HH:mm:ss", + }) +); + +const defaultFormatter = format.combine(baseFormatter, format.errors({ stack: false }), printf); + +const consoleFormatter = format.combine( + baseFormatter, + format.errors({ stack: false }), + consolePrintf, + format.colorize({ + all: true, + }) +); + +const tports: Array = []; + +if (Config.LOGGER_CONFIG.CONSOLE || process.env.FORCE_CONSOLE_LOG) { + tports.push( + new transports.Console({ + format: consoleFormatter, + }) + ); +} + +if (Config.LOGGER_CONFIG.FOLDER) { + tports.push( + new transports.DailyRotateFile({ + filename: `${Config.LOGGER_CONFIG.FOLDER}/toa-%DATE%.log`, + datePattern: "YYYY-MM-DD-HH", + zippedArchive: true, + maxSize: "20m", + maxFiles: "14d", + createSymlink: true, + symlinkName: "toa.log", + format: defaultFormatter, + }) + ); +} + +export const rootLogger = winston.createLogger({ + level, + format: defaultFormatter, + transports: tports, + defaultMeta: { + __ServerName: Config.NAME, + }, +}); + +if (tports.length === 0) { + // eslint-disable-next-line no-console + console.warn( + "You have no transports set. Absolutely no logs will be saved. This is a terrible idea!" + ); +} + +export default function CreateLogCtx(filename: string, lg = rootLogger): winston.Logger { + const replacedFilename = filename.replace( + new RegExp(`^${EscapeStringRegexp(process.cwd())}[\\\\/]((js|src)[\\\\/])?`, "u"), + "" + ); + + const logger = lg.child({ + context: [replacedFilename], + }); + + // @hack, defaultMeta isn't reactive -- won't be updated unless we do this. + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + logger.defaultMeta = { ...(logger.defaultMeta ?? {}), context: [replacedFilename] }; + + return logger; +} + +export function AppendLogCtx(context: string, lg: winston.Logger): winston.Logger { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const newContext = [...lg.defaultMeta.context, context]; + + return lg.child({ context: newContext }); +} + +export function ChangeRootLogLevel( + level: "crit" | "debug" | "error" | "info" | "severe" | "verbose" | "warn" +) { + rootLogger.info(`Changing log level to ${level}.`); + + for (const tp of tports) { + tp.level = level; + } +} + +export function GetLogLevel() { + return ( + tports.map((e) => e.level).find((e) => typeof e === "string") ?? + Config.LOGGER_CONFIG.LOG_LEVEL + ); +} + +export const Transports = tports; diff --git a/src/lib/setup/config.ts b/src/lib/setup/config.ts new file mode 100644 index 0000000..4f07e61 --- /dev/null +++ b/src/lib/setup/config.ts @@ -0,0 +1,66 @@ +import dotenv from "dotenv"; +import JSON5 from "json5"; +import { z } from "zod"; +import { fromZodError } from "zod-validation-error"; +import fs from "fs"; + +dotenv.config(); + +const logger = console; + +const confLocation = process.env.TOA_CONFIG ?? "./config.json5"; + +let configFile; + +try { + configFile = fs.readFileSync(confLocation, "utf-8"); +} catch (err) { + logger.error("Error while trying to open conf.json5. Is one present?", { err }); + + process.exit(1); +} + +const config: unknown = JSON5.parse(configFile); + +const zod16bitNumber = z.number().gt(0).lte(65535); +const zodLogLevel = z.enum(["crit", "debug", "error", "info", "verbose", "warn"]); +const zodOptionalHexString16 = z + .string() + .length(16) + .regex(/^[0-9a-z]+$/iu, "value is not a hex string") + .optional(); + +const configSchema = z.object({ + NAME: z.string(), + DATABASE_PATH: z.string(), + LISTEN_ADDRESS: z.string().ip(), + LOGGER_CONFIG: z.object({ + LOG_LEVEL: zodLogLevel, + CONSOLE: z.boolean(), + FOLDER: z.string().optional(), + }), + ALLNET_CONFIG: z.object({ + ENABLED: z.boolean(), + PORT: zod16bitNumber, + ALLOW_UNREGISTERED_SERIALS: z.boolean(), + UPDATE_CFG_FOLDER: z.string().optional(), + }), + AIMEDB_CONFIG: z.object({ + ENABLED: z.boolean(), + PORT: zod16bitNumber, + KEY: z.string().length(16).optional(), + AIME_MOBILE_CARD_KEY: zodOptionalHexString16, + RESERVED_CARD_PREFIX: z.string().length(5).optional(), + RESERVED_CARD_KEY: zodOptionalHexString16, + }), +}); + +const parseResult = configSchema.safeParse(config); + +if (!parseResult.success) { + const humanFriendlyMessage = fromZodError(parseResult.error); + + throw new Error(`Invalid config.json5 file: ${humanFriendlyMessage}`); +} + +export const Config = parseResult.data; diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..9185728 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,19 @@ +import { aimeDbServerFactory, allnetServer } from "./servers/index"; +import CreateLogCtx from "lib/logger/logger"; +import { Config } from "lib/setup/config"; +import net from "net"; + +const logger = CreateLogCtx(__filename); + +logger.info(`Booting ${Config.NAME}.`, { bootInfo: true }); +logger.info(`Log level is set to ${Config.LOGGER_CONFIG.LOG_LEVEL}.`, { bootInfo: true }); + +if (Config.ALLNET_CONFIG.ENABLED) { + allnetServer.listen(Config.ALLNET_CONFIG.PORT, Config.LISTEN_ADDRESS); +} + +if (Config.AIMEDB_CONFIG.ENABLED) { + const server = net.createServer(aimeDbServerFactory()); + + server.listen(Config.AIMEDB_CONFIG.PORT, Config.LISTEN_ADDRESS); +} diff --git a/src/servers/aimedb/handlers/aime-account.ts b/src/servers/aimedb/handlers/aime-account.ts new file mode 100644 index 0000000..b86bc21 --- /dev/null +++ b/src/servers/aimedb/handlers/aime-account.ts @@ -0,0 +1,164 @@ +import { + AimeAccountQueryStruct, + AimeAccountResponseStruct, + AimeAccountExtendedResponseStruct, + AimeAccountExtendedQueryStruct, +} from "../types/aime-account"; +import { PacketHeaderStruct } from "../types/header"; +import { CommandId, PortalRegistration, ResultCodes } from "../utils/misc"; +import { eq } from "drizzle-orm"; +import { db } from "external/db/db"; +import { card } from "external/db/schemas"; +import CreateLogCtx from "lib/logger/logger"; +import type { AimeDBHandlerFn } from "../types/handlers"; + +const logger = CreateLogCtx(__filename); + +export const GetAimeAccountHandler: AimeDBHandlerFn<"AimeAccountResponse"> = async ( + header, + data +) => { + header.length = PacketHeaderStruct.baseSize + AimeAccountResponseStruct.baseSize; + header.commandId = CommandId.AIME_ACCOUNT_RESPONSE; + header.result = ResultCodes.SUCCESS; + + const req = new AimeAccountQueryStruct(data); + const resp = new AimeAccountResponseStruct(); + + // TODO: Actually handle portal state when we get a webUI + resp.portalRegistered = PortalRegistration.UNREGISTERED; + resp.accountId = -1; + + if (req.companyCode < 0 || req.companyCode > 4) { + logger.error("Received unknown company code. Expected a value between 0 and 4 inclusive.", { + req, + }); + header.result = ResultCodes.INVALID_AIME_ID; + return resp; + } + + const accessCode = Buffer.from(req.accessCode).toString("hex"); + + const cardRow = await db + .select() + .from(card) + .where(eq(card.accessCode, accessCode)) + .then((r) => r[0]); + + if (!cardRow) { + return resp; + } + + if (cardRow.isBanned && cardRow.isLocked) { + header.result = ResultCodes.BAN_SYSTEM_AND_USER_LOCK; + } else if (cardRow.isBanned) { + header.result = ResultCodes.BAN_SYSTEM_LOCK; + } else if (cardRow.isLocked) { + header.result = ResultCodes.USER_LOCK; + } + + resp.accountId = cardRow.id; + return resp; +}; + +export const RegisterAimeAccountHandler: AimeDBHandlerFn<"AimeAccountResponse"> = async ( + header, + data +) => { + header.length = PacketHeaderStruct.baseSize + AimeAccountResponseStruct.baseSize; + header.commandId = CommandId.AIME_ACCOUNT_RESPONSE; + header.result = ResultCodes.SUCCESS; + + const req = new AimeAccountQueryStruct(data); + const resp = new AimeAccountResponseStruct(); + + // TODO: Actually handle portal state when we get a webUI + resp.portalRegistered = PortalRegistration.UNREGISTERED; + resp.accountId = -1; + + if (req.companyCode < 0 || req.companyCode > 4) { + logger.error("Received unknown company code. Expected a value between 0 and 4 inclusive.", { + req, + }); + header.result = ResultCodes.INVALID_AIME_ID; + return resp; + } + + const accessCode = Buffer.from(req.accessCode).toString("hex"); + + const cardRow = await db + .select() + .from(card) + .where(eq(card.accessCode, accessCode)) + .then((r) => r[0]); + + if (cardRow) { + header.result = ResultCodes.ID_ALREADY_REGISTERED; + resp.accountId = cardRow.id; + return resp; + } + + const newCardRow = await db + .insert(card) + .values({ accessCode }) + .returning() + .then((r) => r[0]); + + if (!newCardRow) { + logger.crit("Failed to insert new lookup entry into the database.", { accessCode }); + header.result = ResultCodes.UNKNOWN_ERROR; + return resp; + } + + resp.accountId = newCardRow.id; + return resp; +}; + +export const GetAimeAccountExtendedHandler: AimeDBHandlerFn<"AimeAccountExtendedResponse"> = async ( + header, + data +) => { + header.length = PacketHeaderStruct.baseSize + AimeAccountExtendedResponseStruct.baseSize; + header.commandId = CommandId.EXTENDED_ACCOUNT_RESPONSE; + header.result = ResultCodes.SUCCESS; + + const req = new AimeAccountExtendedQueryStruct(data); + const resp = new AimeAccountExtendedResponseStruct(); + + // TODO: Actually handle portal state when we get a webUI + // TODO: What the fuck is an auth key + resp.portalRegistered = PortalRegistration.UNREGISTERED; + resp.accountId = -1; + + if (req.companyCode < 0 || req.companyCode > 4) { + logger.error("Received unknown company code. Expected a value between 0 and 4 inclusive.", { + req, + }); + header.result = ResultCodes.INVALID_AIME_ID; + return resp; + } + + const accessCode = Buffer.from(req.accessCode).toString("hex"); + + const cardRow = await db + .select() + .from(card) + .where(eq(card.accessCode, accessCode)) + .then((r) => r[0]); + + if (!cardRow) { + resp.accountId = -1; + return resp; + } + + if (cardRow.isBanned && cardRow.isLocked) { + header.result = ResultCodes.BAN_SYSTEM_AND_USER_LOCK; + } else if (cardRow.isBanned) { + header.result = ResultCodes.BAN_SYSTEM_LOCK; + } else if (cardRow.isLocked) { + header.result = ResultCodes.USER_LOCK; + } + + resp.accountId = cardRow.id; + return resp; +}; diff --git a/src/servers/aimedb/handlers/aime-log.ts b/src/servers/aimedb/handlers/aime-log.ts new file mode 100644 index 0000000..629700e --- /dev/null +++ b/src/servers/aimedb/handlers/aime-log.ts @@ -0,0 +1,124 @@ +import { + AimeLogStruct, + AimeLogExtendedResponseStruct, + ExtendedAimeLogStruct, + StatusLogStruct, +} from "../types/aime-log"; +import { PacketHeaderStruct } from "../types/header"; +import { CommandId, LogStatus, ResultCodes } from "../utils/misc"; +import { db } from "external/db/db"; +import { eventLog } from "external/db/schemas"; +import CreateLogCtx from "lib/logger/logger"; +import type { AimeDBHandlerFn } from "../types/handlers"; + +const logger = CreateLogCtx(__filename); + +export const StatusLogHandler: AimeDBHandlerFn = async (header, data) => { + header.commandId = CommandId.STATUS_LOG_RESPONSE; + header.result = ResultCodes.SUCCESS; + header.length = PacketHeaderStruct.baseSize; + + const req = new StatusLogStruct(data); + const statusName = LogStatus[req.status]; + + if (!statusName) { + logger.error("Unknown status for logging. Expected a value between 0 and 4.", { req }); + header.result = ResultCodes.UNKNOWN_ERROR; + return null; + } + + await db.insert(eventLog).values({ + system: "aimedb", + type: `AIMEDB_LOG_${statusName}`, + severity: "info", + details: { aimeId: req.aimeId }, + }); + + return null; +}; + +export const AimeLogHandler: AimeDBHandlerFn = async (header, data) => { + header.commandId = CommandId.AIME_LOG_RESPONSE; + header.result = ResultCodes.SUCCESS; + header.length = PacketHeaderStruct.baseSize; + + const req = new AimeLogStruct(data); + const statusName = LogStatus[req.status]; + + if (!statusName) { + logger.error("Unknown status for logging. Expected a value between 0 and 4.", { req }); + header.result = ResultCodes.UNKNOWN_ERROR; + return null; + } + + await db.insert(eventLog).values({ + system: "aimedb", + type: `AIMEDB_LOG_${statusName}`, + severity: "info", + details: { + aimeId: req.aimeId, + userId: req.userId, + creditCount: req.creditCount, + betCount: req.betCount, + wonCount: req.wonCount, + }, + }); + + return null; +}; + +export const AimeExtendedLogHandler: AimeDBHandlerFn<"AimeLogExtendedResponse"> = async ( + header, + data +) => { + header.commandId = CommandId.EXTENDED_AIME_LOG_RESPONSE; + header.result = ResultCodes.SUCCESS; + header.length = PacketHeaderStruct.baseSize; + + const req = new ExtendedAimeLogStruct(data); + const resp = new AimeLogExtendedResponseStruct(); + + await db.transaction(async (tx) => { + const ops = []; + + for (let i = 0; i < req.count; i++) { + const entry = req.entries[i]; + + if (!entry) { + throw new Error( + "There was an undefined value in the log entries. This should not be possible!" + ); + } + + const statusName = LogStatus[entry.status]; + + if (!statusName) { + logger.error( + "Unknown status for logging. Expected a value between 0 and 4.", + entry + ); + continue; + } + + ops.push( + tx.insert(eventLog).values({ + system: "aimedb", + type: `AIMEDB_LOG_${statusName}`, + severity: "info", + details: { + aimeId: entry.aimeId, + userId: entry.userId.toString(), + creditCount: entry.creditCount, + betCount: entry.betCount, + wonCount: entry.wonCount, + }, + }) + ); + resp.result[i] = 1; + } + + await Promise.all(ops); + }); + + return resp; +}; diff --git a/src/servers/aimedb/handlers/campaign.ts b/src/servers/aimedb/handlers/campaign.ts new file mode 100644 index 0000000..1fa15c0 --- /dev/null +++ b/src/servers/aimedb/handlers/campaign.ts @@ -0,0 +1,36 @@ +// TODO: Actually support campaigns +import { + CampaignClearInfoResponseStruct, + CampaignResponseStruct, + OldCampaignResponseStruct, +} from "../types/campaign"; +import { PacketHeaderStruct } from "../types/header"; +import { CommandId, ResultCodes } from "../utils/misc"; +import type { AimeDBHandlerFn } from "../types/handlers"; + +export const GetCampaignInfoHandler: AimeDBHandlerFn<"CampaignResponse" | "OldCampaignResponse"> = ( + header, + _ +) => { + header.commandId = CommandId.CAMPAIGN_INFO_RESPONSE; + header.result = ResultCodes.SUCCESS; + + if (header.version < 0x3030) { + header.length = PacketHeaderStruct.baseSize + OldCampaignResponseStruct.baseSize; + return new OldCampaignResponseStruct(); + } + + header.length = PacketHeaderStruct.baseSize + CampaignResponseStruct.baseSize; + return new CampaignResponseStruct(); +}; + +export const GetCampaignClearInfoHandler: AimeDBHandlerFn<"CampaignClearInfoResponse"> = ( + header, + _ +) => { + header.commandId = CommandId.CAMPAIGN_CLEAR_INFO_RESPONSE; + header.result = ResultCodes.SUCCESS; + header.length = PacketHeaderStruct.baseSize + CampaignClearInfoResponseStruct.baseSize; + + return new CampaignClearInfoResponseStruct(); +}; diff --git a/src/servers/aimedb/handlers/felica-conversion.ts b/src/servers/aimedb/handlers/felica-conversion.ts new file mode 100644 index 0000000..23de584 --- /dev/null +++ b/src/servers/aimedb/handlers/felica-conversion.ts @@ -0,0 +1,271 @@ +// On real ALL.Net, there's just a massive database of every supported FeliCa's +// IDm -> access code mappings. Since we don't have access to such information, +// every FeliCa card will be treated like FeliCa mobile: an access code is +// generated, and then stored with its IDm for future lookups. +// +// This also means you'll need to get some more keys, but if you're lazy +// you can probably just set +// - RESERVED_CARD_PREFIX to something not starting with 0 or 3 +// - RESERVED_CARD_KEY to a random 16-digit hex string, where each digit displays +// exactly once. +import { + FelicaExtendedLookupRequestStruct, + FelicaExtendedLookupResponseStruct, + FelicaLookupRequestStruct, + FelicaLookupResponseStruct, +} from "../types/felica-conversion"; +import { PacketHeaderStruct } from "../types/header"; +import { CalculateAccessCode } from "../utils/access-code"; +import { IsSupportedFelicaMobile, IsSupportedFelica } from "../utils/felica"; +import { CommandId, CompanyCodes, PortalRegistration, ResultCodes } from "../utils/misc"; +import { desc, eq } from "drizzle-orm"; +import { db } from "external/db/db"; +import { card, felicaCardLookup, felicaMobileLookup } from "external/db/schemas/index"; +import CreateLogCtx from "lib/logger/logger"; +import { Config } from "lib/setup/config"; +import type { AimeDBHandlerFn } from "../types/handlers"; + +const logger = CreateLogCtx(__filename); + +export const FelicaLookupHandler: AimeDBHandlerFn<"FelicaLookupResponse"> = async ( + header, + data +) => { + header.commandId = CommandId.FELICA_LOOKUP_RESPONSE; + header.length = PacketHeaderStruct.baseSize + FelicaLookupResponseStruct.baseSize; + header.result = ResultCodes.SUCCESS; + + const req = new FelicaLookupRequestStruct(data); + const resp = new FelicaLookupResponseStruct(); + + if (!IsSupportedFelica(req.osVer)) { + header.result = ResultCodes.INVALID_AIME_ID; + resp.felicaIndex = -1; + return resp; + } + + const table = IsSupportedFelicaMobile(req.osVer) ? felicaMobileLookup : felicaCardLookup; + + const result = await db + .select() + .from(table) + .where(eq(table.idm, req.idm.toString(16))) + .then((r) => r[0]); + + if (!result) { + resp.felicaIndex = -1; + } else { + resp.felicaIndex = result.id; + resp.accessCode.set(Buffer.from(result.accessCode, "hex")); + } + + return resp; +}; + +export const FelicaExtendedLookupHandler: AimeDBHandlerFn<"FelicaExtendedLookupResponse"> = async ( + header, + data +) => { + header.commandId = CommandId.EXTENDED_FELICA_ACCOUNT_RESPONSE; + header.length = PacketHeaderStruct.baseSize + FelicaExtendedLookupResponseStruct.baseSize; + header.result = ResultCodes.SUCCESS; + + const req = new FelicaExtendedLookupRequestStruct(data); + const resp = new FelicaExtendedLookupResponseStruct(); + + resp.accountId = -1; + + logger.debug("Parsed response body.", { req }); + + if (req.companyCode < 0 || req.companyCode > 4) { + header.result = ResultCodes.INVALID_AIME_ID; + return resp; + } + + if (!IsSupportedFelica(req.osVer)) { + header.result = ResultCodes.INVALID_AIME_ID; + return resp; + } + + let result; + + if (IsSupportedFelicaMobile(req.osVer)) { + result = await db + .select() + .from(felicaMobileLookup) + .where(eq(felicaMobileLookup.idm, req.idm.toString(16))) + .leftJoin(card, eq(card.accessCode, felicaMobileLookup.accessCode)) + .then((r) => r[0]); + } else { + result = await db + .select() + .from(felicaCardLookup) + .where(eq(felicaCardLookup.idm, req.idm.toString(16))) + .leftJoin(card, eq(card.accessCode, felicaCardLookup.accessCode)) + .then((r) => r[0]); + } + + if (result) { + const lookupResult = + "aimedb_felica_mobile_lookup" in result + ? result.aimedb_felica_mobile_lookup + : result.aimedb_felica_card_lookup; + const cardResult = result.aimedb_card; + + resp.accessCode.set(Buffer.from(lookupResult.accessCode, "hex")); + + if (cardResult) { + resp.accountId = cardResult.id; + resp.portalRegistered = PortalRegistration.UNREGISTERED; + + // HACK: Since we cannot possibly know who made it (even AICC cards have + // the same manufacturer code `01:2e`!), we're just going to treat everything + // as a SEGA card. + resp.companyCode = CompanyCodes.SEGA; + } + + return resp; + } + + // Assuming that FeliCa Mobile is handled by their own registration endpoint... + if (IsSupportedFelicaMobile(req.osVer)) { + return resp; + } + + // Card is not in the lookup tables, register a new card... + if (!Config.AIMEDB_CONFIG.RESERVED_CARD_KEY || !Config.AIMEDB_CONFIG.RESERVED_CARD_PREFIX) { + logger.error( + "AIMEDB_CONFIG.RESERVED_CARD_KEY or AIMEDB_CONFIG.RESERVED_CARD_PREFIX is not set in config file. Cannot generate a new access code.", + { req } + ); + + header.result = ResultCodes.INVALID_AIME_ID; + return resp; + } + + const mostRecentRow = await db + .select() + .from(felicaCardLookup) + .orderBy(desc(felicaCardLookup.id)) + .limit(1) + .then((r) => r[0]); + + const nextId = mostRecentRow ? mostRecentRow.id + 1 : 1; + + const accessCode = CalculateAccessCode( + nextId, + Config.AIMEDB_CONFIG.RESERVED_CARD_PREFIX, + Config.AIMEDB_CONFIG.RESERVED_CARD_KEY + ); + + logger.verbose(`Created FeliCa Card access code for serial ${nextId}.`, { + nextId, + accessCode, + }); + + const value = { idm: req.idm.toString(16), accessCode }; + const row = await db + .insert(felicaCardLookup) + .values(value) + .returning() + .then((r) => r[0]); + + if (!row) { + logger.crit("Failed to insert new lookup entry into the database.", value); + + header.result = ResultCodes.UNKNOWN_ERROR; + return resp; + } + + header.result = ResultCodes.SUCCESS; + resp.accessCode.set(Buffer.from(row.accessCode, "hex")); + + return resp; +}; + +export const FelicaRegisterHandler: AimeDBHandlerFn<"FelicaLookupResponse"> = async ( + header, + data +) => { + header.commandId = CommandId.FELICA_LOOKUP_RESPONSE; + header.length = PacketHeaderStruct.baseSize + FelicaLookupResponseStruct.baseSize; + + const req = new FelicaLookupRequestStruct(data); + const resp = new FelicaLookupResponseStruct(); + + if (!IsSupportedFelica(req.osVer)) { + logger.verbose("Rejecting card of unknown OS version.", { + req, + }); + + header.result = ResultCodes.INVALID_AIME_ID; + resp.felicaIndex = -1; + return resp; + } + + const result = await db + .select() + .from(felicaMobileLookup) + .where(eq(felicaMobileLookup.idm, req.idm.toString(16))) + .limit(1) + .then((r) => r[0]); + + if (result) { + header.result = ResultCodes.ID_ALREADY_REGISTERED; + resp.felicaIndex = result.id; + resp.accessCode.set(Buffer.from(result.accessCode, "hex")); + + return resp; + } + + if (!Config.AIMEDB_CONFIG.AIME_MOBILE_CARD_KEY) { + logger.error( + "AIMEDB_CONFIG.AIME_MOBILE_CARD_KEY is not set in config file. Cannot register FeliCa Mobile ID.", + { req } + ); + + header.result = ResultCodes.INVALID_AIME_ID; + resp.felicaIndex = -1; + return resp; + } + + const mostRecentRow = await db + .select() + .from(felicaMobileLookup) + .orderBy(desc(felicaMobileLookup.id)) + .limit(1) + .then((r) => r[0]); + + const nextId = mostRecentRow ? mostRecentRow.id + 1 : 1; + + const accessCode = CalculateAccessCode( + nextId, + "01035", + Config.AIMEDB_CONFIG.AIME_MOBILE_CARD_KEY + ); + + logger.verbose(`Created FeliCa Mobile access code for serial ${nextId}.`, { + nextId, + accessCode, + }); + + const value = { idm: req.idm.toString(16), accessCode }; + const row = await db + .insert(felicaMobileLookup) + .values(value) + .returning() + .then((r) => r[0]); + + if (!row) { + logger.crit("Failed to insert new lookup entry into the database.", value); + header.result = ResultCodes.UNKNOWN_ERROR; + resp.felicaIndex = -1; + return resp; + } + + header.result = ResultCodes.SUCCESS; + resp.felicaIndex = row.id; + resp.accessCode.set(Buffer.from(row.accessCode, "hex")); + + return resp; +}; diff --git a/src/servers/aimedb/handlers/index.ts b/src/servers/aimedb/handlers/index.ts new file mode 100644 index 0000000..98380dc --- /dev/null +++ b/src/servers/aimedb/handlers/index.ts @@ -0,0 +1,56 @@ +import { + GetAimeAccountHandler, + GetAimeAccountExtendedHandler, + RegisterAimeAccountHandler, +} from "./aime-account"; +import { AimeExtendedLogHandler, AimeLogHandler, StatusLogHandler } from "./aime-log"; +import { GetCampaignClearInfoHandler, GetCampaignInfoHandler } from "./campaign"; +import { + FelicaExtendedLookupHandler, + FelicaLookupHandler, + FelicaRegisterHandler, +} from "./felica-conversion"; +import { ServiceHealthCheckHandler } from "./status-check"; +import { CommandId } from "../utils/misc"; +import type { AimeDBHandlerFn, AimeDBReturnTypes } from "../types/handlers"; + +type CommandIdRequest = { + [K in keyof typeof CommandId]: K extends `${infer _}_REQUEST` ? typeof CommandId[K] : never; +}[keyof typeof CommandId]; + +// We need to make the key type wider so that the request handler can still index with +// an arbitrary command ID. On the other hand, the `satisfies` clause makes TypeScript +// yells at us for any known unimplemented AimeDB commands. +export const AIMEDB_HANDLERS: Record> = { + [CommandId.FELICA_LOOKUP_REQUEST]: FelicaLookupHandler, + [CommandId.FELICA_REGISTER_REQUEST]: FelicaRegisterHandler, + [CommandId.AIME_ACCOUNT_REQUEST]: GetAimeAccountHandler, + [CommandId.REGISTER_AIME_ACCOUNT_REQUEST]: RegisterAimeAccountHandler, + [CommandId.STATUS_LOG_REQUEST]: StatusLogHandler, + [CommandId.AIME_LOG_REQUEST]: AimeLogHandler, + [CommandId.EXTENDED_AIME_LOG_REQUEST]: AimeExtendedLogHandler, + [CommandId.CAMPAIGN_INFO_REQUEST]: GetCampaignInfoHandler, + [CommandId.CAMPAIGN_CLEAR_INFO_REQUEST]: GetCampaignClearInfoHandler, + [CommandId.EXTENDED_ACCOUNT_REQUEST]: GetAimeAccountExtendedHandler, + [CommandId.EXTENDED_FELICA_ACCOUNT_REQUEST]: FelicaExtendedLookupHandler, + [CommandId.SERVICE_HEALTH_REQUEST]: ServiceHealthCheckHandler, +} satisfies Record< + Exclude, + AimeDBHandlerFn +>; + +export const EXPECTED_PACKET_LENGTH: Record = { + [CommandId.FELICA_LOOKUP_REQUEST]: 48, + [CommandId.FELICA_REGISTER_REQUEST]: 48, + [CommandId.AIME_ACCOUNT_REQUEST]: 48, + [CommandId.REGISTER_AIME_ACCOUNT_REQUEST]: 48, + [CommandId.STATUS_LOG_REQUEST]: 48, + [CommandId.AIME_LOG_REQUEST]: 64, + [CommandId.EXTENDED_AIME_LOG_REQUEST]: 1008, + [CommandId.CAMPAIGN_INFO_REQUEST]: 48, + [CommandId.CAMPAIGN_CLEAR_INFO_REQUEST]: 48, + [CommandId.EXTENDED_ACCOUNT_REQUEST]: 48, + [CommandId.EXTENDED_FELICA_ACCOUNT_REQUEST]: 112, + [CommandId.SERVICE_HEALTH_REQUEST]: 32, + [CommandId.CLIENT_END_REQUEST]: 32, +} satisfies Record; diff --git a/src/servers/aimedb/handlers/status-check.ts b/src/servers/aimedb/handlers/status-check.ts new file mode 100644 index 0000000..eff7012 --- /dev/null +++ b/src/servers/aimedb/handlers/status-check.ts @@ -0,0 +1,11 @@ +import { PacketHeaderStruct } from "../types/header"; +import { CommandId, ResultCodes } from "../utils/misc"; +import type { AimeDBHandlerFn } from "../types/handlers"; + +export const ServiceHealthCheckHandler: AimeDBHandlerFn = (header, _) => { + header.result = ResultCodes.SUCCESS; + header.commandId = CommandId.SERVICE_HEALTH_RESPONSE; + header.length = PacketHeaderStruct.baseSize; + + return null; +}; diff --git a/src/servers/aimedb/index.ts b/src/servers/aimedb/index.ts new file mode 100644 index 0000000..30ab55d --- /dev/null +++ b/src/servers/aimedb/index.ts @@ -0,0 +1,178 @@ +import { AIMEDB_HANDLERS, EXPECTED_PACKET_LENGTH } from "./handlers"; +import { PacketHeaderStruct } from "./types/header"; +import { decryptPacket, encryptPacket } from "./utils/crypto"; +import { CommandId, ResultCodes } from "./utils/misc"; +import CreateLogCtx from "lib/logger/logger"; +import { Config } from "lib/setup/config"; +import { createHash } from "crypto"; +import type { Socket } from "net"; + +const logger = CreateLogCtx(__filename); + +/** + * For legal reasons, we probably should not include the actual AimeDB key here. + * However, we can still check the key for correctness, so that users get feedback. + */ +const AIMEDB_KEY_SHA256 = "4968f79897cd9517f2b6050a951456106ca98b23535b3e985d62a800b66f3240"; + +const AimeDBServerFactory = () => { + if (!Config.AIMEDB_CONFIG.KEY) { + throw new Error("AimeDB key not set."); + } + + const hash = createHash("sha256"); + const digest = hash.update(Config.AIMEDB_CONFIG.KEY).digest("hex"); + + if (digest !== AIMEDB_KEY_SHA256) { + logger.warn( + "AimeDB key seems incorrect. Allowing it anyways, though games will probably break.", + { + key: Config.AIMEDB_CONFIG.KEY, + expectedSha256: AIMEDB_KEY_SHA256, + } + ); + } + + const AIMEDB_KEY = Buffer.from(Config.AIMEDB_CONFIG.KEY, "utf-8"); + + const logResponse = (header: InstanceType, body: unknown) => { + if (header.result !== 1) { + logger.info(`Returned result code ${header.result}.`, { + header, + body, + }); + } else { + logger.verbose(`Returned result code ${header.result}.`, { + header, + body, + }); + } + }; + + const writeResponse = ( + socket: Socket, + header: InstanceType, + body: unknown + ) => { + const headerBuf = PacketHeaderStruct.raw(header); + const chunks = [headerBuf]; + + // https://github.com/sarakusha/typed-struct/blob/main/src/struct.ts#L799 + if (body !== null && typeof body === "object" && "$raw" in body) { + const bodyBuf = (body as { $raw: Buffer }).$raw; + + chunks.push(bodyBuf); + } + + const raw = Buffer.concat(chunks); + + let encrypted: Buffer; + + try { + encrypted = encryptPacket(raw, AIMEDB_KEY); + } catch (err) { + logger.error("Could not encrypt AimeDB response.", { err }); + return; + } + + socket.write(encrypted); + }; + + return (socket: Socket) => { + socket.on("connect", () => { + logger.debug(`${socket.remoteAddress} connected.`); + }); + + socket.on("data", async (data) => { + logger.verbose(`Received packet: ${data.toString("hex")}.`); + + let packet: Buffer; + + try { + packet = decryptPacket(data, AIMEDB_KEY); + } catch (err) { + logger.error("Could not decrypt AimeDB packet.", { + err, + }); + return; + } + + let header; + + try { + header = new PacketHeaderStruct(packet.slice(0, 32)); + } catch (err) { + logger.error("Decoding AimeDB header failed.", { + err, + data: packet.toString("hex"), + }); + return; + } + + logger.debug("Received AimeDB request.", { + header, + data: packet.slice(32).toString("hex"), + }); + + if (header.magic !== 0xa13e) { + logger.error("Request's magic bytes did not match expected value 0xA13E.", { + header, + }); + return; + } + + if (header.keychipId === "ABCD1234567" || header.storeId === 0xfff0) { + logger.warning("Received request from uninitialized AMLib.", { header }); + } + + if (header.commandId === CommandId.CLIENT_END_REQUEST) { + logger.debug("Client ended the session.", { header }); + socket.destroy(); + return; + } + + const expectedLength = EXPECTED_PACKET_LENGTH[header.commandId]; + + if (!expectedLength) { + logger.warn( + `Packet 0x${header.commandId.toString( + 16 + )} does not declare an expected size. Allowing all packets.`, + { header } + ); + } else if (expectedLength !== header.length || packet.length !== header.length) { + logger.error("Packet does not have expected size.", { + expectedLength, + actualLength: packet.length, + declaredLength: header.length, + }); + + header.result = ResultCodes.UNKNOWN_ERROR; + header.length = 32; + + logResponse(header, null); + writeResponse(socket, header, null); + + return; + } + + const handler = AIMEDB_HANDLERS[header.commandId]; + + if (!handler) { + logger.error("No handlers available for the requested command ID.", { header }); + return; + } + + const body = await handler(header, packet.slice(32)); + + logResponse(header, body); + writeResponse(socket, header, body); + }); + + socket.on("end", () => { + logger.debug(`${socket.remoteAddress} disconnected.`); + }); + }; +}; + +export default AimeDBServerFactory; diff --git a/src/servers/aimedb/types/aime-account.ts b/src/servers/aimedb/types/aime-account.ts new file mode 100644 index 0000000..a17ebac --- /dev/null +++ b/src/servers/aimedb/types/aime-account.ts @@ -0,0 +1,30 @@ +import Struct from "typed-struct"; + +export const AimeAccountQueryStruct = new Struct("AimeAccountQuery") + .UInt8Array("accessCode", 10) + .UInt8("companyCode") + .UInt8("firmwareVersion") + .UInt32LE("serialNumber") + .compile(); + +export const AimeAccountResponseStruct = new Struct("AimeAccountResponse") + .UInt32LE("accountId") + .UInt8("portalRegistered") + .UInt8Array("padding", 11) + .compile(); + +export const AimeAccountExtendedQueryStruct = new Struct("AimeAccountExtendedQuery") + .UInt8Array("accessCode", 10) + .UInt8("companyCode") + .UInt8("readerFirmwareVersion") + .UInt32LE("cardSerialNumber") + .compile(); + +export const AimeAccountExtendedResponseStruct = new Struct("AimeAccountExtendedResponse") + .UInt32LE("accountId") + .UInt8("portalRegistered") + .UInt8Array("padding", 3) + .UInt8Array("authKey", 256) + .UInt32LE("relationId1") + .UInt32LE("relationId2") + .compile(); diff --git a/src/servers/aimedb/types/aime-log.ts b/src/servers/aimedb/types/aime-log.ts new file mode 100644 index 0000000..fc585ad --- /dev/null +++ b/src/servers/aimedb/types/aime-log.ts @@ -0,0 +1,41 @@ +import Struct from "typed-struct"; + +export const StatusLogStruct = new Struct("StatusLog") + .UInt32LE("aimeId") + .UInt32LE("status") + .UInt8Array("padding", 8) + .compile(); + +export const AimeLogStruct = new Struct("AimeLog") + .UInt32LE("aimeId") + .UInt32LE("status") + .BigUInt64LE("userId") + .Int32LE("creditCount") + .Int32LE("betCount") + .Int32LE("wonCount") + .UInt8Array("padding", 4) + .compile(); + +export const ExtendedAimeLogEntryStruct = new Struct("ExtendedAimeLogEntry") + .UInt32LE("aimeId") + .UInt32LE("status") + .BigUInt64LE("userId") + .Int32LE("creditCount") + .Int32LE("betCount") + .Int32LE("wonCount") + .UInt8Array("padding", 4) + .BigUInt64LE("localTime") + .Int32LE("tSeq") + .UInt32LE("placeId") + .compile(); + +export const ExtendedAimeLogStruct = new Struct("ExtendedAimeLog") + .StructArray("entries", ExtendedAimeLogEntryStruct, 20) + .UInt32LE("count") + .UInt8Array("padding", 12) + .compile(); + +export const AimeLogExtendedResponseStruct = new Struct("AimeLogExtendedResponse") + .UInt8Array("result", 20) + .UInt8Array("padding", 12) + .compile(); diff --git a/src/servers/aimedb/types/campaign.ts b/src/servers/aimedb/types/campaign.ts new file mode 100644 index 0000000..5379734 --- /dev/null +++ b/src/servers/aimedb/types/campaign.ts @@ -0,0 +1,47 @@ +import Struct from "typed-struct"; + +/** + * Retrieve information regarding currently active campaigns. + */ +export const OldCampaignRequestStruct = new Struct("OldCampaignRequest") + .UInt32LE("campaignId") + .UInt8Array("padding", 12) + .compile(); + +export const OldCampaignResponseStruct = new Struct("OldCampaignResponse") + .Int32LE("info0") + .Int32LE("info1") + .Int32LE("info2") + .Int32LE("info3") + .compile(); + +const CampaignStruct = new Struct("Campaign") + .UInt32LE("campaignId") + .String("campaignName", 128) + .UInt32LE("announceDate") + .UInt32LE("startDate") + .UInt32LE("endDate") + .UInt32LE("distributionStartDate") + .UInt32LE("distributionEndDate") + .UInt8Array("padding", 8) + .compile(); + +export const CampaignResponseStruct = new Struct("CampaignResponse") + .StructArray("campaigns", CampaignStruct, 3) + .compile(); + +export const CampaignClearInfoRequestStruct = new Struct("CampaignClearInfoRequest") + .UInt32LE("aimeId") + .UInt8Array("padding", 12) + .compile(); + +export const CampaignClearInfoStruct = new Struct("CampaignClearInfo") + .UInt32LE("campaignId") + .UInt32LE("entryFlag") + .UInt32LE("clearFlag") + .UInt8Array("padding", 4) + .compile(); + +export const CampaignClearInfoResponseStruct = new Struct("CampaignClearInfoResponse") + .StructArray("clearInfos", CampaignClearInfoStruct, 3) + .compile(); diff --git a/src/servers/aimedb/types/felica-conversion.ts b/src/servers/aimedb/types/felica-conversion.ts new file mode 100644 index 0000000..61e9cfa --- /dev/null +++ b/src/servers/aimedb/types/felica-conversion.ts @@ -0,0 +1,40 @@ +import Struct from "typed-struct"; + +export const FelicaLookupRequestStruct = new Struct("FelicaLookupRequest") + .BigUInt64LE("idm") + .UInt8("chipCode") + .UInt8("osVer") + .UInt8Array("timing", 6) + .compile(); + +export const FelicaLookupResponseStruct = new Struct("FelicaLookupResponse") + .UInt32LE("felicaIndex") + .UInt8Array("accessCode", 10) + .UInt16LE("padding") + .compile(); + +export const FelicaExtendedLookupRequestStruct = new Struct("FelicaExtendedLookupRequest") + .UInt8Array("randomChallenge", 16) + .BigUInt64LE("idm") + .UInt8("chipCode") + .UInt8("osVer") + .UInt8Array("timing", 6) + .UInt8Array("cardKeyVersion", 16) + .UInt8Array("writeCount", 16) + .BigUInt64LE("maca") + .UInt8("companyCode") + .UInt8("readerFirmwareVersion") + .UInt16LE("DFC") + .UInt8Array("padding", 4) + .compile(); + +export const FelicaExtendedLookupResponseStruct = new Struct("FelicaExtendedLookupResponse") + .UInt32LE("accountId") + .UInt32LE("relationId1") + .UInt32LE("relationId2") + .UInt8Array("accessCode", 10) + .UInt8("portalRegistered") + .UInt8("companyCode") + .UInt8Array("padding", 8) + .UInt8Array("authKey", 256) + .compile(); diff --git a/src/servers/aimedb/types/handlers.ts b/src/servers/aimedb/types/handlers.ts new file mode 100644 index 0000000..50b622e --- /dev/null +++ b/src/servers/aimedb/types/handlers.ts @@ -0,0 +1,31 @@ +import type { PacketHeaderStruct } from "./header"; +import type { StructConstructor } from "typed-struct"; + +export type AimeDBHandlerReturnType = InstanceType< + StructConstructor, S> +>; + +export type AimeDBReturnTypes = + | "__no_body" + | "AimeAccountExtendedResponse" + | "AimeAccountResponse" + | "AimeLogExtendedResponse" + | "CampaignClearInfoResponse" + | "CampaignResponse" + | "FelicaExtendedLookupResponse" + | "FelicaLookupResponse" + | "OldCampaignResponse"; + +type MaybePromise = Promise | T; + +/** + * Base type for all AimeDB command handlers. + * + * All AimeDB handlers must modify the request header and only return the request body. + * The base handler will merge them into one. + */ + +export type AimeDBHandlerFn = ( + header: InstanceType, + data: Buffer +) => MaybePromise<(S extends "__no_body" ? never : AimeDBHandlerReturnType) | null | undefined>; diff --git a/src/servers/aimedb/types/header.ts b/src/servers/aimedb/types/header.ts new file mode 100644 index 0000000..ce4206c --- /dev/null +++ b/src/servers/aimedb/types/header.ts @@ -0,0 +1,12 @@ +import Struct from "typed-struct"; + +export const PacketHeaderStruct = new Struct("PacketHeader") + .UInt16LE("magic") + .UInt16LE("version") + .UInt16LE("commandId") + .UInt16LE("length") + .UInt16LE("result") + .String("gameId", 6) + .UInt32LE("storeId") + .String("keychipId", 12) + .compile(); diff --git a/src/servers/aimedb/utils/access-code.ts b/src/servers/aimedb/utils/access-code.ts new file mode 100644 index 0000000..5b59331 --- /dev/null +++ b/src/servers/aimedb/utils/access-code.ts @@ -0,0 +1,53 @@ +import { Solitaire } from "./crypto"; +import { createHash } from "crypto"; +import type { integer } from "types/misc"; + +function reverseString(data: string) { + return Array.from(data).reverse().join(""); +} + +function CalculateCardKey(serial: integer, key: string) { + const paddedSerial = serial.toString().padStart(8, "0"); + const realDigest = createHash("md5").update(paddedSerial).digest(); + + const digest = new Array(16); + + for (let i = 0; i < 16; i++) { + const idx = Number(`0x${key[i]}`); + const nib = realDigest[idx]; + + if (nib === undefined) { + throw new Error( + "crypto.createHash returned an undefined value in a Buffer. this should not happen." + ); + } + + digest[i] = nib; + } + + // nasty ass bit string hacks that i am not good enough at math to replace + let bitstring = reverseString( + digest.map((n) => reverseString(n.toString(2).padStart(8, "0"))).join("") + ).padStart(6 * 23, "0"); + let computed = 0; + + while (bitstring) { + const work = Number(`0b${bitstring.slice(0, 23)}`); + + // eslint-disable-next-line no-bitwise + computed = computed ^ work; + + bitstring = bitstring.slice(23); + } + + return computed.toString().padStart(7, "0"); +} + +export function CalculateAccessCode(serial: integer, prefix: string, key: string): string { + const digest = CalculateCardKey(serial, key); + + const paddedSerial = serial.toString().padStart(8, "0"); + const hashedId = Solitaire.encrypt(paddedSerial, digest); + + return `${prefix}${hashedId}${digest}`; +} diff --git a/src/servers/aimedb/utils/crypto.ts b/src/servers/aimedb/utils/crypto.ts new file mode 100644 index 0000000..01c6dba --- /dev/null +++ b/src/servers/aimedb/utils/crypto.ts @@ -0,0 +1,230 @@ +/* eslint-disable no-bitwise */ +import { createCipheriv, createDecipheriv } from "crypto"; +import type { integer } from "types/misc"; + +const ASCII_0 = 48; + +export function encryptPacket(packet: Buffer, key: Buffer) { + const cipher = createCipheriv("aes-128-ecb", key, null).setAutoPadding(false); + + return Buffer.concat([cipher.update(packet), cipher.final()]); +} + +export function decryptPacket(packet: Buffer, key: Buffer) { + const cipher = createDecipheriv("aes-128-ecb", key, null).setAutoPadding(false); + + return Buffer.concat([cipher.update(packet), cipher.final()]); +} + +function char2num(char: string) { + return char.charCodeAt(0) - ASCII_0 + 1; +} + +function num2char(num: integer) { + let inner = num; + + while (inner < 1) { + inner = inner + 10; + } + + // 48 is ASCII 0 + return String.fromCharCode(((inner - 1) % 10) + ASCII_0); +} + +/** + * A modified version of the [Solitaire cipher](https://en.wikipedia.org/wiki/Solitaire_(cipher)), + * used for encrypting and decrypting access codes. + */ +export class Solitaire { + private deck: Array; + private readonly deckSize: integer; + readonly jokerA: integer; + readonly jokerB: integer; + + constructor(deckSize: integer, jokerA?: integer, jokerB?: integer) { + if (jokerA && jokerA > deckSize) { + throw new Error( + "Invalid jokerA. jokerA must not be larger than the largest card on deck." + ); + } + + if (jokerB && jokerB > deckSize) { + throw new Error( + "Invalid jokerB. jokerB must not be larger than the largest card on deck." + ); + } + + this.jokerA = jokerA ?? deckSize - 1; + this.jokerB = jokerB ?? deckSize; + this.deck = [...Array(deckSize).keys()].map((v) => v + 1); + this.deckSize = deckSize; + } + + static encrypt(src: string, key: string) { + const deck = new Solitaire(22, 21, 22); + + for (const char of key) { + deck.deckHash(); + deck.cutDeck(char2num(char)); + } + + let output = ""; + + for (const char of src) { + deck.deckHash(); + + const p = deck.getTopCardNumber() ?? 0; + + output = output + num2char(char2num(char) + p); + } + + return output; + } + + static decrypt(src: string, key: string) { + const deck = new Solitaire(22, 21, 22); + + for (const char of key) { + deck.deckHash(); + deck.cutDeck(char2num(char)); + } + + let output = ""; + + for (const char of src) { + deck.deckHash(); + + const p = deck.getTopCardNumber() ?? 0; + + output = output + num2char(char2num(char) - p); + } + + return output; + } + + private moveCardDown(card: integer) { + const cardLocation = this.deck.indexOf(card); + + if (cardLocation === -1) { + throw new Error("Card was not in the deck."); + } + + if (cardLocation < this.deckSize - 1) { + const nextCard = this.deck[cardLocation + 1]; + + if (!nextCard) { + throw new Error("Next card is undefined. This should not be possible."); + } + + this.deck[cardLocation] = nextCard; + this.deck[cardLocation + 1] = card; + } else { + for (let i = this.deckSize - 1; i > 1; i--) { + const prevCard = this.deck[i - 1]; + + if (!prevCard) { + throw new Error("Previous card is undefined. This should not be possible."); + } + + this.deck[i] = prevCard; + } + + this.deck[1] = card; + } + } + + private cutDeck(point: integer) { + const tmpDeck = this.deck.slice(0); + + let idx = 0; + + for (let i = point; i < this.deckSize - 1; i++) { + const item = tmpDeck[i]; + + if (!item) { + throw new Error("not happening."); + } + + this.deck[idx] = item; + idx++; + } + + for (let i = 0; i < point; i++) { + const item = tmpDeck[i]; + + if (!item) { + throw new Error("not happening."); + } + + this.deck[idx] = item; + idx++; + } + } + + private swapOutsideJoker() { + let joker1 = -1; + let joker1Value = -1; + let joker2 = -1; + let joker2Value = -1; + + for (let i = 0; i < this.deckSize; i++) { + const card = this.deck[i]; + + if (!card) { + continue; + } + + if (card === this.jokerA || card === this.jokerB) { + if (joker1 === -1) { + joker1 = i; + joker1Value = card; + } else { + joker2 = i; + joker2Value = card; + } + } + } + + this.deck = [ + ...this.deck.slice(joker2 + 1), + joker1Value, + ...this.deck.slice(joker1 + 1, joker2), + joker2Value, + ...this.deck.slice(0, joker1), + ]; + } + + private cutByBottomCard() { + const bottom = this.deck[this.deckSize - 1]; + + if (!bottom) { + throw new Error("bottom card is undefined (not possbile)"); + } + + this.cutDeck(bottom === this.jokerB ? this.jokerA : bottom); + } + + private getTopCardNumber() { + const top = this.deck[0]; + + if (!top) { + throw new Error("top card is undefined (not possbile)"); + } + + return this.deck[top === this.jokerB ? this.jokerA : top]; + } + + private deckHash() { + let p = -1; + + do { + this.moveCardDown(this.jokerA); + this.moveCardDown(this.jokerB); + this.moveCardDown(this.jokerB); + this.swapOutsideJoker(); + this.cutByBottomCard(); + + p = this.getTopCardNumber() ?? -1; + } while (p === this.jokerA || p === this.jokerB); + } +} diff --git a/src/servers/aimedb/utils/felica.ts b/src/servers/aimedb/utils/felica.ts new file mode 100644 index 0000000..d23d62d --- /dev/null +++ b/src/servers/aimedb/utils/felica.ts @@ -0,0 +1,20 @@ +const FELICA_MOBILE_OS_VERSIONS = [0x06, 0x07, 0x10, 0x12, 0x13, 0x14, 0x15, 0x17, 0x18] as const; +const FELICA_CARD_OS_VERSIONS = [0x20, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7] as const; + +export function IsSupportedFelicaMobile( + osVer: number +): osVer is typeof FELICA_MOBILE_OS_VERSIONS[number] { + return (FELICA_MOBILE_OS_VERSIONS as ReadonlyArray).includes(osVer); +} + +export function IsSupportedFelicaCard( + osVer: number +): osVer is typeof FELICA_CARD_OS_VERSIONS[number] { + return (FELICA_CARD_OS_VERSIONS as ReadonlyArray).includes(osVer); +} + +export function IsSupportedFelica( + osVer: number +): osVer is typeof FELICA_CARD_OS_VERSIONS[number] | typeof FELICA_MOBILE_OS_VERSIONS[number] { + return IsSupportedFelicaMobile(osVer) || IsSupportedFelicaCard(osVer); +} diff --git a/src/servers/aimedb/utils/misc.ts b/src/servers/aimedb/utils/misc.ts new file mode 100644 index 0000000..4737a7b --- /dev/null +++ b/src/servers/aimedb/utils/misc.ts @@ -0,0 +1,70 @@ +export const enum ResultCodes { + UNKNOWN_ERROR = 0, + SUCCESS = 1, + INVALID_AIME_ID = 2, + ID_ALREADY_REGISTERED = 3, + BAN_SYSTEM_AND_USER_LOCK = 4, + BAN_SYSTEM_LOCK = 5, + BAN_USER_LOCK = 6, + BAN_GENERIC_LOCK = 7, + SYSTEM_AND_USER_LOCK = 8, + SYSTEM_LOCK = 9, + USER_LOCK = 10, +} + +export const enum CommandId { + FELICA_LOOKUP_REQUEST = 1, + FELICA_REGISTER_REQUEST = 2, + FELICA_LOOKUP_RESPONSE = 3, + + AIME_ACCOUNT_REQUEST = 4, + REGISTER_AIME_ACCOUNT_REQUEST = 5, + AIME_ACCOUNT_RESPONSE = 6, + + STATUS_LOG_REQUEST = 7, + STATUS_LOG_RESPONSE = 8, + + AIME_LOG_REQUEST = 9, + AIME_LOG_RESPONSE = 10, + + CAMPAIGN_INFO_REQUEST = 11, + CAMPAIGN_INFO_RESPONSE = 12, + + CAMPAIGN_CLEAR_INFO_REQUEST = 13, + CAMPAIGN_CLEAR_INFO_RESPONSE = 14, + + EXTENDED_ACCOUNT_REQUEST = 15, + EXTENDED_ACCOUNT_RESPONSE = 16, + + EXTENDED_FELICA_ACCOUNT_REQUEST = 17, + EXTENDED_FELICA_ACCOUNT_RESPONSE = 18, + + EXTENDED_AIME_LOG_REQUEST = 19, + EXTENDED_AIME_LOG_RESPONSE = 20, + + SERVICE_HEALTH_REQUEST = 100, + SERVICE_HEALTH_RESPONSE = 101, + + CLIENT_END_REQUEST = 102, +} + +export enum LogStatus { + NONE = 0, + GAME_START = 1, + GAME_CONTINUE = 2, + GAME_END = 3, + OTHERS = 4, +} + +export const enum PortalRegistration { + UNREGISTERED = 0, + REGISTERED_ON_PORTAL = 1, + LINKED_TO_ID = 2, +} + +export const enum CompanyCodes { + SEGA = 1, + BANDAI_NAMCO = 2, + KONAMI = 3, + TAITO = 4, +} diff --git a/src/servers/allnet/index.ts b/src/servers/allnet/index.ts new file mode 100644 index 0000000..f4fd266 --- /dev/null +++ b/src/servers/allnet/index.ts @@ -0,0 +1,77 @@ +// THIS IMPORT **MUST** GO HERE. DO NOT MOVE IT. IT MUST OCCUR BEFORE ANYTHING HAPPENS WITH EXPRESS +// BUT AFTER EXPRESS IS IMPORTED. +/* eslint-disable import/order */ +import express from "express"; +import "express-async-errors"; + +// eslint-disable-next-line import/order +import mainRouter from "./router/router"; +import CreateLogCtx from "lib/logger/logger"; +import { DFIRequestResponse } from "./middleware/dfi"; +import type { Express } from "express"; +import { RequestLoggerMiddleware } from "./middleware/request-logger"; +import { IsRecord } from "utils/misc"; + +const logger = CreateLogCtx(__filename); + +const app: Express = express(); + +// Pass the IP of the user up our increasingly insane chain of nginx/docker nonsense +app.set("trust proxy", ["loopback", "linklocal", "uniquelocal"]); + +// we don't allow nesting in query strings. +app.set("query parser", "simple"); + +// taken from https://nodejs.org/api/process.html#process_event_unhandledrejection +// to avoid future deprecation. +process.on("unhandledRejection", (reason, promise) => { + // @ts-expect-error reason is an error, and the logger can handle errors + // it just refuses. + logger.error(reason, { promise }); +}); + +// ALL.Net sends a form body that is sometimes deflated and base64-encoded. +// This also does some special handling to prevent keys/values from being +// URL-escaped, which ALL.Net doesn't do. Pray they don't need an & or a =. +app.use(DFIRequestResponse); + +app.use((req, res, next) => { + if (req.method !== "GET" && (typeof req.body !== "object" || req.body === null)) { + req.body = {}; + } + + req.safeBody = req.body as Record; + + next(); +}); + +app.use(RequestLoggerMiddleware); + +app.use("/", mainRouter); + +const MAIN_ERR_HANDLER: express.ErrorRequestHandler = (err, req, res, _next) => { + logger.info(`MAIN_ERR_HANDLER hit by request.`, { url: req.originalUrl }); + + const unknownErr = err as unknown; + + if (IsRecord(unknownErr) && unknownErr.type === "entity.too.large") { + return res.status(413).json({ + success: false, + description: "Your request body was too large. The limit is 4MB.", + }); + } + + logger.error("Fatal error propagated to server root? ", { + err: unknownErr, + url: req.originalUrl, + }); + + return res.status(500).json({ + success: false, + description: "A fatal internal server error has occured.", + }); +}; + +app.use(MAIN_ERR_HANDLER); + +export default app; diff --git a/src/servers/allnet/middleware/dfi.ts b/src/servers/allnet/middleware/dfi.ts new file mode 100644 index 0000000..6a477d7 --- /dev/null +++ b/src/servers/allnet/middleware/dfi.ts @@ -0,0 +1,64 @@ +import iconv from "iconv-lite"; +import getRawBody from "raw-body"; +import { promisify } from "util"; +import { inflate } from "zlib"; +import type { RequestHandler } from "express"; + +const inflateAsync = promisify(inflate); + +export const DFIRequestResponse: RequestHandler = async (req, res, next) => { + if (Number(req.headers["content-length"] ?? 0) === 0) { + next(); + return; + } + + const isUsingDfi = req.headers.pragma?.toUpperCase() === "DFI"; + + const rawBody = await getRawBody(req, { encoding: "utf-8" }); + + let body: string; + + if (isUsingDfi) { + const compressedBuffer = Buffer.from(rawBody, "base64"); + const buffer = await inflateAsync(compressedBuffer); + + body = buffer.toString("utf-8").trim(); + } else { + body = rawBody.trim(); + } + + // Keys and values are not URL escaped. + // This should be fine. I think. + // eslint-disable-next-line require-atomic-updates + req.body = Object.fromEntries(body.split("&").map((s) => s.split("="))); + + const originalSend = res.send; + + res.send = (params) => { + const body = + typeof params === "object" + ? `${Object.entries(params) + .map(([k, v]) => `${k}=${v}`) + .join("&")}\n` + : params; + + const encoding = req.body.encode ?? "EUC-JP"; + const encodedBody = iconv.encode(body, encoding); + + res.header("Content-Type", `text/plain; charset=${encoding}`); + + // TODO: I don't know what black magic SEGA did, but I have been woefully + // unable to DFI-encode my responses... + return originalSend.apply(res, [encodedBody]); + + // if (req.headers.pragma?.toUpperCase() !== "DFI") { + // return originalSend.apply(res, [encodedBody]); + // } + + // res.header("Pragma", "DFI"); + + // return originalSend.apply(res, [deflateSync(encodedBody).toString("base64")]); + }; + + next(); +}; diff --git a/src/servers/allnet/middleware/request-logger.ts b/src/servers/allnet/middleware/request-logger.ts new file mode 100644 index 0000000..7d94222 --- /dev/null +++ b/src/servers/allnet/middleware/request-logger.ts @@ -0,0 +1,56 @@ +import CreateLogCtx from "lib/logger/logger"; +import type { RequestHandler, Response } from "express"; + +const logger = CreateLogCtx(__filename); + +// https://stackoverflow.com/a/64546368/11885828 +const ResSendInterceptor = (res: Response, send: Response["send"]) => (content: unknown) => { + // @ts-expect-error general monkeypatching error + res.contentBody = content; + res.send = send; + res.send(content); +}; + +export const RequestLoggerMiddleware: RequestHandler = (req, res, next) => { + logger.debug(`Received request ${req.method} ${req.originalUrl}.`, { + query: req.query, + body: req.body, + }); + + // @ts-expect-error we're doing some wacky monkey patching + res.send = ResSendInterceptor(res, res.send); + + res.on("finish", () => { + const contents = { + // @ts-expect-error we're doing some monkey patching - contentBody is what we're returning. + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + body: res.contentBody, + statusCode: res.statusCode, + requestQuery: req.query, + requestBody: req.body, + fromIp: req.ip, + }; + + // special overrides + // This stuff is spam, so we'll just not log it. + if (res.statusCode === 429) { + return; + } + + if (res.statusCode < 400 || res.statusCode === 404) { + logger.verbose( + `(${req.method} ${req.originalUrl}) Returned ${res.statusCode}.`, + contents + ); + } else if (res.statusCode < 500) { + logger.info(`(${req.method} ${req.originalUrl}) Returned ${res.statusCode}.`, contents); + } else { + logger.error( + `(${req.method} ${req.originalUrl}) Returned ${res.statusCode}.`, + contents + ); + } + }); + + next(); +}; diff --git a/src/servers/allnet/router/router.ts b/src/servers/allnet/router/router.ts new file mode 100644 index 0000000..cb0013e --- /dev/null +++ b/src/servers/allnet/router/router.ts @@ -0,0 +1,12 @@ +import sysServletRouter from "./sys/servlet/router"; +import { Router } from "express"; + +const router: Router = Router({ mergeParams: true }); + +router.all("/naomitest.html", (_, res) => { + return res.status(200).send("naomi ok").contentType("text/html"); +}); + +router.use("/sys/servlet", sysServletRouter); + +export default router; diff --git a/src/servers/allnet/router/sys/servlet/Alive/router.ts b/src/servers/allnet/router/sys/servlet/Alive/router.ts new file mode 100644 index 0000000..d2c92e9 --- /dev/null +++ b/src/servers/allnet/router/sys/servlet/Alive/router.ts @@ -0,0 +1,13 @@ +import { Router } from "express"; +import iconv from "iconv-lite"; + +const router: Router = Router({ mergeParams: true }); + +router.all("/", (_, res) => { + return res + .status(200) + .contentType("text/plain; charset=EUC-JP") + .send(iconv.encode("OK", "EUC-JP")); +}); + +export default router; diff --git a/src/servers/allnet/router/sys/servlet/DownloadOrder/router.ts b/src/servers/allnet/router/sys/servlet/DownloadOrder/router.ts new file mode 100644 index 0000000..498c93c --- /dev/null +++ b/src/servers/allnet/router/sys/servlet/DownloadOrder/router.ts @@ -0,0 +1,25 @@ +import { Router } from "express"; +import { + DownloadOrderRequestSchema, + DownloadOrderStatus, +} from "servers/allnet/types/download-order"; +import type { DownloadOrderResponse } from "servers/allnet/types/download-order"; + +const router: Router = Router({ mergeParams: true }); + +router.post("/", (req, res) => { + const parseResult = DownloadOrderRequestSchema.safeParse(req.safeBody); + + if (!parseResult.success) { + return res.status(403).send(""); + } + + // TODO: Allow network delivery. + const response = { + stat: DownloadOrderStatus.FAILURE, + } satisfies DownloadOrderResponse; + + return res.status(200).send(response); +}); + +export default router; diff --git a/src/servers/allnet/router/sys/servlet/PowerOn/router.ts b/src/servers/allnet/router/sys/servlet/PowerOn/router.ts new file mode 100644 index 0000000..448b847 --- /dev/null +++ b/src/servers/allnet/router/sys/servlet/PowerOn/router.ts @@ -0,0 +1,226 @@ +import { eq } from "drizzle-orm"; +import { Router } from "express"; +import { db } from "external/db/db"; +import { arcade, machine } from "external/db/schemas"; +import CreateLogCtx from "lib/logger/logger"; +import { Config } from "lib/setup/config"; +import { DateTime } from "luxon"; +import { + PowerOnRequestChinaSchema, + PowerOnRequestV1Schema, + PowerOnRequestV2Schema, + PowerOnRequestV3Schema, + PowerOnRequestV5Schema, + PowerOnRequestV6Schema, + PowerOnStat, +} from "servers/allnet/types/power-on"; +import { fromZodError } from "zod-validation-error"; +import type { + PowerOnResponseChina, + PowerOnResponseV1, + PowerOnResponseV2, + PowerOnResponseV3, + PowerOnResponseV5, +} from "servers/allnet/types/power-on"; + +const logger = CreateLogCtx(__filename); + +const router: Router = Router({ mergeParams: true }); + +router.post("/", async (req, res) => { + if (!req.ip) { + logger.error("Request does not have an IP associated with it?"); + return res.status(500).send(); + } + + const formatVer = req.safeBody.format_ver ?? "1"; + + let parseResult; + + // TODO: ALL.Net China + if (formatVer === "1") { + parseResult = PowerOnRequestV1Schema.safeParse(req.safeBody); + } else if (formatVer === "2") { + parseResult = PowerOnRequestV2Schema.safeParse(req.safeBody); + } else if (formatVer === "3") { + parseResult = + "game_ver" in req.safeBody + ? PowerOnRequestChinaSchema.safeParse(req.safeBody) + : PowerOnRequestV3Schema.safeParse(req.safeBody); + } else if (formatVer === "5") { + parseResult = PowerOnRequestV5Schema.safeParse(req.safeBody); + } else if (formatVer === "6") { + parseResult = PowerOnRequestV6Schema.safeParse(req.safeBody); + } else { + logger.error("Received PowerOn request of unknown version.", { formatVer }); + return res.status(400).send(""); + } + + if (!parseResult.success) { + logger.error(`Received invalid PowerOn request: ${fromZodError(parseResult.error)}`, { + formatVer, + }); + return res.status(400).send(""); + } + + const request = parseResult.data; + const gameId = "game_id" in request ? request.game_id : request.title_id; + const serial = "serial" in request ? request.serial : request.machine; + const titleVer = + // eslint-disable-next-line no-nested-ternary + "ver" in request + ? request.ver + : "game_ver" in request + ? request.game_ver + : request.title_ver; + + // We reject non-DFI requests late, so we can find the offending + // "machine". + if (req.headers.pragma?.toUpperCase() !== "DFI") { + logger.error("Received non-DFI-encoded request.", { + gameId, + serial, + ip: req.ip, + }); + return res.status(400).send(""); + } + + if (titleVer.length === 0) { + logger.error("Received PowerOn request with empty title version.", { + formatVer, + titleVer, + }); + return res.status(400).send(""); + } + + // TODO: Implement store authentication + fetch arcade information + // Reference implementation: https://sega.bsnk.me/allnet/auth/power-on + // For now, we just check if there's a cab registered in the database. + const cabAndStore = await db + .select() + .from(machine) + .leftJoin(arcade, eq(arcade.id, machine.arcade_id)) + .where(eq(machine.serial, serial)) + .then((r) => r[0]); + + if (!cabAndStore && !Config.ALLNET_CONFIG.ALLOW_UNREGISTERED_SERIALS) { + logger.error("Unregistered serial attempted ALL.Net authentication.", { + gameId, + serial, + ip: req.ip, + }); + return res.status(400).send({ stat: PowerOnStat.BOARD_ERROR }); + } + + // TODO: Verify that title exists and is enabled. + const serverTime = DateTime.now().setZone("Asia/Tokyo"); + const baseResponse = { + // Same thing + stat: 1, + + place_id: (0x123).toString(16), + // uri: `http://localhost:8080/${gameId}/${titleVer.replace(/\./u, "")}/`, + uri: `http://localhost:8080/${titleVer.replace(/\./u, "")}/`, + host: "localhost:8080", + name: cabAndStore?.allnet_arcade?.name ?? Config.NAME, + nickname: cabAndStore?.allnet_arcade?.nickname ?? "kozukata-toa", + setting: 1, + region0: cabAndStore?.allnet_arcade?.regionId ?? 1, + region_name0: cabAndStore?.allnet_arcade?.regionName0 ?? "W", + region_name1: cabAndStore?.allnet_arcade?.regionName1 ?? "", + region_name2: cabAndStore?.allnet_arcade?.regionName2 ?? "", + region_name3: cabAndStore?.allnet_arcade?.regionName3 ?? "", + }; + + let response; + + if (request.format_ver === "1") { + response = { + ...baseResponse, + year: serverTime.year, + month: serverTime.month, + day: serverTime.day, + hour: serverTime.hour, + minute: serverTime.minute, + second: serverTime.second, + } satisfies PowerOnResponseV1; + } else if (request.format_ver === "2") { + response = { + ...baseResponse, + year: serverTime.year, + month: serverTime.month, + day: serverTime.day, + hour: serverTime.hour, + minute: serverTime.minute, + second: serverTime.second, + country: "JPN", + timezone: "+09:00", + res_class: "PowerOnResponseVer2", + } satisfies PowerOnResponseV2; + } else if (request.format_ver === "3" && "ver" in request) { + response = { + ...baseResponse, + res_ver: 3, + allnet_id: 456, + utc_time: serverTime.toFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"), + country: "JPN", + client_timezone: "+0900", + token: request.token ?? "null", + } satisfies PowerOnResponseV3; + } else if (request.format_ver === "3" && "game_ver" in request) { + response = { + result: baseResponse.stat, + place_id: baseResponse.place_id, + uri1: baseResponse.uri, + uri2: baseResponse.uri, + name: baseResponse.name, + nickname: baseResponse.nickname, + setting: baseResponse.setting, + region0: baseResponse.region0, + region_name0: baseResponse.region_name0, + region_name1: baseResponse.region_name1, + region_name2: baseResponse.region_name2, + region_name3: baseResponse.region_name3, + country: "CHN", + client_timezone: "+800", + token: request.token ?? "null", + res_ver: 3, + allnet_id: 456, + utc_time: serverTime.toFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"), + } satisfies PowerOnResponseChina; + } else if (request.format_ver === "5") { + response = { + result: baseResponse.stat, + place_id: baseResponse.place_id, + title_uri: baseResponse.uri, + title_host: baseResponse.host, + name: baseResponse.name, + nickname: baseResponse.nickname, + setting: baseResponse.setting, + region0: baseResponse.region0, + region_name0: baseResponse.region_name0, + region_name1: baseResponse.region_name1, + region_name2: baseResponse.region_name2, + region_name3: baseResponse.region_name3, + res_ver: 5, + allnet_id: 456, + utc_time: serverTime.toFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"), + country: "JPN", + client_timezone: "+0900", + token: request.token ?? "null", + } satisfies PowerOnResponseV5; + } else { + logger.error("Received auth20 PowerOn request, which is currently unsupported.", { + gameId, + serial, + ip: req.ip, + }); + return res.status(403).send({ stat: 0 }); + } + + logger.info("Authenticated machine with ALL.Net.", { serial, gameId, ip: req.ip }); + + return res.status(200).send(response); +}); + +export default router; diff --git a/src/servers/allnet/router/sys/servlet/router.ts b/src/servers/allnet/router/sys/servlet/router.ts new file mode 100644 index 0000000..494a94a --- /dev/null +++ b/src/servers/allnet/router/sys/servlet/router.ts @@ -0,0 +1,12 @@ +import aliveRouter from "./Alive/router"; +import downloadOrderRouter from "./DownloadOrder/router"; +import powerOnRouter from "./PowerOn/router"; +import { Router } from "express"; + +const router: Router = Router({ mergeParams: true }); + +router.use("/Alive", aliveRouter); +router.use("/DownloadOrder", downloadOrderRouter); +router.use("/PowerOn", powerOnRouter); + +export default router; diff --git a/src/servers/allnet/types/download-order.ts b/src/servers/allnet/types/download-order.ts new file mode 100644 index 0000000..be4c097 --- /dev/null +++ b/src/servers/allnet/types/download-order.ts @@ -0,0 +1,22 @@ +import { z } from "zod"; + +export const DownloadOrderRequestSchema = z.object({ + game_id: z.string().max(5), + ver: z.string().max(5), + serial: z.string().max(11), + ip: z.string().ip().optional(), + encode: z.enum(["Shift_JIS", "EUC-JP", "UTF-8"]).default("EUC-JP"), +}); + +export type DownloadOrderRequest = z.infer; + +export const enum DownloadOrderStatus { + FAILURE = 0, + SUCCESS = 1, +} + +export interface DownloadOrderResponse { + stat: DownloadOrderStatus; + serial?: string; + uri?: string; +} diff --git a/src/servers/allnet/types/power-on.ts b/src/servers/allnet/types/power-on.ts new file mode 100644 index 0000000..fc24f6b --- /dev/null +++ b/src/servers/allnet/types/power-on.ts @@ -0,0 +1,278 @@ +import { z } from "zod"; +import type { integer } from "types/misc"; + +export const PowerOnRequestV1Schema = z.object({ + game_id: z.string().max(5), + ver: z.string().max(5), + serial: z.string().max(11), + ip: z.string().ip(), + firm_ver: z.coerce.number().optional(), + boot_ver: z.coerce.number().optional(), + encode: z.enum(["Shift_JIS", "EUC-JP", "UTF-8"]).default("EUC-JP"), + format_ver: z.literal("1"), + hops: z.coerce.number().default(-1), +}); + +export type PowerOnRequestV1 = z.infer; + +export const PowerOnRequestV2Schema = PowerOnRequestV1Schema.extend({ + format_ver: z.literal("2"), +}); + +export type PowerOnRequestV2 = z.infer; + +export const PowerOnRequestV3Schema = PowerOnRequestV2Schema.extend({ + format_ver: z.literal("3"), + token: z.string().optional(), +}); + +export type PowerOnRequestV3 = z.infer; + +export const PowerOnRequestV5Schema = z.object({ + title_id: z.string().max(5), + title_ver: z.string().max(5), + machine: z.string().max(11), + firm_ver: z.coerce.number().optional(), + boot_ver: z.coerce.number().optional(), + encode: z.enum(["Shift_JIS", "EUC-JP", "UTF-8"]).default("EUC-JP"), + format_ver: z.literal("5"), + hops: z.coerce.number().default(-1), + token: z.string().optional(), +}); + +export type PowerOnRequestV5 = z.infer; + +export const PowerOnRequestChinaSchema = z.object({ + game_id: z.string().max(5), + game_ver: z.string().max(5), + machine: z.string().max(11), + server: z.string(), + firm_ver: z.coerce.number().optional(), + boot_ver: z.coerce.number().optional(), + encode: z.enum(["Shift_JIS", "EUC-JP", "UTF-8"]).default("EUC-JP"), + format_ver: z.literal("3"), + hops: z.coerce.number().default(-1), + token: z.string().optional(), +}); + +export type PowerOnRequestChina = z.infer; + +export const PowerOnRequestV6Schema = PowerOnRequestV3Schema.extend({ + format_ver: z.literal("6"), + auth_data: z.string().max(1535), +}); + +export type PowerOnRequestV6 = z.infer; + +export const enum PowerOnStat { + SUCCESS = 1, + GAME_ERROR = -1, + BOARD_ERROR = -2, + LOCATION_ERROR = -3, +} + +export interface PowerOnResponseV1 { + /** + * ALL.Net authentication status + */ + stat: PowerOnStat; + + /** + * The arcade's place ID, encoded as an uppercase hexadecimal string. + */ + place_id: string; + + /** + * Title server URI. Will be present, but empty, if authentication + * is not successful. + */ + uri: string; + + /** + * Title server hostname. Will be present, but empty, if authentication + * is not successful. + * + * @note The hostname (if present) in URI is only used for name resolution. + * This value is passed to the title server in the `Host` header, and can be + * utilized as an extra authentication step. + */ + host: string; + + /** + * ALL.Net location name + * + * @note URL-encoded UTF-8. + */ + name: string; + + /** + * ALL.Net location nickname + * + * @note URL-encoded UTF-8. + */ + nickname: string; + + /** + * Server time's year + */ + year: integer; + + /** + * Server time's month + */ + month: integer; + + /** + * Server time's day + */ + day: integer; + + /** + * Server time's hour + */ + hour: integer; + + /** + * Server time's minute + */ + minute: integer; + + /** + * Server time's second + */ + second: integer; + + /** + * Game-specific setting. + * + * @note In practice this appears to be used as a "network allowed" flag. + * If ever unsure, specify this field as `1`. + */ + setting: integer; + + /** + * Region code + */ + region0: integer; + + /** + * Region 1 + * + * @note URL-encoded UTF-8. + */ + region_name0: string; + + /** + * Region 2 + * + * @note URL-encoded UTF-8. + */ + region_name1: string; + + /** + * Region 3 + * + * @note URL-encoded UTF-8. + */ + region_name2: string; + + /** + * Region 4 + * + * @note URL-encoded UTF-8. + */ + region_name3: string; +} + +export interface PowerOnResponseV2 extends PowerOnResponseV1 { + /** + * Country code + */ + country: string; + + timezone: "+09:00"; + + res_class: "PowerOnResponseVer2"; +} + +export interface PowerOnResponseV3 + extends Omit< + PowerOnResponseV2, + "day" | "hour" | "minute" | "month" | "res_class" | "second" | "timezone" | "year" + > { + res_ver: 3; + + /** + * ALL.Net ID + */ + allnet_id: integer; + + /** + * Authentication time. Format must be `yyyy-MM-dd'T'HH:mm:ss'Z'`. + */ + utc_time: string; + + /** + * @example `+0900` + */ + client_timezone: string; + + /** + * Echoes the request token. The literal `null` will be used if token is not + * present in request. + */ + token: string; +} + +export interface PowerOnResponseV5 + extends Omit { + res_ver: 5; + + /** + * ALL.Net authentication status + */ + result: PowerOnStat; + + /** + * Title server URI. Will be present, but empty, if authentication + * is not successful. + */ + title_uri: string; + + /** + * Title server hostname. Will be present, but empty, if authentication + * is not successful. + * + * @note The hostname (if present) in URI is only used for name resolution. + * This value is passed to the title server in the `Host` header, and can be + * utilized as an extra authentication step. + */ + title_host: string; +} + +export interface PowerOnResponseChina + extends Omit { + /** + * ALL.Net authentication status + */ + result: PowerOnStat; + + /** + * Title server URI 1 + */ + uri1: string; + + /** + * Title server URI 2 + */ + uri2: string; + + country: "CHN"; + + client_timezone: "+800"; +} + +export interface PowerOnResponseV6 { + auth_data: string; + packet_data: string; +} diff --git a/src/servers/index.ts b/src/servers/index.ts new file mode 100644 index 0000000..fb3a1b8 --- /dev/null +++ b/src/servers/index.ts @@ -0,0 +1,2 @@ +export { default as allnetServer } from "./allnet"; +export { default as aimeDbServerFactory } from "./aimedb"; diff --git a/src/types/misc.ts b/src/types/misc.ts new file mode 100644 index 0000000..0053b28 --- /dev/null +++ b/src/types/misc.ts @@ -0,0 +1 @@ +export type integer = number; diff --git a/src/utils/misc.ts b/src/utils/misc.ts new file mode 100644 index 0000000..22e474b --- /dev/null +++ b/src/utils/misc.ts @@ -0,0 +1,13 @@ +export function EscapeStringRegexp(string: string) { + if (typeof string !== "string") { + throw new TypeError("Expected a string"); + } + + // Escape characters with special meaning either inside or outside character sets. + // Use a simple backslash escape when it's always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns' stricter grammar. + return string.replace(/[|\\{}()[\]^$+*?.]/gu, "\\$&").replace(/-/gu, "\\x2d"); +} + +export function IsRecord(maybeRecord: unknown): maybeRecord is Record { + return typeof maybeRecord === "object" && maybeRecord !== null; +} diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 0000000..0a76dbf --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,15 @@ +// This TSConfig file is used when pnpm build is ran. It omits out +// unecessary files, such as anything involved in testing. +// This is a separate TSConfig file because VSCode (by default) uses +// the exclude list to find out what it should care about for typechecking +// while writing code. +// Since I still want my tests to take advantage of static typing, this is +// a necessary hack. +{ + "extends": "./tsconfig.json", + "exclude": [ + "node_modules", + "src/test-utils", + "src/**/*.test.ts" + ] +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a0ca8e4 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,110 @@ +{ + "include": ["src"], + "compilerOptions": { + /* 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": "es2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + "lib": ["ES2019"], /* 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 legacy experimental 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": "commonjs", /* Specify what module code is generated. */ + "rootDir": "./src", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + "baseUrl": "./src", /* 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": ["@types", "node_modules/@types"], /* 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. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + "allowJs": false, /* 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. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "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": "./js", /* 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. */ + // "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. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "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. */ + } +}