diff --git a/.gitignore b/.gitignore index 942f67c..cf7c2b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,183 +1,61 @@ -# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore +# compiled output +/dist +/node_modules +/build # Logs - logs -_.log -npm-debug.log_ +*.log +npm-debug.log* +pnpm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* -.pnpm-debug.log* - -# Caches - -.cache - -# 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 +# OS +.DS_Store -.yarn-integrity +# Tests +/coverage +/.nyc_output + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# Config files with actual data (defaults are tracked) +configs/*.config.json # dotenv environment variable files - .env .env.development.local .env.test.local .env.production.local .env.local -# parcel-bundler cache (https://parceljs.org/) - -.parcel-cache - -# Next.js build output - -.next -out - -# Nuxt.js build / generate output - -.output -.data -.nuxt -.nitro -.cache -dist - -# Gatsby files - -# 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 directory .temp +.tmp -# 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.* - -# IntelliJ based IDEs -. -.fleet +# Runtime data +pids +*.pid +*.seed +*.pid.lock -# Finder (MacOS) folder config -.DS_Store +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json -# opensrc - source code for packages -opensrc/ +legacy/ diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index 5548ea1..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,26 +0,0 @@ -# AGENTS.md - -Instructions for AI coding agents working with this codebase. - - - -## Source Code Reference - -Source code for dependencies is available in `opensrc/` for deeper understanding of implementation details. - -See `opensrc/sources.json` for the list of available packages and their versions. - -Use this source code when you need to understand how a package works internally, not just its types/interface. - -### Fetching Additional Source Code - -To fetch source code for a package or repository you need to understand, run: - -```bash -npx opensrc # npm package (e.g., npx opensrc zod) -npx opensrc pypi: # Python package (e.g., npx opensrc pypi:requests) -npx opensrc crates: # Rust crate (e.g., npx opensrc crates:serde) -npx opensrc / # GitHub repo (e.g., npx opensrc vercel/ai) -``` - - diff --git a/README.md b/README.md index fd2649c..c872aaf 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,6 @@ node --run copy:config ```sh # Using docker cli docker compose up db -d - -# Using provided npm script -node --run db:start:dev ``` 5. Generate and apply migration: @@ -52,9 +49,6 @@ node --run db:apply-migration ```sh node --run start:dev - -# For running in watch mode -node --run start:dev:watch ``` ### Working with migrations diff --git a/configs/cache.default.json b/configs/cache.default.json new file mode 100644 index 0000000..26f4a83 --- /dev/null +++ b/configs/cache.default.json @@ -0,0 +1,6 @@ +{ + "host": "127.0.0.1", + "user": "default", + "password": "default", + "port": 6379 +} diff --git a/configs/db.default.json b/configs/db.default.json new file mode 100644 index 0000000..7c19a7e --- /dev/null +++ b/configs/db.default.json @@ -0,0 +1,7 @@ +{ + "host": "127.0.0.1", + "database": "postgres", + "user": "postgres", + "password": "postgres", + "port": 5432 +} diff --git a/configs/integrations.default.json b/configs/integrations.default.json new file mode 100644 index 0000000..93c16d2 --- /dev/null +++ b/configs/integrations.default.json @@ -0,0 +1,10 @@ +{ + "moodle": { + "enabled": false, + "baseUrl": "https://example.com" + }, + "proxy": { + "enabled": false, + "baseUrl": "http://127.0.0.1:5035" + } +} diff --git a/configs/server.default.json b/configs/server.default.json new file mode 100644 index 0000000..fcb43fb --- /dev/null +++ b/configs/server.default.json @@ -0,0 +1,3 @@ +{ + "port": 8080 +} diff --git a/configs/webhooks.default.json b/configs/webhooks.default.json new file mode 100644 index 0000000..f516835 --- /dev/null +++ b/configs/webhooks.default.json @@ -0,0 +1,4 @@ +{ + "enabled": false, + "webhookUrl": "https://example.com/webhook" +} diff --git a/eslint.config.js b/eslint.config.mjs similarity index 62% rename from eslint.config.js rename to eslint.config.mjs index 831e2be..8a9306f 100644 --- a/eslint.config.js +++ b/eslint.config.mjs @@ -6,13 +6,27 @@ import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended' /** @type {import('eslint').Linter.Config[]} */ export default [ { files: ['**/*.{js,mjs,cjs,ts}'] }, - { languageOptions: { globals: globals.node } }, + { + languageOptions: { + globals: { + ...globals.node, + ...globals.vitest, + }, + sourceType: 'commonjs', + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, + }, + }, { ignores: ['coverage', 'public', 'dist', 'pnpm-lock.yaml'], }, { rules: { '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-floating-promises': 'warn', + '@typescript-eslint/no-unsafe-argument': 'warn', }, }, pluginJs.configs.recommended, diff --git a/nest-cli.json b/nest-cli.json new file mode 100644 index 0000000..12c1ab8 --- /dev/null +++ b/nest-cli.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true, + "builder": "swc", + "typeCheck": true + } +} diff --git a/package.json b/package.json index 1a3d57e..4c17809 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,20 @@ { "name": "mindenit-schedule-api", "version": "0.0.1", - "type": "module", "description": "API for Mindenit Schedule", "scripts": { - "build": "tsc && resolve-tspaths", - "start": "node --run db:apply-migration && node --run start:prod", - "start:prod": "NODE_ENV=production node dist/index.js", - "start:dev": "node ./scripts/depsCheck.js && NODE_ENV=development tsx src/index.ts", - "start:dev:watch": "NODE_ENV=development tsx --watch src/index.ts", - "docker:start:dev": "docker compose up", - "docker:stop:dev": "docker compose down", - "infrastructure:start:dev": "docker compose -f ./docker-compose.dev.yml up db cache cist-proxy", + "build": "nest build", + "start": "nest start", + "start:dev": "nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "node dist/main", + "test": "vitest run", + "test:watch": "vitest", + "test:cov": "vitest run --coverage", + "test:debug": "vitest --inspect-brk --inspect --logHeapUsage --threads=false", + "test:e2e": "vitest run --config ./vitest.config.e2e.ts", + "infrastructure:start:dev": "docker compose -f ./docker-compose.dev.yml up -d db cache cist-proxy", "infrastructure:stop:dev": "docker compose down", - "db:start:dev": "docker compose -f docker-compose.dev.yml up db", - "db:stop:dev": "docker compose down", "db:generate-schema": "tsc -p tsconfig.drizzle.json", "db:generate-migration": "NODE_ENV=development node --run db:generate-schema && npx drizzle-kit generate --config=./drizzle.config.ts", "db:apply-migration": "NODE_ENV=development npx drizzle-kit migrate --config=./drizzle.config.ts", @@ -44,7 +44,16 @@ "@commitlint/cli": "^19.7.1", "@commitlint/config-conventional": "^19.7.1", "@eslint/js": "^9.21.0", + "@nestjs/cli": "^11.0.21", + "@nestjs/schematics": "^11.1.0", + "@nestjs/testing": "^11.1.19", + "@swc/cli": "^0.8.1", + "@swc/core": "^1.15.30", + "@total-typescript/ts-reset": "^0.6.1", + "@types/jest": "^30.0.0", "@types/qs": "^6.14.0", + "@types/supertest": "^7.2.0", + "@vitest/coverage-v8": "^4.1.5", "cpy-cli": "^5.0.0", "drizzle-kit": "1.0.0-beta.1-c0277c0", "eslint": "^9.21.0", @@ -52,13 +61,21 @@ "eslint-plugin-prettier": "^5.2.3", "globals": "^16.0.0", "husky": "^9.1.7", + "jest": "^30.3.0", "lint-staged": "^15.4.3", "pino-pretty": "^13.0.0", "prettier": "^3.5.2", "resolve-tspaths": "^0.8.23", + "source-map-support": "^0.5.21", + "supertest": "^7.2.2", + "ts-jest": "^29.4.9", + "ts-loader": "^9.5.7", + "ts-node": "^10.9.2", "tsx": "^4.19.3", "typescript": "5.8.3", - "typescript-eslint": "^8.25.0" + "typescript-eslint": "^8.25.0", + "unplugin-swc": "^1.5.9", + "vitest": "^4.1.5" }, "packageManager": "pnpm@9.12.3", "dependencies": { @@ -68,8 +85,16 @@ "@fastify/helmet": "^13.0.1", "@fastify/rate-limit": "^10.2.2", "@fastify/schedule": "^6.0.0", + "@fastify/static": "^9.1.3", "@fastify/swagger": "^9.4.2", + "@mindenit/cist-crawler": "^0.1.4", + "@nestjs/common": "^11.1.19", + "@nestjs/core": "^11.1.19", + "@nestjs/platform-fastify": "^11.1.19", + "@nestjs/schedule": "^6.1.3", + "@nestjs/swagger": "^11.4.1", "@scalar/fastify-api-reference": "^1.31.3", + "@scalar/nestjs-api-reference": "^1.1.10", "@types/node": "^22.13.8", "awilix": "^12.0.4", "better-result": "^2.7.0", @@ -78,11 +103,35 @@ "fastify": "^5.2.1", "fastify-type-provider-zod": "^5.0.2", "ioredis": "^5.6.1", + "nestjs-pino": "^4.6.1", + "nestjs-zod": "^5.3.0", "node-html-markdown": "^2.0.0", "node-object-hash": "^3.1.1", + "pino-http": "^11.0.0", "postgres": "^3.4.5", "qs": "^6.14.0", + "reflect-metadata": "^0.2.2", + "rimraf": "^6.1.3", + "rxjs": "^7.8.2", + "temporal-polyfill": "^0.3.2", "toad-scheduler": "^3.1.0", "zod": "^4.0.10" + }, + "jest": { + "moduleFileExtensions": [ + "js", + "json", + "ts" + ], + "rootDir": "src", + "testRegex": ".*\\.spec\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "collectCoverageFrom": [ + "**/*.(t|j)s" + ], + "coverageDirectory": "../coverage", + "testEnvironment": "node" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a31a029..e2328aa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,12 +26,36 @@ importers: '@fastify/schedule': specifier: ^6.0.0 version: 6.0.0(toad-scheduler@3.1.0) + '@fastify/static': + specifier: ^9.1.3 + version: 9.1.3 '@fastify/swagger': specifier: ^9.4.2 version: 9.5.1 + '@mindenit/cist-crawler': + specifier: ^0.1.4 + version: 0.1.4 + '@nestjs/common': + specifier: ^11.1.19 + version: 11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': + specifier: ^11.1.19 + version: 11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/platform-fastify': + specifier: ^11.1.19 + version: 11.1.19(@fastify/static@9.1.3)(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2)) + '@nestjs/schedule': + specifier: ^6.1.3 + version: 6.1.3(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2)) + '@nestjs/swagger': + specifier: ^11.4.1 + version: 11.4.1(@fastify/static@9.1.3)(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2) '@scalar/fastify-api-reference': specifier: ^1.31.3 version: 1.31.3 + '@scalar/nestjs-api-reference': + specifier: ^1.1.10 + version: 1.1.10 '@types/node': specifier: ^22.13.8 version: 22.15.29 @@ -56,18 +80,39 @@ importers: ioredis: specifier: ^5.6.1 version: 5.6.1 + nestjs-pino: + specifier: ^4.6.1 + version: 4.6.1(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(pino-http@11.0.0)(pino@10.3.1)(rxjs@7.8.2) + nestjs-zod: + specifier: ^5.3.0 + version: 5.3.0(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/swagger@11.4.1(@fastify/static@9.1.3)(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2))(rxjs@7.8.2)(zod@4.0.10) node-html-markdown: specifier: ^2.0.0 version: 2.0.0 node-object-hash: specifier: ^3.1.1 version: 3.1.1 + pino-http: + specifier: ^11.0.0 + version: 11.0.0 postgres: specifier: ^3.4.5 version: 3.4.7 qs: specifier: ^6.14.0 version: 6.14.0 + reflect-metadata: + specifier: ^0.2.2 + version: 0.2.2 + rimraf: + specifier: ^6.1.3 + version: 6.1.3 + rxjs: + specifier: ^7.8.2 + version: 7.8.2 + temporal-polyfill: + specifier: ^0.3.2 + version: 0.3.2 toad-scheduler: specifier: ^3.1.0 version: 3.1.0 @@ -84,9 +129,36 @@ importers: '@eslint/js': specifier: ^9.21.0 version: 9.28.0 + '@nestjs/cli': + specifier: ^11.0.21 + version: 11.0.21(@swc/cli@0.8.1(@swc/core@1.15.30)(chokidar@4.0.3))(@swc/core@1.15.30)(@types/node@22.15.29)(esbuild@0.25.5)(prettier@3.5.3) + '@nestjs/schematics': + specifier: ^11.1.0 + version: 11.1.0(chokidar@4.0.3)(prettier@3.5.3)(typescript@5.8.3) + '@nestjs/testing': + specifier: ^11.1.19 + version: 11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2)) + '@swc/cli': + specifier: ^0.8.1 + version: 0.8.1(@swc/core@1.15.30)(chokidar@4.0.3) + '@swc/core': + specifier: ^1.15.30 + version: 1.15.30 + '@total-typescript/ts-reset': + specifier: ^0.6.1 + version: 0.6.1 + '@types/jest': + specifier: ^30.0.0 + version: 30.0.0 '@types/qs': specifier: ^6.14.0 version: 6.14.0 + '@types/supertest': + specifier: ^7.2.0 + version: 7.2.0 + '@vitest/coverage-v8': + specifier: ^4.1.5 + version: 4.1.5(vitest@4.1.5) cpy-cli: specifier: ^5.0.0 version: 5.0.0 @@ -101,13 +173,16 @@ importers: version: 10.1.5(eslint@9.28.0(jiti@2.4.2)) eslint-plugin-prettier: specifier: ^5.2.3 - version: 5.4.1(eslint-config-prettier@10.1.5(eslint@9.28.0(jiti@2.4.2)))(eslint@9.28.0(jiti@2.4.2))(prettier@3.5.3) + version: 5.4.1(@types/eslint@9.6.1)(eslint-config-prettier@10.1.5(eslint@9.28.0(jiti@2.4.2)))(eslint@9.28.0(jiti@2.4.2))(prettier@3.5.3) globals: specifier: ^16.0.0 version: 16.2.0 husky: specifier: ^9.1.7 version: 9.1.7 + jest: + specifier: ^30.3.0 + version: 30.3.0(@types/node@22.15.29)(esbuild-register@3.6.0(esbuild@0.25.5))(ts-node@10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3)) lint-staged: specifier: ^15.4.3 version: 15.5.2 @@ -120,6 +195,21 @@ importers: resolve-tspaths: specifier: ^0.8.23 version: 0.8.23(typescript@5.8.3) + source-map-support: + specifier: ^0.5.21 + version: 0.5.21 + supertest: + specifier: ^7.2.2 + version: 7.2.2 + ts-jest: + specifier: ^29.4.9 + version: 29.4.9(@babel/core@7.29.0)(@jest/transform@30.3.0)(@jest/types@30.3.0)(babel-jest@30.3.0(@babel/core@7.29.0))(esbuild@0.25.5)(jest-util@30.3.0)(jest@30.3.0(@types/node@22.15.29)(esbuild-register@3.6.0(esbuild@0.25.5))(ts-node@10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3)))(typescript@5.8.3) + ts-loader: + specifier: ^9.5.7 + version: 9.5.7(typescript@5.8.3)(webpack@5.106.0(@swc/core@1.15.30)(esbuild@0.25.5)) + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3) tsx: specifier: ^4.19.3 version: 4.19.4 @@ -129,23 +219,223 @@ importers: typescript-eslint: specifier: ^8.25.0 version: 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) + unplugin-swc: + specifier: ^1.5.9 + version: 1.5.9(@swc/core@1.15.30) + vitest: + specifier: ^4.1.5 + version: 4.1.5(@types/node@22.15.29)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@22.15.29)(esbuild@0.25.5)(jiti@2.4.2)(terser@5.46.2)(tsx@4.19.4)(yaml@2.8.0)) packages: + '@angular-devkit/core@19.2.24': + resolution: {integrity: sha512-Kd49warf6U/EyWe5BszF/eebN3zQ3bk7tgfEljAw8q/rX95UUtriJubWvp6pgzHfzBA4jwq8f+QiNZB8eBEXPA==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + chokidar: ^4.0.0 + peerDependenciesMeta: + chokidar: + optional: true + + '@angular-devkit/schematics-cli@19.2.24': + resolution: {integrity: sha512-bsStZQG67J1HBqTmWxtIcobvgrn32L4UOdL7hGyOru5VxDWPNA8pRnDYavT3hnJeBkJYPoQIw8u7Dm0ecoQprw==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + hasBin: true + + '@angular-devkit/schematics@19.2.24': + resolution: {integrity: sha512-lnw+ZM1Io+cJAkReC0NPDjqObL8NtKzKIkdgEEKC8CUmkhurYhedbicN8Y8NYHgG1uLd2GozW3+/QqPRZaN+Lw==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.0': + resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.28.6': + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.28.6': + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.27.1': resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.2': + resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.28.6': + resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.28.6': + resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.28.6': + resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} + + '@borewit/text-codec@0.2.2': + resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==} + '@clack/core@0.5.0': resolution: {integrity: sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow==} '@clack/prompts@0.11.0': resolution: {integrity: sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw==} + '@colors/colors@1.5.0': + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + '@commitlint/cli@19.8.1': resolution: {integrity: sha512-LXUdNIkspyxrlV6VDHWBmCZRtkEVRpBKxi2Gtw3J54cGWhLCTouVD/Q6ZSaSvd2YaDObWK8mDjrz3TIKtaQMAA==} engines: {node: '>=v18'} @@ -215,9 +505,22 @@ packages: resolution: {integrity: sha512-/yCrWGCoA1SVKOks25EGadP9Pnj0oAIHGpl2wH2M2Y46dPM2ueb8wyCVOD7O3WCTkaJ0IkKvzhl1JY7+uCT2Dw==} engines: {node: '>=v18'} + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + '@drizzle-team/brocli@0.10.2': resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==} + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + '@esbuild-kit/core-utils@3.3.2': resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} deprecated: 'Merged into tsx: https://tsx.is' @@ -546,9 +849,15 @@ packages: resolution: {integrity: sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@fastify/accept-negotiator@2.0.1': + resolution: {integrity: sha512-/c/TW2bO/v9JeEgoD/g1G5GxGeCF1Hafdf79WPmUlgYiBXummY0oX3VVq4yFkKKVBKDNlaDUYoab7g38RpPqCQ==} + '@fastify/ajv-compiler@4.0.2': resolution: {integrity: sha512-Rkiu/8wIjpsf46Rr+Fitd3HRP+VsxUFDDeag0hs9L0ksfnwx2g7SPQQTFL0E8Qv+rfXzQOxBJnjUB9ITUDjfWQ==} + '@fastify/ajv-compiler@4.0.5': + resolution: {integrity: sha512-KoWKW+MhvfTRWL4qrhUwAAZoaChluo0m0vbiJlGMt2GXvL4LVPQEjt8kSpHI3IBq5Rez8fg+XeH3cneztq+C7A==} + '@fastify/awilix@7.0.0': resolution: {integrity: sha512-wttTQKfZkrVn/8ReJMHo4RZ7GxIbx+ErwCZv4QpXa9+OxeVWUg4Wb2r+LcQigfmc2LBTDQ183iJ5aYnr5J0mEg==} peerDependencies: @@ -561,12 +870,18 @@ packages: '@fastify/cors@11.0.1': resolution: {integrity: sha512-dmZaE7M1f4SM8ZZuk5RhSsDJ+ezTgI7v3HHRj8Ow9CneczsPLZV6+2j2uwdaSLn8zhTv6QV0F4ZRcqdalGx1pQ==} + '@fastify/cors@11.2.0': + resolution: {integrity: sha512-LbLHBuSAdGdSFZYTLVA3+Ch2t+sA6nq3Ejc6XLAKiQ6ViS2qFnvicpj0htsx03FyYeLs04HfRNBsz/a8SvbcUw==} + '@fastify/error@4.2.0': resolution: {integrity: sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==} '@fastify/fast-json-stringify-compiler@5.0.3': resolution: {integrity: sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ==} + '@fastify/formbody@8.0.2': + resolution: {integrity: sha512-84v5J2KrkXzjgBpYnaNRPqwgMsmY7ZDjuj0YVuMR3NXCJRCgKEZy/taSP1wUYGn0onfxJpLyRGDLa+NMaDJtnA==} + '@fastify/forwarded@3.0.0': resolution: {integrity: sha512-kJExsp4JCms7ipzg7SJ3y8DwmePaELHxKYtg+tZow+k0znUTf3cb+npgyqm8+ATZOdmfgfydIebPDWM172wfyA==} @@ -587,6 +902,12 @@ packages: peerDependencies: toad-scheduler: '>=2.0.0' + '@fastify/send@4.1.0': + resolution: {integrity: sha512-TMYeQLCBSy2TOFmV95hQWkiTYgC/SEx7vMdV+wnZVX4tt8VBLKzmH8vV9OzJehV0+XBfg+WxPMt5wp+JBUKsVw==} + + '@fastify/static@9.1.3': + resolution: {integrity: sha512-aXrYtsiryLhRxRNaxNqsn7FUISeb7rB9q4eHUPIot5aeQBLNahnz1m6thzm7JWC1poSGXS9XrX8DvuMivp2hkQ==} + '@fastify/swagger@9.5.1': resolution: {integrity: sha512-EGjYLA7vDmCPK7XViAYMF6y4+K3XUy5soVTVxsyXolNe/Svb4nFQxvtuQvvoQb2Gzc9pxiF3+ZQN/iZDHhKtTg==} @@ -610,2127 +931,6445 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@ioredis/commands@1.2.0': - resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==} - - '@lukeed/ms@2.0.2': - resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} - engines: {node: '>=8'} - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} + '@inquirer/ansi@1.0.2': + resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} + engines: {node: '>=18'} - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} + '@inquirer/checkbox@4.3.2': + resolution: {integrity: sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} + '@inquirer/confirm@5.1.21': + resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@pkgr/core@0.2.7': - resolution: {integrity: sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@inquirer/core@10.3.2': + resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@scalar/core@0.3.1': - resolution: {integrity: sha512-k5TsihZcSdVnqE6JrRFdsvePDTe2RxjE+1wHdcnyFdIPief+ZdPn2fxCTlN0ozLoe08xlY3N9DHzDaneMpX58Q==} - engines: {node: '>=20'} + '@inquirer/editor@4.2.23': + resolution: {integrity: sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@scalar/fastify-api-reference@1.31.3': - resolution: {integrity: sha512-r+VotFGBZvD8Cpj99AlZLAF4qVVYBsvHx6XRUzoLEViba16WJICPBpQ+xWmC9fVAUzQR58TvwUjI7X1h37Sp/A==} - engines: {node: '>=20'} + '@inquirer/expand@4.0.23': + resolution: {integrity: sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@scalar/openapi-parser@0.14.0': - resolution: {integrity: sha512-54KxfMUioaNYYQLZuTPUVcBqBSS7vFrd+bA4p95uYvvnWP/7lL+t1dQqQk+jRv7uut6IbnjiDeFFIkVABteJSA==} - engines: {node: '>=20'} + '@inquirer/external-editor@1.0.3': + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@scalar/openapi-types@0.3.1': - resolution: {integrity: sha512-635pb0OIxhhr2yVPwqExOyNh8eo01JLOqXkDvvflHFBaGo7CHvq5sduwriXdplkn2TRNkxdkdy/eNSOMNPVa1A==} - engines: {node: '>=20'} + '@inquirer/figures@1.0.15': + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} + engines: {node: '>=18'} - '@scalar/types@0.2.1': - resolution: {integrity: sha512-eXcxuwazLABrnCjpqE4tG+FgiCKyHhKxB4V8Bn4Uj/XCBTemRd+WSzXp0mmpGuBbqz820j5UGrlZ5cWlUWaWWw==} - engines: {node: '>=20'} + '@inquirer/input@4.3.1': + resolution: {integrity: sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@types/conventional-commits-parser@5.0.1': - resolution: {integrity: sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==} + '@inquirer/number@3.0.23': + resolution: {integrity: sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@types/estree@1.0.7': - resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + '@inquirer/password@4.0.23': + resolution: {integrity: sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@inquirer/prompts@7.10.1': + resolution: {integrity: sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@types/node@22.15.29': - resolution: {integrity: sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==} + '@inquirer/prompts@7.3.2': + resolution: {integrity: sha512-G1ytyOoHh5BphmEBxSwALin3n1KGNYB6yImbICcRQdzXfOGbuJ9Jske/Of5Sebk339NSGGNfUshnzK8YWkTPsQ==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@types/qs@6.14.0': - resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} + '@inquirer/rawlist@4.1.11': + resolution: {integrity: sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@typescript-eslint/eslint-plugin@8.33.1': - resolution: {integrity: sha512-TDCXj+YxLgtvxvFlAvpoRv9MAncDLBV2oT9Bd7YBGC/b/sEURoOYuIwLI99rjWOfY3QtDzO+mk0n4AmdFExW8A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@inquirer/search@3.2.2': + resolution: {integrity: sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==} + engines: {node: '>=18'} peerDependencies: - '@typescript-eslint/parser': ^8.33.1 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@typescript-eslint/parser@8.33.1': - resolution: {integrity: sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@inquirer/select@4.4.2': + resolution: {integrity: sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==} + engines: {node: '>=18'} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@typescript-eslint/project-service@8.33.1': - resolution: {integrity: sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@inquirer/type@3.0.10': + resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==} + engines: {node: '>=18'} peerDependencies: - typescript: '>=4.8.4 <5.9.0' + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true - '@typescript-eslint/scope-manager@8.33.1': - resolution: {integrity: sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ioredis/commands@1.2.0': + resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==} - '@typescript-eslint/tsconfig-utils@8.33.1': - resolution: {integrity: sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <5.9.0' + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} - '@typescript-eslint/type-utils@8.33.1': - resolution: {integrity: sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} - '@typescript-eslint/types@8.33.1': - resolution: {integrity: sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@istanbuljs/schema@0.1.6': + resolution: {integrity: sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==} + engines: {node: '>=8'} - '@typescript-eslint/typescript-estree@8.33.1': - resolution: {integrity: sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <5.9.0' + '@jest/console@30.3.0': + resolution: {integrity: sha512-PAwCvFJ4696XP2qZj+LAn1BWjZaJ6RjG6c7/lkMaUJnkyMS34ucuIsfqYvfskVNvUI27R/u4P1HMYFnlVXG/Ww==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@typescript-eslint/utils@8.33.1': - resolution: {integrity: sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@jest/core@30.3.0': + resolution: {integrity: sha512-U5mVPsBxLSO6xYbf+tgkymLx+iAhvZX43/xI1+ej2ZOPnPdkdO1CzDmFKh2mZBn2s4XZixszHeQnzp1gm/DIxw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true - '@typescript-eslint/visitor-keys@8.33.1': - resolution: {integrity: sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@jest/diff-sequences@30.3.0': + resolution: {integrity: sha512-cG51MVnLq1ecVUaQ3fr6YuuAOitHK1S4WUJHnsPFE/quQr33ADUx1FfrTCpMCRxvy0Yr9BThKpDjSlcTi91tMA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - JSONStream@1.3.5: - resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} - hasBin: true + '@jest/environment@30.3.0': + resolution: {integrity: sha512-SlLSF4Be735yQXyh2+mctBOzNDx5s5uLv88/j8Qn1wH679PDcwy67+YdADn8NJnGjzlXtN62asGH/T4vWOkfaw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - abstract-logging@2.0.1: - resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} + '@jest/expect-utils@30.3.0': + resolution: {integrity: sha512-j0+W5iQQ8hBh7tHZkTQv3q2Fh/M7Je72cIsYqC4OaktgtO7v1So9UTjp6uPBHIaB6beoF/RRsCgMJKvti0wADA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + '@jest/expect@30.3.0': + resolution: {integrity: sha512-76Nlh4xJxk2D/9URCn3wFi98d2hb19uWE1idLsTt2ywhvdOldbw3S570hBgn25P4ICUZ/cBjybrBex2g17IDbg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - acorn@8.14.1: - resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} - engines: {node: '>=0.4.0'} - hasBin: true + '@jest/fake-timers@30.3.0': + resolution: {integrity: sha512-WUQDs8SOP9URStX1DzhD425CqbN/HxUYCTwVrT8sTVBfMvFqYt/s61EK5T05qnHu0po6RitXIvP9otZxYDzTGQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - aggregate-error@4.0.1: - resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==} - engines: {node: '>=12'} + '@jest/get-type@30.1.0': + resolution: {integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - ajv-draft-04@1.0.0: - resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} - peerDependencies: - ajv: ^8.5.0 - peerDependenciesMeta: - ajv: - optional: true + '@jest/globals@30.3.0': + resolution: {integrity: sha512-+owLCBBdfpgL3HU+BD5etr1SvbXpSitJK0is1kiYjJxAAJggYMRQz5hSdd5pq1sSggfxPbw2ld71pt4x5wwViA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - ajv-formats@3.0.1: - resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + '@jest/pattern@30.0.1': + resolution: {integrity: sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/reporters@30.3.0': + resolution: {integrity: sha512-a09z89S+PkQnL055bVj8+pe2Caed2PBOaczHcXCykW5ngxX9EWx/1uAwncxc/HiU0oZqfwseMjyhxgRjS49qPw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: - ajv: ^8.0.0 + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: - ajv: + node-notifier: optional: true - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + '@jest/schemas@30.0.5': + resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + '@jest/snapshot-utils@30.3.0': + resolution: {integrity: sha512-ORbRN9sf5PP82v3FXNSwmO1OTDR2vzR2YTaR+E3VkSBZ8zadQE6IqYdYEeFH1NIkeB2HIGdF02dapb6K0Mj05g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} + '@jest/source-map@30.0.1': + resolution: {integrity: sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - ansi-escapes@7.0.0: - resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} - engines: {node: '>=18'} + '@jest/test-result@30.3.0': + resolution: {integrity: sha512-e/52nJGuD74AKTSe0P4y5wFRlaXP0qmrS17rqOMHeSwm278VyNyXE3gFO/4DTGF9w+65ra3lo3VKj0LBrzmgdQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} + '@jest/test-sequencer@30.3.0': + resolution: {integrity: sha512-dgbWy9b8QDlQeRZcv7LNF+/jFiiYHTKho1xirauZ7kVwY7avjFF6uTT0RqlgudB5OuIPagFdVtfFMosjVbk1eA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} - engines: {node: '>=12'} + '@jest/transform@30.3.0': + resolution: {integrity: sha512-TLKY33fSLVd/lKB2YI1pH69ijyUblO/BQvCj566YvnwuzoTNr648iE0j22vRvVNk2HsPwByPxATg3MleS3gf5A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + '@jest/types@30.3.0': + resolution: {integrity: sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} - array-ify@1.0.0: - resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} - arrify@3.0.0: - resolution: {integrity: sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==} - engines: {node: '>=12'} + '@jridgewell/source-map@0.3.11': + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} - atomic-sleep@1.0.0: - resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} - engines: {node: '>=8.0.0'} + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - avvio@9.1.0: - resolution: {integrity: sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==} + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - awilix-manager@6.1.0: - resolution: {integrity: sha512-lI769LH19Co5rQoivSXBfU2nuNR/Hnwfsbc0ZSWGbz4NmZUa8J5LMdIwxSHtGgBVeoqgdYb6Lbmw/Y9C5jE5FA==} - engines: {node: '>=16'} - peerDependencies: - awilix: '>=9.0.0' + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - awilix@12.0.5: - resolution: {integrity: sha512-Qf/V/hRo6DK0FoBKJ9QiObasRxHAhcNi0mV6kW2JMawxS3zq6Un+VsZmVAZDUfvB+MjTEiJ2tUJUl4cr0JiUAw==} - engines: {node: '>=16.3.0'} + '@keyv/serialize@1.1.1': + resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + '@lukeed/csprng@1.1.0': + resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} + engines: {node: '>=8'} - better-result@2.7.0: - resolution: {integrity: sha512-7zrmXjAK8u8Z6SOe4R65XObOR5X+Y2I/VVku3t5cPOGQ8/WsBcfFmfnIPiEl5EBMDOzPHRwbiPbMtQBKYdw7RA==} - hasBin: true + '@lukeed/ms@2.0.2': + resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} + engines: {node: '>=8'} - boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + '@microsoft/tsdoc@0.16.0': + resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + '@mindenit/cist-crawler@0.1.4': + resolution: {integrity: sha512-BLxII1akKjidYZVWWfOhQRZtr4oybHS3BD+q3FPzUOvPzTK35GRnjNFezQCd7039SAo1RgqnUlpdk/dPl0MXUw==} + engines: {node: '>= 22.x'} - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + '@napi-rs/nice-android-arm-eabi@1.1.1': + resolution: {integrity: sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} + '@napi-rs/nice-android-arm64@1.1.1': + resolution: {integrity: sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + '@napi-rs/nice-darwin-arm64@1.1.1': + resolution: {integrity: sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} + '@napi-rs/nice-darwin-x64@1.1.1': + resolution: {integrity: sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] - call-bound@1.0.4: - resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} - engines: {node: '>= 0.4'} + '@napi-rs/nice-freebsd-x64@1.1.1': + resolution: {integrity: sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} + '@napi-rs/nice-linux-arm-gnueabihf@1.1.1': + resolution: {integrity: sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] - camel-case@4.1.2: - resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + '@napi-rs/nice-linux-arm64-gnu@1.1.1': + resolution: {integrity: sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} + '@napi-rs/nice-linux-arm64-musl@1.1.1': + resolution: {integrity: sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] - chalk@5.4.1: - resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + '@napi-rs/nice-linux-ppc64-gnu@1.1.1': + resolution: {integrity: sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==} + engines: {node: '>= 10'} + cpu: [ppc64] + os: [linux] - clean-stack@4.2.0: - resolution: {integrity: sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==} - engines: {node: '>=12'} + '@napi-rs/nice-linux-riscv64-gnu@1.1.1': + resolution: {integrity: sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] - cli-cursor@5.0.0: - resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} - engines: {node: '>=18'} + '@napi-rs/nice-linux-s390x-gnu@1.1.1': + resolution: {integrity: sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==} + engines: {node: '>= 10'} + cpu: [s390x] + os: [linux] - cli-truncate@4.0.0: - resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} - engines: {node: '>=18'} + '@napi-rs/nice-linux-x64-gnu@1.1.1': + resolution: {integrity: sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} + '@napi-rs/nice-linux-x64-musl@1.1.1': + resolution: {integrity: sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] - cluster-key-slot@1.1.2: - resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} - engines: {node: '>=0.10.0'} + '@napi-rs/nice-openharmony-arm64@1.1.1': + resolution: {integrity: sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [openharmony] - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + '@napi-rs/nice-win32-arm64-msvc@1.1.1': + resolution: {integrity: sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + '@napi-rs/nice-win32-ia32-msvc@1.1.1': + resolution: {integrity: sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] - colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + '@napi-rs/nice-win32-x64-msvc@1.1.1': + resolution: {integrity: sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] - commander@12.1.0: - resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} - engines: {node: '>=18'} + '@napi-rs/nice@1.1.1': + resolution: {integrity: sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==} + engines: {node: '>= 10'} - commander@13.1.0: - resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} - engines: {node: '>=18'} + '@napi-rs/wasm-runtime@0.2.12': + resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} - compare-func@2.0.0: - resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + '@napi-rs/wasm-runtime@1.1.4': + resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + '@nestjs/cli@11.0.21': + resolution: {integrity: sha512-F8mV0Sj/zVEouzR3NxBuJy08YHTUOmC5Xdcx3qIIaJWzrm8Vw86CHkhkaPBJ5ewRMHPDCShPmhsfwhpCcjts3A==} + engines: {node: '>= 20.11'} + hasBin: true + peerDependencies: + '@swc/cli': ^0.1.62 || ^0.3.0 || ^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0 || ^0.8.0 + '@swc/core': ^1.3.62 + peerDependenciesMeta: + '@swc/cli': + optional: true + '@swc/core': + optional: true - conventional-changelog-angular@7.0.0: - resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} - engines: {node: '>=16'} + '@nestjs/common@11.1.19': + resolution: {integrity: sha512-qeiTt2tv+e5QyDKqG8HlVZb2wx64FEaSGFJouqTSRs+kG44iTfl3xlz1XqVped+rihx4hmjWgL5gkhtdK3E6+Q==} + peerDependencies: + class-transformer: '>=0.4.1' + class-validator: '>=0.13.2' + reflect-metadata: ^0.1.12 || ^0.2.0 + rxjs: ^7.1.0 + peerDependenciesMeta: + class-transformer: + optional: true + class-validator: + optional: true - conventional-changelog-conventionalcommits@7.0.2: - resolution: {integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==} - engines: {node: '>=16'} + '@nestjs/core@11.1.19': + resolution: {integrity: sha512-6nJkWa2efrYi+XlU686J9y5L7OvxpLVjT0T/sxRKE7Jvpffiihelup4WSvLvRhdHDjj/5SuoWEwqReXAaaeHmw==} + engines: {node: '>= 20'} + peerDependencies: + '@nestjs/common': ^11.0.0 + '@nestjs/microservices': ^11.0.0 + '@nestjs/platform-express': ^11.0.0 + '@nestjs/websockets': ^11.0.0 + reflect-metadata: ^0.1.12 || ^0.2.0 + rxjs: ^7.1.0 + peerDependenciesMeta: + '@nestjs/microservices': + optional: true + '@nestjs/platform-express': + optional: true + '@nestjs/websockets': + optional: true - conventional-commits-parser@5.0.0: - resolution: {integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==} - engines: {node: '>=16'} - hasBin: true + '@nestjs/mapped-types@2.1.1': + resolution: {integrity: sha512-SCCoMEJ6jdeI5h/N+KCVF1+pmg/hmEkNA5nHTS8Gvww7T/LCl4o1gFLinw2iQ60w7slFkszHcGLKGdazVI4F8A==} + peerDependencies: + '@nestjs/common': ^10.0.0 || ^11.0.0 + class-transformer: ^0.4.0 || ^0.5.0 + class-validator: ^0.13.0 || ^0.14.0 || ^0.15.0 + reflect-metadata: ^0.1.12 || ^0.2.0 + peerDependenciesMeta: + class-transformer: + optional: true + class-validator: + optional: true - cookie@1.0.2: - resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} - engines: {node: '>=18'} + '@nestjs/platform-fastify@11.1.19': + resolution: {integrity: sha512-PdldJPw+xu8JM7VNE2FY+ty+qoxDMW7326h/z0MtfZvKj84FE6zuqpcSXen1CYjtyP8og+x/5XrJbKKKDNabtQ==} + peerDependencies: + '@fastify/static': ^8.0.0 || ^9.0.0 + '@fastify/view': ^10.0.0 || ^11.0.0 + '@nestjs/common': ^11.0.0 + '@nestjs/core': ^11.0.0 + peerDependenciesMeta: + '@fastify/static': + optional: true + '@fastify/view': + optional: true - cosmiconfig-typescript-loader@6.1.0: - resolution: {integrity: sha512-tJ1w35ZRUiM5FeTzT7DtYWAFFv37ZLqSRkGi2oeCK1gPhvaWjkAtfXvLmvE1pRfxxp9aQo6ba/Pvg1dKj05D4g==} - engines: {node: '>=v18'} + '@nestjs/schedule@6.1.3': + resolution: {integrity: sha512-RflMFOpR16Dwd1jAUbeB4mfGTCh65fvEdL4mSjQPJChpkRGRjIXjb+6YQcK2faQrVT60c9DmLmoVR7/ONCtuYQ==} peerDependencies: - '@types/node': '*' - cosmiconfig: '>=9' - typescript: '>=5' + '@nestjs/common': ^10.0.0 || ^11.0.0 + '@nestjs/core': ^10.0.0 || ^11.0.0 - cosmiconfig@9.0.0: - resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} - engines: {node: '>=14'} + '@nestjs/schematics@11.1.0': + resolution: {integrity: sha512-lVxGZ46tcdItFMoXr6vyKWlnOsm1SZm/GUqAEDvy2RL4Q4O+3bkziAhrO7Y8JLssFUUvNFEGqAizI52WAxhjDw==} peerDependencies: - typescript: '>=4.9.5' + prettier: ^3.0.0 + typescript: '>=4.8.2' peerDependenciesMeta: - typescript: + prettier: optional: true - cp-file@10.0.0: - resolution: {integrity: sha512-vy2Vi1r2epK5WqxOLnskeKeZkdZvTKfFZQCplE3XWsP+SUJyd5XAUFC9lFgTjjXJF2GMne/UML14iEmkAaDfFg==} - engines: {node: '>=14.16'} + '@nestjs/swagger@11.4.1': + resolution: {integrity: sha512-GuGzs8F1Cb3n+eEarmOqB4nt2ai+x4XGOYUXNYplOtDeB59DaFY5E16bsHsBWXiWgD1ywbyKQ5OVv02bQtB1Dw==} + peerDependencies: + '@fastify/static': ^8.0.0 || ^9.0.0 + '@nestjs/common': ^11.0.1 + '@nestjs/core': ^11.0.1 + class-transformer: '*' + class-validator: '*' + reflect-metadata: ^0.1.12 || ^0.2.0 + peerDependenciesMeta: + '@fastify/static': + optional: true + class-transformer: + optional: true + class-validator: + optional: true + + '@nestjs/testing@11.1.19': + resolution: {integrity: sha512-/UFNWXvPEdu4v4DlC5oWLbGKmD27LehLK06b8oLzs6D6lf4vAQTdST8LRAXBadyMUQnVEQWMuBo3CtAVtlfXtQ==} + peerDependencies: + '@nestjs/common': ^11.0.0 + '@nestjs/core': ^11.0.0 + '@nestjs/microservices': ^11.0.0 + '@nestjs/platform-express': ^11.0.0 + peerDependenciesMeta: + '@nestjs/microservices': + optional: true + '@nestjs/platform-express': + optional: true + + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@nuxt/opencollective@0.4.1': + resolution: {integrity: sha512-GXD3wy50qYbxCJ652bDrDzgMr3NFEkIS374+IgFQKkCvk9yiYcLvX2XDYr7UyQxf4wK0e+yqDYRubZ0DtOxnmQ==} + engines: {node: ^14.18.0 || >=16.10.0, npm: '>=5.10.0'} + hasBin: true + + '@oxc-project/types@0.127.0': + resolution: {integrity: sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==} + + '@paralleldrive/cuid2@2.3.1': + resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==} + + '@pinojs/redact@0.4.0': + resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pkgr/core@0.2.7': + resolution: {integrity: sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@rolldown/binding-android-arm64@1.0.0-rc.17': + resolution: {integrity: sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.0-rc.17': + resolution: {integrity: sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-rc.17': + resolution: {integrity: sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-rc.17': + resolution: {integrity: sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': + resolution: {integrity: sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': + resolution: {integrity: sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': + resolution: {integrity: sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': + resolution: {integrity: sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': + resolution: {integrity: sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': + resolution: {integrity: sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': + resolution: {integrity: sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': + resolution: {integrity: sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': + resolution: {integrity: sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': + resolution: {integrity: sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': + resolution: {integrity: sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.0-rc.17': + resolution: {integrity: sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==} + + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@scalar/client-side-rendering@0.1.3': + resolution: {integrity: sha512-rUI5EQA8y0xivzqc/AwExZYW8HRfQSFxPxvvuLjHTCATpKz0xcQBGVJQIPOmp78NJyO8mnQmltE1AxIdtvdPGg==} + engines: {node: '>=22'} + + '@scalar/core@0.3.1': + resolution: {integrity: sha512-k5TsihZcSdVnqE6JrRFdsvePDTe2RxjE+1wHdcnyFdIPief+ZdPn2fxCTlN0ozLoe08xlY3N9DHzDaneMpX58Q==} + engines: {node: '>=20'} + + '@scalar/fastify-api-reference@1.31.3': + resolution: {integrity: sha512-r+VotFGBZvD8Cpj99AlZLAF4qVVYBsvHx6XRUzoLEViba16WJICPBpQ+xWmC9fVAUzQR58TvwUjI7X1h37Sp/A==} + engines: {node: '>=20'} + + '@scalar/helpers@0.5.2': + resolution: {integrity: sha512-Pi1GAl8jO6ungmGj2sjDfCfqiBNrKW6HXDZmminV94ybGU/KtRLOqHwd0n9FIhY3j0RYGpGC0VCuniCICfQPHg==} + engines: {node: '>=22'} + + '@scalar/nestjs-api-reference@1.1.10': + resolution: {integrity: sha512-cArel3yufju5WXvuU76MkLZC1W/tW7nUwIHWKtrG5ctog3GPSNeVlAFYidA1GsgyplHJU2P7emtwEzK3WTp6OQ==} + engines: {node: '>=22'} + + '@scalar/openapi-parser@0.14.0': + resolution: {integrity: sha512-54KxfMUioaNYYQLZuTPUVcBqBSS7vFrd+bA4p95uYvvnWP/7lL+t1dQqQk+jRv7uut6IbnjiDeFFIkVABteJSA==} + engines: {node: '>=20'} + + '@scalar/openapi-types@0.3.1': + resolution: {integrity: sha512-635pb0OIxhhr2yVPwqExOyNh8eo01JLOqXkDvvflHFBaGo7CHvq5sduwriXdplkn2TRNkxdkdy/eNSOMNPVa1A==} + engines: {node: '>=20'} + + '@scalar/types@0.2.1': + resolution: {integrity: sha512-eXcxuwazLABrnCjpqE4tG+FgiCKyHhKxB4V8Bn4Uj/XCBTemRd+WSzXp0mmpGuBbqz820j5UGrlZ5cWlUWaWWw==} + engines: {node: '>=20'} + + '@scalar/types@0.9.2': + resolution: {integrity: sha512-aLn7QTHafpjrN/whup7U5/CHaoPPaYMNtz4L/2yfN5GDSy3AbDM7kV1q8s3nMQIhvC1uscxfriV+KhEND+xHvA==} + engines: {node: '>=22'} + + '@scarf/scarf@1.4.0': + resolution: {integrity: sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==} + + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + + '@sinclair/typebox@0.34.49': + resolution: {integrity: sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A==} + + '@sindresorhus/is@7.2.0': + resolution: {integrity: sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==} + engines: {node: '>=18'} + + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@15.3.2': + resolution: {integrity: sha512-mrn35Jl2pCpns+mE3HaZa1yPN5EYCRgiMI+135COjr2hr8Cls9DXqIZ57vZe2cz7y2XVSq92tcs6kGQcT1J8Rw==} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@swc/cli@0.8.1': + resolution: {integrity: sha512-L+ACCGHCiS0VqHVep/INLVnvRvJ2XooQFLZq4L8snhxw1jsqz+XRcY313UsyPVturPPE1shW3jic7rt3qEQTSQ==} + engines: {node: '>= 20.19.0'} + hasBin: true + peerDependencies: + '@swc/core': ^1.2.66 + chokidar: ^5.0.0 + peerDependenciesMeta: + chokidar: + optional: true + + '@swc/core-darwin-arm64@1.15.30': + resolution: {integrity: sha512-VvpP+vq08HmGYewMWvrdsxh9s2lthz/808zXm8Yu5kaqeR8Yia2b0eYXleHQ3VAjoStUDk6LzTheBW9KXYQdMA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + + '@swc/core-darwin-x64@1.15.30': + resolution: {integrity: sha512-WiJA0hiZI3nwQAO6mu5RqigtWGDtth4Hiq6rbZxAaQyhIcqKIg5IoMRc1Y071lrNJn29eEDMC86Rq58xgUxlDg==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + + '@swc/core-linux-arm-gnueabihf@1.15.30': + resolution: {integrity: sha512-YANuFUo48kIT6plJgCD0keae9HFXfjxsbvsgevqc0hr/07X/p7sAWTFOGYEc2SXcASaK7UvuQqzlbW8pr7R79g==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + + '@swc/core-linux-arm64-gnu@1.15.30': + resolution: {integrity: sha512-VndG8jaR4ugY6u+iVOT0Q+d2fZd7sLgjPgN8W/Le+3EbZKl+cRfFxV7Eoz4gfLqhmneZPdcIzf9T3LkgkmqNLg==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-arm64-musl@1.15.30': + resolution: {integrity: sha512-1SYGs2l0Yyyi0pR/P/NKz/x0kqxkoiw+BXeJjLUdecSk/KasncWlJrc6hOvFSgKHOBrzgM5jwuluKtlT8dnrcA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-ppc64-gnu@1.15.30': + resolution: {integrity: sha512-TXREtiXeRhbfDFbmhnkIsXpKfzbfT73YkV2ZF6w0sfxgjC5zI2ZAbaCOq25qxvegofj2K93DtOpm9RLaBgqR2g==} + engines: {node: '>=10'} + cpu: [ppc64] + os: [linux] + + '@swc/core-linux-s390x-gnu@1.15.30': + resolution: {integrity: sha512-DCR2YYeyd6DQE4OuDhImouuNcjXEiEdnn1Y0DyGteugPEDvVuvYk8Xddi+4o2SgWH6jiW8/I+3emZvbep1NC+g==} + engines: {node: '>=10'} + cpu: [s390x] + os: [linux] + + '@swc/core-linux-x64-gnu@1.15.30': + resolution: {integrity: sha512-5Pizw3NgfOJ5BJOBK8TIRa59xFW2avESTOBDPTAYwZYa1JNDs+KMF9lUfjJiJLM5HiMs/wPheA9eiT0q9m2AoA==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-linux-x64-musl@1.15.30': + resolution: {integrity: sha512-qyqydP/wyH8alcIP4a2hnGSjHLJjm9H7yDFup+CPy9oTahFgLLwnNcv5UHXqO2Qs3AIND+cls5f/Bb6hqpxdgA==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-win32-arm64-msvc@1.15.30': + resolution: {integrity: sha512-CaQENgDHVGOg1mSF5sQVgvfFHG9kjMor2rkLMLeLOkfZYNj13ppnJ9+lfaBZLZUMMbnlGQnavCJb8PVBUOso7Q==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + + '@swc/core-win32-ia32-msvc@1.15.30': + resolution: {integrity: sha512-30VdLeGk6fugiUs/kUdJ/pAg7z/zpvVbR11RH60jZ0Z42WIeIniYx0rLEWN7h/pKJ3CopqsQ3RsogCAkRKiA2g==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + + '@swc/core-win32-x64-msvc@1.15.30': + resolution: {integrity: sha512-4iObHPR+Q4oDY110EF5SF5eIaaVJNpMdG9C0q3Q92BsJ5y467uHz7sYQhP60WYlLFsLQ1el2YrIPUItUAQGOKg==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + + '@swc/core@1.15.30': + resolution: {integrity: sha512-R8VQbQY1BZcbIF2p3gjlTCwAQzx1A194ugWfwld5y+WgVVWqVKm7eURGGOVbQVubgKWzidP2agomBbg96rZilQ==} + engines: {node: '>=10'} + peerDependencies: + '@swc/helpers': '>=0.5.17' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + '@swc/types@0.1.26': + resolution: {integrity: sha512-lyMwd7WGgG79RS7EERZV3T8wMdmPq3xwyg+1nmAM64kIhx5yl+juO2PYIHb7vTiPgPCj8LYjsNV2T5wiQHUEaw==} + + '@tokenizer/inflate@0.4.1': + resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} + engines: {node: '>=18'} + + '@tokenizer/token@0.3.0': + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + + '@total-typescript/ts-reset@0.6.1': + resolution: {integrity: sha512-cka47fVSo6lfQDIATYqb/vO1nvFfbPw7uWLayIXIhGETj0wcOOlrlkobOMDNQOFr9QOafegUPq13V2+6vtD7yg==} + + '@tsconfig/node10@1.0.12': + resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/conventional-commits-parser@5.0.1': + resolution: {integrity: sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==} + + '@types/cookiejar@2.1.5': + resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/eslint-scope@3.7.7': + resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} + + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + + '@types/estree@1.0.7': + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/http-cache-semantics@4.2.0': + resolution: {integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@30.0.0': + resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/luxon@3.7.1': + resolution: {integrity: sha512-H3iskjFIAn5SlJU7OuxUmTEpebK6TKB8rxZShDslBMZJ5u9S//KM1sbdAisiSrqwLQncVjnpi2OK2J51h+4lsg==} + + '@types/methods@1.1.4': + resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==} + + '@types/node@22.15.29': + resolution: {integrity: sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==} + + '@types/qs@6.14.0': + resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/superagent@8.1.9': + resolution: {integrity: sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==} + + '@types/supertest@7.2.0': + resolution: {integrity: sha512-uh2Lv57xvggst6lCqNdFAmDSvoMG7M/HDtX4iUCquxQ5EGPtaPM5PL5Hmi7LCvOG8db7YaCPNJEeoI8s/WzIQw==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + + '@typescript-eslint/eslint-plugin@8.33.1': + resolution: {integrity: sha512-TDCXj+YxLgtvxvFlAvpoRv9MAncDLBV2oT9Bd7YBGC/b/sEURoOYuIwLI99rjWOfY3QtDzO+mk0n4AmdFExW8A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.33.1 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/parser@8.33.1': + resolution: {integrity: sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/project-service@8.33.1': + resolution: {integrity: sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/scope-manager@8.33.1': + resolution: {integrity: sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.33.1': + resolution: {integrity: sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/type-utils@8.33.1': + resolution: {integrity: sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/types@8.33.1': + resolution: {integrity: sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.33.1': + resolution: {integrity: sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/utils@8.33.1': + resolution: {integrity: sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/visitor-keys@8.33.1': + resolution: {integrity: sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} + cpu: [arm] + os: [android] + + '@unrs/resolver-binding-android-arm64@1.11.1': + resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} + cpu: [arm64] + os: [android] + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} + cpu: [arm64] + os: [darwin] + + '@unrs/resolver-binding-darwin-x64@1.11.1': + resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} + cpu: [x64] + os: [darwin] + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} + cpu: [x64] + os: [freebsd] + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} + cpu: [ppc64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} + cpu: [s390x] + os: [linux] + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} + cpu: [arm64] + os: [win32] + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} + cpu: [ia32] + os: [win32] + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} + cpu: [x64] + os: [win32] + + '@vitest/coverage-v8@4.1.5': + resolution: {integrity: sha512-38C0/Ddb7HcRG0Z4/DUem8x57d2p9jYgp18mkaYswEOQBGsI1CG4f/hjm0ZCeaJfWhSZ4k7jgs29V1Zom7Ki9A==} + peerDependencies: + '@vitest/browser': 4.1.5 + vitest: 4.1.5 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/expect@4.1.5': + resolution: {integrity: sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==} + + '@vitest/mocker@4.1.5': + resolution: {integrity: sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.1.5': + resolution: {integrity: sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==} + + '@vitest/runner@4.1.5': + resolution: {integrity: sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==} + + '@vitest/snapshot@4.1.5': + resolution: {integrity: sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==} + + '@vitest/spy@4.1.5': + resolution: {integrity: sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==} + + '@vitest/utils@4.1.5': + resolution: {integrity: sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==} + + '@webassemblyjs/ast@1.14.1': + resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} + + '@webassemblyjs/floating-point-hex-parser@1.13.2': + resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} + + '@webassemblyjs/helper-api-error@1.13.2': + resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} + + '@webassemblyjs/helper-buffer@1.14.1': + resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} + + '@webassemblyjs/helper-numbers@1.13.2': + resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': + resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} + + '@webassemblyjs/helper-wasm-section@1.14.1': + resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} + + '@webassemblyjs/ieee754@1.13.2': + resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} + + '@webassemblyjs/leb128@1.13.2': + resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} + + '@webassemblyjs/utf8@1.13.2': + resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} + + '@webassemblyjs/wasm-edit@1.14.1': + resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} + + '@webassemblyjs/wasm-gen@1.14.1': + resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} + + '@webassemblyjs/wasm-opt@1.14.1': + resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} + + '@webassemblyjs/wasm-parser@1.14.1': + resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} + + '@webassemblyjs/wast-printer@1.14.1': + resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} + + '@xhmikosr/archive-type@8.0.1': + resolution: {integrity: sha512-toXuiWChyfOpEiCPsIw6HGHaNji5LVkvB6EREL548vGWr+hGaehwxG4LzN20vm9aGFXwnA/Jty8yW2/SmV+1zQ==} + engines: {node: '>=20'} + + '@xhmikosr/bin-check@8.2.1': + resolution: {integrity: sha512-DNruLq+kalxcE7JeDxtqrN9kyWjLW8VqsQPLRTwD1t9ck/1rF4qBL0mX5Fe2/xLOMjo5wPb67BNX2kSAhzfLjA==} + engines: {node: '>=20'} + + '@xhmikosr/bin-wrapper@14.2.3': + resolution: {integrity: sha512-F8Sr2O2aqwYfoXTafemRNAYDG4xwBTaHJpAo9YVnnnRXHLP9gkb+HYDsFoCAsCneS3/J7BOfeYnxxlUCicLqjg==} + engines: {node: '>=20'} + + '@xhmikosr/decompress-tar@9.0.1': + resolution: {integrity: sha512-4AkVR1SoqTxYY22IRRYKDeLirPIDGqMqYsqgjKYuwhgRcBb+yDP4t5Xph33UCzL/nahK/aADmlMEjTNstbX7kw==} + engines: {node: '>=20'} + + '@xhmikosr/decompress-tarbz2@9.0.1': + resolution: {integrity: sha512-aFONnsbqEOuXudvK7V7wB8dcEAKR389oUYQfZhrQZA8OtogJpDjrUAvEH3Qlc9yFqTU6r5/svTEcRwtXhoIJbQ==} + engines: {node: '>=20'} + + '@xhmikosr/decompress-targz@9.0.1': + resolution: {integrity: sha512-1JXu2b6yrpm5EuBoOzMU57B4qrHXJKWQQ7LlMynNEiz85mEjDciO3ayf//GXaTLLCEKiHjWlU3q3THjgf7uODA==} + engines: {node: '>=20'} + + '@xhmikosr/decompress-unzip@8.1.0': + resolution: {integrity: sha512-hVcpEZIS8avXU1ioR0Pb2LcBYHfah1lzzTQPDItkBi3W+kSE/DxSeEgOoHJB8rn+Izm0ArWZxxlpsvEK4ySjaw==} + engines: {node: '>=20'} + + '@xhmikosr/decompress@11.1.2': + resolution: {integrity: sha512-f2hlnMN1ChbifAfdzWns6mssojjr3lgJm6MtT4ttVAClx85QEIQAdGXN22bPqy/qKxbvDf93GdqbR6+xIO/a4A==} + engines: {node: '>=20'} + + '@xhmikosr/downloader@16.1.2': + resolution: {integrity: sha512-31KQzQ6p4Rwnbo/gwTe4/Z+hVRcC8YoH/8f5xl+so1Oqqah5u1R3CGte8od+wOyNVfZ77DFijwy1umHk2NT6ZQ==} + engines: {node: '>=20'} + + '@xhmikosr/os-filter-obj@4.0.0': + resolution: {integrity: sha512-CBJYipR5lrtQQZl9ylarWyh1qhcs/tMy9ydSHte/Hefn3ev8NMvS3ss+eqiXEoBr2wBVgKj2qjcViXO9P/8K4A==} + engines: {node: '>=20'} + + '@xtuc/ieee754@1.2.0': + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + + '@xtuc/long@4.2.2': + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + + JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + + abstract-logging@2.0.1: + resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} + + acorn-import-phases@1.0.4: + resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} + engines: {node: '>=10.13.0'} + peerDependencies: + acorn: ^8.14.0 + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@8.3.5: + resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} + engines: {node: '>=0.4.0'} + + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + engines: {node: '>=0.4.0'} + hasBin: true + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + aggregate-error@4.0.1: + resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==} + engines: {node: '>=12'} + + ajv-draft-04@1.0.0: + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-keywords@3.5.2: + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + + ajv-keywords@5.1.0: + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-escapes@7.0.0: + resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + engines: {node: '>=18'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + ansis@4.2.0: + resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} + engines: {node: '>=14'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arch@3.0.0: + resolution: {integrity: sha512-AmIAC+Wtm2AU8lGfTtHsw0Y9Qtftx2YXEEtiBP10xFUtMOA+sHHx6OAddyL52mUKh1vsXQ6/w1mVDptZCyUt4Q==} + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-ify@1.0.0: + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} + + array-timsort@1.0.3: + resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} + + arrify@3.0.0: + resolution: {integrity: sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==} + engines: {node: '>=12'} + + asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + ast-v8-to-istanbul@1.0.0: + resolution: {integrity: sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + + avvio@9.1.0: + resolution: {integrity: sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==} + + awilix-manager@6.1.0: + resolution: {integrity: sha512-lI769LH19Co5rQoivSXBfU2nuNR/Hnwfsbc0ZSWGbz4NmZUa8J5LMdIwxSHtGgBVeoqgdYb6Lbmw/Y9C5jE5FA==} + engines: {node: '>=16'} + peerDependencies: + awilix: '>=9.0.0' + + awilix@12.0.5: + resolution: {integrity: sha512-Qf/V/hRo6DK0FoBKJ9QiObasRxHAhcNi0mV6kW2JMawxS3zq6Un+VsZmVAZDUfvB+MjTEiJ2tUJUl4cr0JiUAw==} + engines: {node: '>=16.3.0'} + + b4a@1.8.0: + resolution: {integrity: sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==} + peerDependencies: + react-native-b4a: '*' + peerDependenciesMeta: + react-native-b4a: + optional: true + + babel-jest@30.3.0: + resolution: {integrity: sha512-gRpauEU2KRrCox5Z296aeVHR4jQ98BCnu0IO332D/xpHNOsIH/bgSRk9k6GbKIbBw8vFeN6ctuu6tV8WOyVfYQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@babel/core': ^7.11.0 || ^8.0.0-0 + + babel-plugin-istanbul@7.0.1: + resolution: {integrity: sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==} + engines: {node: '>=12'} + + babel-plugin-jest-hoist@30.3.0: + resolution: {integrity: sha512-+TRkByhsws6sfPjVaitzadk1I0F5sPvOVUH5tyTSzhePpsGIVrdeunHSw/C36QeocS95OOk8lunc4rlu5Anwsg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + babel-preset-current-node-syntax@1.2.0: + resolution: {integrity: sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==} + peerDependencies: + '@babel/core': ^7.0.0 || ^8.0.0-0 + + babel-preset-jest@30.3.0: + resolution: {integrity: sha512-6ZcUbWHC+dMz2vfzdNwi87Z1gQsLNK2uLuK1Q89R11xdvejcivlYYwDlEv0FHX3VwEXpbBQ9uufB/MUNpZGfhQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@babel/core': ^7.11.0 || ^8.0.0-beta.1 + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + bare-events@2.8.2: + resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==} + peerDependencies: + bare-abort-controller: '*' + peerDependenciesMeta: + bare-abort-controller: + optional: true + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + baseline-browser-mapping@2.10.22: + resolution: {integrity: sha512-6qruVrb5rse6WylFkU0FhBKKGuecWseqdpQfhkawn6ztyk2QlfwSRjsDxMCLJrkfmfN21qvhl9ABgaMeRkuwww==} + engines: {node: '>=6.0.0'} + hasBin: true + + better-result@2.7.0: + resolution: {integrity: sha512-7zrmXjAK8u8Z6SOe4R65XObOR5X+Y2I/VVku3t5cPOGQ8/WsBcfFmfnIPiEl5EBMDOzPHRwbiPbMtQBKYdw7RA==} + hasBin: true + + binary-version-check@6.1.0: + resolution: {integrity: sha512-REKdLKmuViV2WrtWXvNSiPX04KbIjfUV3Cy8batUeOg+FtmowavzJorfFhWq95cVJzINnL/44ixP26TrdJZACA==} + engines: {node: '>=18'} + + binary-version@7.1.0: + resolution: {integrity: sha512-Iy//vPc3ANPNlIWd242Npqc8MK0a/i4kVcHDlDA6HNMv5zMxz4ulIFhOSYJVKw/8AbHdHy0CnGYEt1QqSXxPsw==} + engines: {node: '>=18'} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + brace-expansion@5.0.5: + resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} + engines: {node: 18 || 20 || >=22} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.28.2: + resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bs-logger@0.2.6: + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + byte-counter@0.1.0: + resolution: {integrity: sha512-jheRLVMeUKrDBjVw2O5+k4EvR4t9wtxHL+bo/LxfkxsVeuGMy3a5SEGgXdAFA4FSzTrU8rQXQIrsZ3oBq5a0pQ==} + engines: {node: '>=20'} + + cacheable-lookup@7.0.0: + resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} + engines: {node: '>=14.16'} + + cacheable-request@13.0.18: + resolution: {integrity: sha512-rFWadDRKJs3s2eYdXlGggnBZKG7MTblkFBB0YllFds+UYnfogDp2wcR6JN97FhRkHTvq59n2vhNoHNZn29dh/Q==} + engines: {node: '>=18'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camel-case@4.1.2: + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001790: + resolution: {integrity: sha512-bOoxfJPyYo+ds6W0YfptaCWbFnJYjh2Y1Eow5lRv+vI2u8ganPZqNm1JwNh0t2ELQCqIWg4B3dWEusgAmsoyOw==} + + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + + chardet@2.1.1: + resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + chrome-trace-event@1.0.4: + resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} + engines: {node: '>=6.0'} + + ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + engines: {node: '>=8'} + + cjs-module-lexer@2.2.0: + resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} + + clean-stack@4.2.0: + resolution: {integrity: sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==} + engines: {node: '>=12'} + + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-table3@0.6.5: + resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} + engines: {node: 10.* || >= 12.*} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + cluster-key-slot@1.1.2: + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} + engines: {node: '>=0.10.0'} + + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + collect-v8-coverage@1.0.3: + resolution: {integrity: sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + commander@13.1.0: + resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} + engines: {node: '>=18'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + commander@6.2.1: + resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} + engines: {node: '>= 6'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + + comment-json@5.0.0: + resolution: {integrity: sha512-uiqLcOiVDJtBP8WGkZHEP+FZIhTzP1dxvn59EfoYUi9gqupjrBWVQkO2atDrbnKPwLeotFYDsuNb26uBMqB+hw==} + engines: {node: '>= 6'} + + compare-func@2.0.0: + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + + component-emitter@1.3.1: + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + + content-disposition@1.1.0: + resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==} + engines: {node: '>=18'} + + conventional-changelog-angular@7.0.0: + resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} + engines: {node: '>=16'} + + conventional-changelog-conventionalcommits@7.0.2: + resolution: {integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==} + engines: {node: '>=16'} + + conventional-commits-parser@5.0.0: + resolution: {integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==} + engines: {node: '>=16'} + hasBin: true + + convert-hrtime@5.0.0: + resolution: {integrity: sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==} + engines: {node: '>=12'} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + + cookie@1.0.2: + resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} + engines: {node: '>=18'} + + cookiejar@2.1.4: + resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==} + + cosmiconfig-typescript-loader@6.1.0: + resolution: {integrity: sha512-tJ1w35ZRUiM5FeTzT7DtYWAFFv37ZLqSRkGi2oeCK1gPhvaWjkAtfXvLmvE1pRfxxp9aQo6ba/Pvg1dKj05D4g==} + engines: {node: '>=v18'} + peerDependencies: + '@types/node': '*' + cosmiconfig: '>=9' + typescript: '>=5' + + cosmiconfig@8.3.6: + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + cosmiconfig@9.0.0: + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + cp-file@10.0.0: + resolution: {integrity: sha512-vy2Vi1r2epK5WqxOLnskeKeZkdZvTKfFZQCplE3XWsP+SUJyd5XAUFC9lFgTjjXJF2GMne/UML14iEmkAaDfFg==} + engines: {node: '>=14.16'} + + cpy-cli@5.0.0: + resolution: {integrity: sha512-fb+DZYbL9KHc0BC4NYqGRrDIJZPXUmjjtqdw4XRRg8iV8dIfghUX/WiL+q4/B/KFTy3sK6jsbUhBaz0/Hxg7IQ==} + engines: {node: '>=16'} + hasBin: true + + cpy@10.1.0: + resolution: {integrity: sha512-VC2Gs20JcTyeQob6UViBLnyP0bYHkBh6EiKzot9vi2DmeGlFT9Wd7VG3NBrkNx/jYvFBeyDOMMHdHQhbtKLgHQ==} + engines: {node: '>=16'} + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cron@4.4.0: + resolution: {integrity: sha512-fkdfq+b+AHI4cKdhZlppHveI/mgz2qpiYxcm+t5E5TsxX7QrLS1VE0+7GENEk9z0EeGPcpSciGv6ez24duWhwQ==} + engines: {node: '>=18.x'} + + croner@8.1.2: + resolution: {integrity: sha512-ypfPFcAXHuAZRCzo3vJL6ltENzniTjwe/qsLleH1V2/7SRDjgvRQyrLmumFTLmjFax4IuSxfGXEn79fozXcJog==} + engines: {node: '>=18.0'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + + dargs@8.1.0: + resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} + engines: {node: '>=12'} + + dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decompress-response@10.0.0: + resolution: {integrity: sha512-oj7KWToJuuxlPr7VV0vabvxEIiqNMo+q0NueIiL3XhtwC6FVOX7Hr1c0C4eD0bmf7Zr+S/dSf2xvkH3Ad6sU3Q==} + engines: {node: '>=20'} + + dedent@1.7.2: + resolution: {integrity: sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + denque@2.1.0: + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} + engines: {node: '>=0.10'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + + dezalgo@1.0.4: + resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} + + diff@4.0.4: + resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==} + engines: {node: '>=0.3.1'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + dot-prop@5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + + dotenv@16.5.0: + resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} + engines: {node: '>=12'} + + drizzle-kit@1.0.0-beta.1-c0277c0: + resolution: {integrity: sha512-8oRt69AyPA1ONsI1/2nZCJGkp9egyQOOe/uBuNB8yxcWxIMCDI60OF4rLHUaYfpHP4zuqJwiABFIBQUViPxXTw==} + hasBin: true + + drizzle-orm@1.0.0-beta.1-c0277c0: + resolution: {integrity: sha512-4XnmY3CdFHUzJpbRwc6mElkpDzyZs8Ko98i+cRuuPlakFgZqItr+inoK0bFTH50Eh66E/UXbxfAW6U0JK/1wyw==} + peerDependencies: + '@aws-sdk/client-rds-data': '>=3' + '@cloudflare/workers-types': '>=4' + '@electric-sql/pglite': '>=0.2.0' + '@libsql/client': '>=0.10.0' + '@libsql/client-wasm': '>=0.10.0' + '@neondatabase/serverless': '>=0.10.0' + '@op-engineering/op-sqlite': '>=2' + '@opentelemetry/api': ^1.4.1 + '@planetscale/database': '>=1.13' + '@prisma/client': '*' + '@tidbcloud/serverless': '*' + '@types/better-sqlite3': '*' + '@types/pg': '*' + '@types/sql.js': '*' + '@vercel/postgres': '>=0.8.0' + '@xata.io/client': '*' + better-sqlite3: '>=9.3.0' + bun-types: '*' + expo-sqlite: '>=14.0.0' + gel: '>=2' + knex: '*' + kysely: '*' + mysql2: '>=2' + pg: '>=8' + postgres: '>=3' + prisma: '*' + sql.js: '>=1' + sqlite3: '>=5' + peerDependenciesMeta: + '@aws-sdk/client-rds-data': + optional: true + '@cloudflare/workers-types': + optional: true + '@electric-sql/pglite': + optional: true + '@libsql/client': + optional: true + '@libsql/client-wasm': + optional: true + '@neondatabase/serverless': + optional: true + '@op-engineering/op-sqlite': + optional: true + '@opentelemetry/api': + optional: true + '@planetscale/database': + optional: true + '@prisma/client': + optional: true + '@tidbcloud/serverless': + optional: true + '@types/better-sqlite3': + optional: true + '@types/pg': + optional: true + '@types/sql.js': + optional: true + '@vercel/postgres': + optional: true + '@xata.io/client': + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + expo-sqlite: + optional: true + gel: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + prisma: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + electron-to-chromium@1.5.344: + resolution: {integrity: sha512-4MxfbmNDm+KPh066EZy+eUnkcDPcZ35wNmOWzFuh/ijvHsve6kbLTLURy88uCNK5FbpN+yk2nQY6BYh1GEt+wg==} + + emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + enhanced-resolve@5.21.0: + resolution: {integrity: sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==} + engines: {node: '>=10.13.0'} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + esbuild-register@3.6.0: + resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} + peerDependencies: + esbuild: '>=0.12 <1' + + esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.25.5: + resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + eslint-config-prettier@10.1.5: + resolution: {integrity: sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-plugin-prettier@5.4.1: + resolution: {integrity: sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + + eslint-scope@8.3.0: + resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + 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} + + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.28.0: + resolution: {integrity: sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + events-universal@1.0.1: + resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + execa@9.6.1: + resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==} + engines: {node: ^18.19.0 || >=20.5.0} + + exit-x@0.2.2: + resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==} + engines: {node: '>= 0.8.0'} + + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + + expect@30.3.0: + resolution: {integrity: sha512-1zQrciTiQfRdo7qJM1uG4navm8DayFa2TgCSRlzUyNkhcJ6XUZF3hjnpkyr3VhAqPH7i/9GkG7Tv5abz6fqz0Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + ext-list@2.2.2: + resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==} + engines: {node: '>=0.10.0'} + + ext-name@5.0.0: + resolution: {integrity: sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==} + engines: {node: '>=4'} + + fast-copy@3.0.2: + resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} + + fast-decode-uri-component@1.0.1: + resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + + fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-json-stringify@6.0.1: + resolution: {integrity: sha512-s7SJE83QKBZwg54dIbD5rCtzOBVD43V1ReWXXYqBgwCwHLYAAT0RQc/FmrQglXqWPpz6omtryJQOau5jI4Nrvg==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-querystring@1.1.2: + resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} + + fast-redact@3.5.0: + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} + engines: {node: '>=6'} + + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + + fast-uri@3.0.6: + resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + + fastify-plugin@4.5.1: + resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==} + + fastify-plugin@5.0.1: + resolution: {integrity: sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ==} + + fastify-plugin@5.1.0: + resolution: {integrity: sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==} + + fastify-type-provider-zod@5.0.2: + resolution: {integrity: sha512-myolKCxze2rx25Ia88Erb4TZpFIUWyCUqMDgNqE6KQnXoERXwMCPuwfj/1zKkVBlu5dvLo1c/H7GneZUhOWXiw==} + peerDependencies: + '@fastify/swagger': '>=9.5.1' + fastify: ^5.0.0 + zod: '>=3.25.67' + + fastify@5.3.3: + resolution: {integrity: sha512-nCBiBCw9q6jPx+JJNVgO8JVnTXeUyrGcyTKPQikRkA/PanrFcOIo4R+ZnLeOLPZPGgzjomqfVarzE0kYx7qWiQ==} + + fastify@5.8.4: + resolution: {integrity: sha512-sa42J1xylbBAYUWALSBoyXKPDUvM3OoNOibIefA+Oha57FryXKKCZarA1iDntOCWp3O35voZLuDg2mdODXtPzQ==} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + file-type@21.3.4: + resolution: {integrity: sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==} + engines: {node: '>=20'} + + filename-reserved-regex@4.0.0: + resolution: {integrity: sha512-9ZT504KxEQDamsOogZImAWGEN24R1uFAxU3ZS4AZqn2ooidmN68Olh7n4/RcA4lLatZztjA0ZSuxeLHVoCc8JA==} + engines: {node: '>=20'} + + filenamify@7.0.1: + resolution: {integrity: sha512-9b4rfnaX2MkJCgp27wypV6DAMvj4WMOSgJ+TdcpJIO84Dql+Cv6iJjdG4XDTLubOWkfNiBv3joO59sau/TXw+Q==} + engines: {node: '>=20'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-my-way@9.3.0: + resolution: {integrity: sha512-eRoFWQw+Yv2tuYlK2pjFS2jGXSxSppAs3hSQjfxVKxM5amECzIgYYc1FEI8ZmhSh/Ig+FrKEz43NLRKJjYCZVg==} + engines: {node: '>=20'} + + find-my-way@9.5.0: + resolution: {integrity: sha512-VW2RfnmscZO5KgBY5XVyKREMW5nMZcxDy+buTOsL+zIPnBlbKm+00sgzoQzq1EVh4aALZLfKdwv6atBGcjvjrQ==} + engines: {node: '>=20'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + find-up@7.0.0: + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} + engines: {node: '>=18'} + + find-versions@6.0.0: + resolution: {integrity: sha512-2kCCtc+JvcZ86IGAz3Z2Y0A1baIz9fL31pH/0S1IqZr9Iwnjq8izfPtrCyQKO6TLMPELLsQMre7VDqeIKCsHkA==} + engines: {node: '>=18'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + fork-ts-checker-webpack-plugin@9.1.0: + resolution: {integrity: sha512-mpafl89VFPJmhnJ1ssH+8wmM2b50n+Rew5x42NeI2U78aRWgtkEtGmctp7iT16UjquJTjorEmIfESj3DxdW84Q==} + engines: {node: '>=14.21.3'} + peerDependencies: + typescript: '>3.6.0' + webpack: ^5.11.0 + + form-data-encoder@4.1.0: + resolution: {integrity: sha512-G6NsmEW15s0Uw9XnCg+33H3ViYRyiM0hMrMhhqQOR8NFc5GhYrI+6I3u7OTw7b91J2g8rtvMBZJDbcGb2YUniw==} + engines: {node: '>= 18'} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + formidable@3.5.4: + resolution: {integrity: sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==} + engines: {node: '>=14.0.0'} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-monkey@1.1.0: + resolution: {integrity: sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function-timeout@1.0.2: + resolution: {integrity: sha512-939eZS4gJ3htTHAldmyyuzlrD58P03fHG49v2JfFXbV6OhvZKRC9j2yAtdHw/zrp2zXHuv05zMIy40F0ge7spA==} + engines: {node: '>=18'} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + engines: {node: '>=18'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} + + git-raw-commits@4.0.0: + resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} + engines: {node: '>=16'} + hasBin: true + + github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + + glob@13.0.6: + resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + engines: {node: 18 || 20 || >=22} + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + + global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@16.2.0: + resolution: {integrity: sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==} + engines: {node: '>=18'} + + globby@13.2.2: + resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + got@14.6.6: + resolution: {integrity: sha512-QLV1qeYSo5l13mQzWgP/y0LbMr5Plr5fJilgAIwgnwseproEbtNym8xpLsDzeZ6MWXgNE6kdWGBjdh3zT/Qerg==} + engines: {node: '>=20'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + handlebars@4.7.9: + resolution: {integrity: sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==} + engines: {node: '>=0.4.7'} + hasBin: true + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + helmet@8.1.0: + resolution: {integrity: sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==} + engines: {node: '>=18.0.0'} + + help-me@5.0.0: + resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + http-cache-semantics@4.2.0: + resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + http2-wrapper@2.2.1: + resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} + engines: {node: '>=10.19.0'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + human-signals@8.0.1: + resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} + engines: {node: '>=18.18.0'} + + husky@9.1.7: + resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} + engines: {node: '>=18'} + hasBin: true + + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} + hasBin: true + + import-meta-resolve@4.1.0: + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + inspect-with-kind@1.0.5: + resolution: {integrity: sha512-MAQUJuIo7Xqk8EVNP+6d3CKq9c80hi4tjIbIAT6lmGW9W6WzlHiu9PS8uSuUYU+Do+j1baiFp3H25XEVxDIG2g==} + + ioredis@5.6.1: + resolution: {integrity: sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==} + engines: {node: '>=12.22.0'} + + ipaddr.js@2.2.0: + resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} + engines: {node: '>= 10'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + + is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + + is-text-path@2.0.0: + resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} + engines: {node: '>=8'} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isexe@4.0.0: + resolution: {integrity: sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==} + engines: {node: '>=20'} + + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} + + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} + + iterare@1.2.1: + resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==} + engines: {node: '>=6'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jest-changed-files@30.3.0: + resolution: {integrity: sha512-B/7Cny6cV5At6M25EWDgf9S617lHivamL8vl6KEpJqkStauzcG4e+WPfDgMMF+H4FVH4A2PLRyvgDJan4441QA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-circus@30.3.0: + resolution: {integrity: sha512-PyXq5szeSfR/4f1lYqCmmQjh0vqDkURUYi9N6whnHjlRz4IUQfMcXkGLeEoiJtxtyPqgUaUUfyQlApXWBSN1RA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-cli@30.3.0: + resolution: {integrity: sha512-l6Tqx+j1fDXJEW5bqYykDQQ7mQg+9mhWXtnj+tQZrTWYHyHoi6Be8HPumDSA+UiX2/2buEgjA58iJzdj146uCw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@30.3.0: + resolution: {integrity: sha512-WPMAkMAtNDY9P/oKObtsRG/6KTrhtgPJoBTmk20uDn4Uy6/3EJnnaZJre/FMT1KVRx8cve1r7/FlMIOfRVWL4w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@types/node': '*' + esbuild-register: '>=3.4.0' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + esbuild-register: + optional: true + ts-node: + optional: true + + jest-diff@30.3.0: + resolution: {integrity: sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-docblock@30.2.0: + resolution: {integrity: sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-each@30.3.0: + resolution: {integrity: sha512-V8eMndg/aZ+3LnCJgSm13IxS5XSBM22QSZc9BtPK8Dek6pm+hfUNfwBdvsB3d342bo1q7wnSkC38zjX259qZNA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-environment-node@30.3.0: + resolution: {integrity: sha512-4i6HItw/JSiJVsC5q0hnKIe/hbYfZLVG9YJ/0pU9Hz2n/9qZe3Rhn5s5CUZA5ORZlcdT/vmAXRMyONXJwPrmYQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-haste-map@30.3.0: + resolution: {integrity: sha512-mMi2oqG4KRU0R9QEtscl87JzMXfUhbKaFqOxmjb2CKcbHcUGFrJCBWHmnTiUqi6JcnzoBlO4rWfpdl2k/RfLCA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-leak-detector@30.3.0: + resolution: {integrity: sha512-cuKmUUGIjfXZAiGJ7TbEMx0bcqNdPPI6P1V+7aF+m/FUJqFDxkFR4JqkTu8ZOiU5AaX/x0hZ20KaaIPXQzbMGQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-matcher-utils@30.3.0: + resolution: {integrity: sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-message-util@30.3.0: + resolution: {integrity: sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-mock@30.3.0: + resolution: {integrity: sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@30.0.1: + resolution: {integrity: sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-resolve-dependencies@30.3.0: + resolution: {integrity: sha512-9ev8s3YN6Hsyz9LV75XUwkCVFlwPbaFn6Wp75qnI0wzAINYWY8Fb3+6y59Rwd3QaS3kKXffHXsZMziMavfz/nw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-resolve@30.3.0: + resolution: {integrity: sha512-NRtTAHQlpd15F9rUR36jqwelbrDV/dY4vzNte3S2kxCKUJRYNd5/6nTSbYiak1VX5g8IoFF23Uj5TURkUW8O5g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-runner@30.3.0: + resolution: {integrity: sha512-gDv6C9LGKWDPLia9TSzZwf4h3kMQCqyTpq+95PODnTRDO0g9os48XIYYkS6D236vjpBir2fF63YmJFtqkS5Duw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-runtime@30.3.0: + resolution: {integrity: sha512-CgC+hIBJbuh78HEffkhNKcbXAytQViplcl8xupqeIWyKQF50kCQA8J7GeJCkjisC6hpnC9Muf8jV5RdtdFbGng==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-snapshot@30.3.0: + resolution: {integrity: sha512-f14c7atpb4O2DeNhwcvS810Y63wEn8O1HqK/luJ4F6M4NjvxmAKQwBUWjbExUtMxWJQ0wVgmCKymeJK6NZMnfQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-util@30.3.0: + resolution: {integrity: sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-validate@30.3.0: + resolution: {integrity: sha512-I/xzC8h5G+SHCb2P2gWkJYrNiTbeL47KvKeW5EzplkyxzBRBw1ssSHlI/jXec0ukH2q7x2zAWQm7015iusg62Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-watcher@30.3.0: + resolution: {integrity: sha512-PJ1d9ThtTR8aMiBWUdcownq9mDdLXsQzJayTk4kmaBRHKvwNQn+ANveuhEBUyNI2hR1TVhvQ8D5kHubbzBHR/w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + + jest-worker@30.3.0: + resolution: {integrity: sha512-DrCKkaQwHexjRUFTmPzs7sHQe0TSj9nvDALKGdwmK5mW9v7j90BudWirKAJHt3QQ9Dhrg1F7DogPzhChppkJpQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest@30.3.0: + resolution: {integrity: sha512-AkXIIFcaazymvey2i/+F94XRnM6TsVLZDhBMLsd1Sf/W0wzsvvpjeyUrCZD6HGG4SDYPgDJDBKeiJTBb10WzMg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + + js-tokens@10.0.0: + resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.2: + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-ref-resolver@2.0.1: + resolution: {integrity: sha512-HG0SIB9X4J8bwbxCbnd5FfPEbcXAJYTi1pBJeP/QPON+w8ovSME8iRG+ElHNxZNX2Qh6eYn1GdzJFS4cDFfx0Q==} + + json-schema-resolver@3.0.0: + resolution: {integrity: sha512-HqMnbz0tz2DaEJ3ntsqtx3ezzZyDE7G56A/pPY/NGmrPu76UzsWquOpHFRAf5beTNXoH2LU5cQePVvRli1nchA==} + engines: {node: '>=20'} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + + jsonfile@6.2.1: + resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} + + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + + jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} + + junk@4.0.1: + resolution: {integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==} + engines: {node: '>=12.20'} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + keyv@5.6.0: + resolution: {integrity: sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + leven@4.0.0: + resolution: {integrity: sha512-puehA3YKku3osqPlNuzGDUHq8WpwXupUg1V6NXdV38G+gr+gkBwFC8g1b/+YcIvp8gnqVIus+eJCH/eGsRmJNw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + light-my-request@6.6.0: + resolution: {integrity: sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==} + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lint-staged@15.5.2: + resolution: {integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==} + engines: {node: '>=18.12.0'} + hasBin: true + + listr2@8.3.3: + resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==} + engines: {node: '>=18.0.0'} + + load-esm@1.0.3: + resolution: {integrity: sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA==} + engines: {node: '>=13.2.0'} + + load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + loader-runner@4.3.2: + resolution: {integrity: sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==} + engines: {node: '>=6.11.5'} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + + lodash.isarguments@3.1.0: + resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.kebabcase@4.1.1: + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + + lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + + lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + + lodash.upperfirst@4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + + lowercase-keys@3.0.0: + resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.3.5: + resolution: {integrity: sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + luxon@3.7.2: + resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} + engines: {node: '>=12'} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + magicast@0.5.2: + resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} + + make-asynchronous@1.1.0: + resolution: {integrity: sha512-ayF7iT+44LXdxJLTrTd3TLQpFDDvPCBxXxbv+pMUSuHA5Q8zyAfwkRP6aHHwNVFBUFWtxAHqwNJxF8vMZLAbVg==} + engines: {node: '>=18'} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + memfs@3.5.3: + resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} + engines: {node: '>= 4.0.0'} + + meow@12.1.1: + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} + engines: {node: '>=16.10'} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@2.6.0: + resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} + engines: {node: '>=4.0.0'} + hasBin: true + + mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + mimic-response@4.0.0: + resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mute-stream@2.0.0: + resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} + engines: {node: ^18.17.0 || >=20.5.0} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@5.1.5: + resolution: {integrity: sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==} + engines: {node: ^18 || >=20} + hasBin: true + + nanoid@5.1.9: + resolution: {integrity: sha512-ZUvP7KeBLe3OZ1ypw6dI/TzYJuvHP77IM4Ry73waSQTLn8/g8rpdjfyVAh7t1/+FjBtG4lCP42MEbDxOsRpBMw==} + engines: {node: ^18 || >=20} + hasBin: true + + napi-postinstall@0.3.4: + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + nested-error-stacks@2.1.1: + resolution: {integrity: sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==} + + nestjs-pino@4.6.1: + resolution: {integrity: sha512-nuARXa0xpdJ1lY2+fgycIQr6H3g0VgqAWNK3xMYjOFcj2DoPETNXj0lV3Y86nRuI7BUfQp5PGiVoZvT4dTWbpQ==} + engines: {node: '>= 14'} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 + pino: ^7.5.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 + pino-http: ^6.4.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 + rxjs: ^7.1.0 + + nestjs-zod@5.3.0: + resolution: {integrity: sha512-QY6imXm9heMOpWigjFHgMWPvc1ZQHeNQ7pdogo9Q5xj5F8HpqZ972vKlVdkaTyzYlOXJP/yVy3wlF1EjubDQPg==} + peerDependencies: + '@nestjs/common': ^10.0.0 || ^11.0.0 + '@nestjs/swagger': ^7.4.2 || ^8.0.0 || ^11.0.0 + rxjs: ^7.0.0 + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + '@nestjs/swagger': + optional: true + + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + + node-abort-controller@3.1.1: + resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} + + node-emoji@1.11.0: + resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} + + node-html-markdown@2.0.0: + resolution: {integrity: sha512-DqUC3GGP7pwSYxS93SwHoP+qCw78xcMP6C6H2DuC8rPD2AweJRjBzQb5SdXpKtDlqAQ7hVotJcfhgU7hU5Gthw==} + engines: {node: '>=20.0.0'} + + node-html-parser@6.1.13: + resolution: {integrity: sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==} + + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-object-hash@3.1.1: + resolution: {integrity: sha512-A32kRGjXtwQ+uSa3GrXiCl8HVFY0Jy6IiKFO7UjagAKSaOOrruxB2Qf/w7TP5QtNfB3uOiHTu3cjhp8k/C0PCg==} + engines: {node: '>=16', pnpm: '>=8'} + + node-releases@2.0.38: + resolution: {integrity: sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-url@8.1.1: + resolution: {integrity: sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==} + engines: {node: '>=14.16'} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + npm-run-path@6.0.0: + resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} + engines: {node: '>=18'} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + openapi-types@12.1.3: + resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + + p-cancelable@4.0.1: + resolution: {integrity: sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==} + engines: {node: '>=14.16'} + + p-event@5.0.1: + resolution: {integrity: sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-event@6.0.1: + resolution: {integrity: sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w==} + engines: {node: '>=16.17'} + + p-filter@3.0.0: + resolution: {integrity: sha512-QtoWLjXAW++uTX67HZQz1dbTpqBfiidsB6VtQUC9iR85S120+s0T5sO6s+B5MLzFcZkrEd/DGMmCjR+f2Qpxwg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-map@5.5.0: + resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==} + engines: {node: '>=12'} + + p-map@6.0.0: + resolution: {integrity: sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==} + engines: {node: '>=16'} + + p-timeout@5.1.0: + resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==} + engines: {node: '>=12'} + + p-timeout@6.1.4: + resolution: {integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==} + engines: {node: '>=14.16'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + + pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + + path-to-regexp@8.4.2: + resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + + pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-abstract-transport@3.0.0: + resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==} + + pino-http@11.0.0: + resolution: {integrity: sha512-wqg5XIAGRRIWtTk8qPGxkbrfiwEWz1lgedVLvhLALudKXvg1/L2lTFgTGPJ4Z2e3qcRmxoFxDuSdMdMGNM6I1g==} + + pino-pretty@13.0.0: + resolution: {integrity: sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==} + hasBin: true + + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + + pino@10.3.1: + resolution: {integrity: sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==} + hasBin: true + + pino@9.7.0: + resolution: {integrity: sha512-vnMCM6xZTb1WDmLvtG2lE/2p+t9hDEIvTWJsu6FejkE62vB7gDhvzrpFR4Cw2to+9JNQxVnkAKVPA1KPB98vWg==} + hasBin: true + + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + piscina@4.9.2: + resolution: {integrity: sha512-Fq0FERJWFEUpB4eSY59wSNwXD4RYqR+nR/WiEVcZW8IWfVBxJJafcgTEZDQo8k3w0sUarJ8RyVbbUF4GQ2LGbQ==} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + postcss@8.5.10: + resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==} + engines: {node: ^10 || ^12 || >=14} + + postgres@3.4.7: + resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==} + engines: {node: '>=12'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + + prettier@3.5.3: + resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@30.3.0: + resolution: {integrity: sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + pretty-ms@9.3.0: + resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} + engines: {node: '>=18'} + + process-warning@4.0.1: + resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==} + + process-warning@5.0.0: + resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + pure-rand@7.0.1: + resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} + + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + + qs@6.15.1: + resolution: {integrity: sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==} + engines: {node: '>=0.6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + + redis-errors@1.2.0: + resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} + engines: {node: '>=4'} + + redis-parser@3.0.0: + resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} + engines: {node: '>=4'} + + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve-tspaths@0.8.23: + resolution: {integrity: sha512-VMZPjXnYLHnNHXOmJ9Unkkls08zDc+0LSBUo8Rp+SKzRt8rfD9dMpBudQJ5PNG8Szex/fnwdNKzd7rqipIH/zg==} + hasBin: true + peerDependencies: + typescript: '>=3.0.3' - cpy-cli@5.0.0: - resolution: {integrity: sha512-fb+DZYbL9KHc0BC4NYqGRrDIJZPXUmjjtqdw4XRRg8iV8dIfghUX/WiL+q4/B/KFTy3sK6jsbUhBaz0/Hxg7IQ==} - engines: {node: '>=16'} + responselike@4.0.2: + resolution: {integrity: sha512-cGk8IbWEAnaCpdAt1BHzJ3Ahz5ewDJa0KseTsE3qIRMJ3C698W8psM7byCeWVpd/Ha7FUYzuRVzXoKoM6nRUbA==} + engines: {node: '>=20'} + + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + ret@0.5.0: + resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==} + engines: {node: '>=10'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rimraf@6.1.3: + resolution: {integrity: sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==} + engines: {node: 20 || >=22} hasBin: true - cpy@10.1.0: - resolution: {integrity: sha512-VC2Gs20JcTyeQob6UViBLnyP0bYHkBh6EiKzot9vi2DmeGlFT9Wd7VG3NBrkNx/jYvFBeyDOMMHdHQhbtKLgHQ==} - engines: {node: '>=16'} + rolldown@1.0.0-rc.17: + resolution: {integrity: sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true - croner@8.1.2: - resolution: {integrity: sha512-ypfPFcAXHuAZRCzo3vJL6ltENzniTjwe/qsLleH1V2/7SRDjgvRQyrLmumFTLmjFax4IuSxfGXEn79fozXcJog==} - engines: {node: '>=18.0'} + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex2@5.0.0: + resolution: {integrity: sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw==} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} + engines: {node: '>= 10.13.0'} + + schema-utils@4.3.3: + resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} + engines: {node: '>= 10.13.0'} + + secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + + secure-json-parse@4.0.0: + resolution: {integrity: sha512-dxtLJO6sc35jWidmLxo7ij+Eg48PM/kleBsxpC8QJE0qJICe+KawkDQmvCMZUr9u7WKVHgMW6vy3fQ7zMiFZMA==} + + seek-bzip@2.0.0: + resolution: {integrity: sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg==} + hasBin: true + + semver-regex@4.0.5: + resolution: {integrity: sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==} + engines: {node: '>=12'} + + semver-truncate@3.0.0: + resolution: {integrity: sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg==} + engines: {node: '>=12'} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + set-cookie-parser@2.7.1: + resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + + sonic-boom@4.2.0: + resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} + + sort-keys-length@1.0.1: + resolution: {integrity: sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==} + engines: {node: '>=0.10.0'} + + sort-keys@1.1.2: + resolution: {integrity: sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==} + engines: {node: '>=0.10.0'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} - css-select@5.2.2: - resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} - css-what@6.2.2: - resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} - engines: {node: '>= 6'} + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} - dargs@8.1.0: - resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + standard-as-callback@2.1.0: + resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + std-env@4.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} + + streamx@2.25.0: + resolution: {integrity: sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} - dateformat@4.6.3: - resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} - debug@4.4.1: - resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} - engines: {node: '>=6.0'} + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + + strip-dirs@3.0.0: + resolution: {integrity: sha512-I0sdgcFTfKQlUPZyAqPJmSG3HLO9rWDFnxonnIbskYNM3DwFOeTNB5KzVq3dA1GdRAc/25b5Y7UO2TQfKWw4aQ==} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-final-newline@4.0.0: + resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} + engines: {node: '>=18'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strtok3@10.3.5: + resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==} + engines: {node: '>=18'} + + super-regex@1.1.0: + resolution: {integrity: sha512-WHkws2ZflZe41zj6AolvvmaTrWds/VuyeYr9iPVv/oQeaIoVxMKaushfFWpOGDT+GuBrM/sVqF8KUCYQlSSTdQ==} + engines: {node: '>=18'} + + superagent@10.3.0: + resolution: {integrity: sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==} + engines: {node: '>=14.18.0'} + + supertest@7.2.2: + resolution: {integrity: sha512-oK8WG9diS3DlhdUkcFn4tkNIiIbBx9lI2ClF8K+b2/m8Eyv47LSawxUzZQSNKUrVb2KsqeTDCcjAAVPYaSLVTA==} + engines: {node: '>=14.18.0'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + swagger-ui-dist@5.32.4: + resolution: {integrity: sha512-0AADFFQNJzExEN49SrD/34Nn9cxNxVLiydYl2MBwSZFPVXNkVwC/EFAjoezGGqE8oDegiDC+p47t8lKObCinMQ==} + + symbol-observable@4.0.0: + resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} + engines: {node: '>=0.10'} + + synckit@0.11.8: + resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==} + engines: {node: ^14.18.0 || >=16.0.0} + + tagged-tag@1.0.0: + resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} + engines: {node: '>=20'} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + + tar-stream@3.1.7: + resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} + + temporal-polyfill@0.3.2: + resolution: {integrity: sha512-TzHthD/heRK947GNiSu3Y5gSPpeUDH34+LESnfsq8bqpFhsB79HFBX8+Z834IVX68P3EUyRPZK5bL/1fh437Eg==} + + temporal-spec@0.3.1: + resolution: {integrity: sha512-B4TUhezh9knfSIMwt7RVggApDRJZo73uZdj8AacL2mZ8RP5KtLianh2MXxL06GN9ESYiIsiuoLQhgVfwe55Yhw==} + + terser-webpack-plugin@5.5.0: + resolution: {integrity: sha512-UYhptBwhWvfIjKd/UuFo6D8uq9xpGLDK+z8EDsj/zWhrTaH34cKEbrkMKfV5YWqGBvAYA3tlzZbs2R+qYrbQJA==} + engines: {node: '>= 10.13.0'} peerDependencies: - supports-color: '*' + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 peerDependenciesMeta: - supports-color: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: optional: true - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + terser@5.46.2: + resolution: {integrity: sha512-uxfo9fPcSgLDYob/w1FuL0c99MWiJDnv+5qXSQc5+Ki5NjVNsYi66INnMFBjf6uFz6OnX12piJQPF4IpjJTNTw==} + engines: {node: '>=10'} + hasBin: true + + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + + text-decoder@1.2.7: + resolution: {integrity: sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==} + + text-extensions@2.4.0: + resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} + engines: {node: '>=8'} + + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + + thread-stream@4.0.0: + resolution: {integrity: sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==} + engines: {node: '>=20'} + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + time-span@5.1.0: + resolution: {integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==} + engines: {node: '>=12'} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.0.1: + resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} + + tinyexec@1.1.1: + resolution: {integrity: sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==} + engines: {node: '>=18'} - denque@2.1.0: - resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} - engines: {node: '>=0.10'} + tinyglobby@0.2.16: + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + engines: {node: '>=12.0.0'} - dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} - domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + toad-cache@3.7.0: + resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} + engines: {node: '>=12'} - domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} + toad-scheduler@3.1.0: + resolution: {integrity: sha512-ZTwsGMWyKTOokgTmIvjPIvkT3ZiPFgkAi8L0OLONOcSc/BUDPRzNMOfVWZzugIAxyntvY0Nzy1etNk+31Q4FXQ==} - domutils@3.2.2: - resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} - dot-prop@5.3.0: - resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} - engines: {node: '>=8'} + token-types@6.1.2: + resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} + engines: {node: '>=14.16'} - dotenv@16.5.0: - resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} - engines: {node: '>=12'} + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' - drizzle-kit@1.0.0-beta.1-c0277c0: - resolution: {integrity: sha512-8oRt69AyPA1ONsI1/2nZCJGkp9egyQOOe/uBuNB8yxcWxIMCDI60OF4rLHUaYfpHP4zuqJwiABFIBQUViPxXTw==} + ts-jest@29.4.9: + resolution: {integrity: sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==} + engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} hasBin: true - - drizzle-orm@1.0.0-beta.1-c0277c0: - resolution: {integrity: sha512-4XnmY3CdFHUzJpbRwc6mElkpDzyZs8Ko98i+cRuuPlakFgZqItr+inoK0bFTH50Eh66E/UXbxfAW6U0JK/1wyw==} peerDependencies: - '@aws-sdk/client-rds-data': '>=3' - '@cloudflare/workers-types': '>=4' - '@electric-sql/pglite': '>=0.2.0' - '@libsql/client': '>=0.10.0' - '@libsql/client-wasm': '>=0.10.0' - '@neondatabase/serverless': '>=0.10.0' - '@op-engineering/op-sqlite': '>=2' - '@opentelemetry/api': ^1.4.1 - '@planetscale/database': '>=1.13' - '@prisma/client': '*' - '@tidbcloud/serverless': '*' - '@types/better-sqlite3': '*' - '@types/pg': '*' - '@types/sql.js': '*' - '@vercel/postgres': '>=0.8.0' - '@xata.io/client': '*' - better-sqlite3: '>=9.3.0' - bun-types: '*' - expo-sqlite: '>=14.0.0' - gel: '>=2' - knex: '*' - kysely: '*' - mysql2: '>=2' - pg: '>=8' - postgres: '>=3' - prisma: '*' - sql.js: '>=1' - sqlite3: '>=5' + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/transform': ^29.0.0 || ^30.0.0 + '@jest/types': ^29.0.0 || ^30.0.0 + babel-jest: ^29.0.0 || ^30.0.0 + esbuild: '*' + jest: ^29.0.0 || ^30.0.0 + jest-util: ^29.0.0 || ^30.0.0 + typescript: '>=4.3 <7' peerDependenciesMeta: - '@aws-sdk/client-rds-data': - optional: true - '@cloudflare/workers-types': - optional: true - '@electric-sql/pglite': - optional: true - '@libsql/client': - optional: true - '@libsql/client-wasm': - optional: true - '@neondatabase/serverless': - optional: true - '@op-engineering/op-sqlite': - optional: true - '@opentelemetry/api': - optional: true - '@planetscale/database': - optional: true - '@prisma/client': - optional: true - '@tidbcloud/serverless': - optional: true - '@types/better-sqlite3': - optional: true - '@types/pg': - optional: true - '@types/sql.js': - optional: true - '@vercel/postgres': - optional: true - '@xata.io/client': - optional: true - better-sqlite3: - optional: true - bun-types: - optional: true - expo-sqlite: - optional: true - gel: - optional: true - knex: + '@babel/core': optional: true - kysely: + '@jest/transform': optional: true - mysql2: + '@jest/types': optional: true - pg: + babel-jest: optional: true - postgres: + esbuild: optional: true - prisma: + jest-util: optional: true - sql.js: + + ts-loader@9.5.7: + resolution: {integrity: sha512-/ZNrKgA3K3PtpMYOC71EeMWIloGw3IYEa5/t1cyz2r5/PyUwTXGzYJvcD3kfUvmhlfpz1rhV8B2O6IVTQ0avsg==} + engines: {node: '>=12.0.0'} + peerDependencies: + typescript: '*' + webpack: ^5.0.0 + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': optional: true - sqlite3: + '@swc/wasm': optional: true - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} + tsconfig-paths-webpack-plugin@4.2.0: + resolution: {integrity: sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==} + engines: {node: '>=10.13.0'} - emoji-regex@10.4.0: - resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - end-of-stream@1.4.4: - resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + tsx@4.19.4: + resolution: {integrity: sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==} + engines: {node: '>=18.0.0'} + hasBin: true - entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} - env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} - environment@1.1.0: - resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} - engines: {node: '>=18'} + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} + type-fest@5.6.0: + resolution: {integrity: sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA==} + engines: {node: '>=20'} - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} + typescript-eslint@8.33.1: + resolution: {integrity: sha512-AgRnV4sKkWOiZ0Kjbnf5ytTJXMUZQ0qhSVdQtDNYLPLnjsATEYhaO94GlRQwi4t4gO8FfjM6NnikHeKjUm8D7A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true - esbuild-register@3.6.0: - resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} - peerDependencies: - esbuild: '>=0.12 <1' + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true - esbuild@0.18.20: - resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} - engines: {node: '>=12'} + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} hasBin: true - esbuild@0.25.5: - resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==} + uid@2.0.2: + resolution: {integrity: sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==} + engines: {node: '>=8'} + + uint8array-extras@1.5.0: + resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} engines: {node: '>=18'} - hasBin: true - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} + unbzip2-stream@1.4.3: + resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - escape-string-regexp@5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} + unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} - eslint-config-prettier@10.1.5: - resolution: {integrity: sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==} + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unplugin-swc@1.5.9: + resolution: {integrity: sha512-RKwK3yf0M+MN17xZfF14bdKqfx0zMXYdtOdxLiE6jHAoidupKq3jGdJYANyIM1X/VmABhh1WpdO+/f4+Ol89+g==} + peerDependencies: + '@swc/core': ^1.2.108 + + unplugin@2.3.11: + resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} + engines: {node: '>=18.12.0'} + + unrs-resolver@1.11.1: + resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true peerDependencies: - eslint: '>=7.0.0' + browserslist: '>= 4.21.0' - eslint-plugin-prettier@5.4.1: - resolution: {integrity: sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg==} - engines: {node: ^14.18.0 || >=16.0.0} + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} + + vite@8.0.10: + resolution: {integrity: sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true peerDependencies: - '@types/eslint': '>=8.0.0' - eslint: '>=8.0.0' - eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0' - prettier: '>=3.0.0' + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.1.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 peerDependenciesMeta: - '@types/eslint': + '@types/node': optional: true - eslint-config-prettier: + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: optional: true - eslint-scope@8.3.0: - resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - 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} - - eslint-visitor-keys@4.2.0: - resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint@9.28.0: - resolution: {integrity: sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + vitest@4.1.5: + resolution: {integrity: sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: - jiti: '*' + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.5 + '@vitest/browser-preview': 4.1.5 + '@vitest/browser-webdriverio': 4.1.5 + '@vitest/coverage-istanbul': 4.1.5 + '@vitest/coverage-v8': 4.1.5 + '@vitest/ui': 4.1.5 + happy-dom: '*' + jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: - jiti: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: optional: true - espree@10.3.0: - resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} + watchpack@2.5.1: + resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==} + engines: {node: '>=10.13.0'} - eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} + web-worker@1.5.0: + resolution: {integrity: sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==} - fast-copy@3.0.2: - resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} + webpack-node-externals@3.0.0: + resolution: {integrity: sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==} + engines: {node: '>=6'} - fast-decode-uri-component@1.0.1: - resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} + webpack-sources@3.4.0: + resolution: {integrity: sha512-gHwIe1cgBvvfLeu1Yz/dcFpmHfKDVxxyqI+kzqmuxZED81z2ChxpyqPaWcNqigPywhaEke7AjSGga+kxY55gjQ==} + engines: {node: '>=10.13.0'} - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} - fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + webpack@5.106.0: + resolution: {integrity: sha512-Pkx5joZ9RrdgO5LBkyX1L2ZAJeK/Taz3vqZ9CbcP0wS5LEMx5QkKsEwLl29QJfihZ+DKRBFldzy1O30pJ1MDpA==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true - fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true - fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} - fast-json-stringify@6.0.1: - resolution: {integrity: sha512-s7SJE83QKBZwg54dIbD5rCtzOBVD43V1ReWXXYqBgwCwHLYAAT0RQc/FmrQglXqWPpz6omtryJQOau5jI4Nrvg==} + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} - fast-querystring@1.1.2: - resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} - fast-redact@3.5.0: - resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} - engines: {node: '>=6'} + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} - fast-safe-stringify@2.1.1: - resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} - fast-uri@3.0.6: - resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - fastify-plugin@4.5.1: - resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==} + write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - fastify-plugin@5.0.1: - resolution: {integrity: sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ==} + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} - fastify-type-provider-zod@5.0.2: - resolution: {integrity: sha512-myolKCxze2rx25Ia88Erb4TZpFIUWyCUqMDgNqE6KQnXoERXwMCPuwfj/1zKkVBlu5dvLo1c/H7GneZUhOWXiw==} - peerDependencies: - '@fastify/swagger': '>=9.5.1' - fastify: ^5.0.0 - zod: '>=3.25.67' + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - fastify@5.3.3: - resolution: {integrity: sha512-nCBiBCw9q6jPx+JJNVgO8JVnTXeUyrGcyTKPQikRkA/PanrFcOIo4R+ZnLeOLPZPGgzjomqfVarzE0kYx7qWiQ==} + yaml@2.8.0: + resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==} + engines: {node: '>= 14.6'} + hasBin: true - fastq@1.19.1: - resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} + yauzl@3.3.0: + resolution: {integrity: sha512-PtGEvEP30p7sbIBJKUBjUnqgTVOyMURc4dLo9iNyAJnNIEz9pm88cCXF21w94Kg3k6RXkeZh5DHOGS0qEONvNQ==} + engines: {node: '>=12'} - find-my-way@9.3.0: - resolution: {integrity: sha512-eRoFWQw+Yv2tuYlK2pjFS2jGXSxSppAs3hSQjfxVKxM5amECzIgYYc1FEI8ZmhSh/Ig+FrKEz43NLRKJjYCZVg==} - engines: {node: '>=20'} + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - find-up@7.0.0: - resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} - engines: {node: '>=18'} - - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - - flatted@3.3.3: - resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + yocto-queue@1.2.1: + resolution: {integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==} + engines: {node: '>=12.20'} - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} + yoctocolors-cjs@2.1.3: + resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} + engines: {node: '>=18'} - get-east-asian-width@1.3.0: - resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + yoctocolors@2.1.2: + resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} engines: {node: '>=18'} - get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} + zod@3.24.1: + resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} + zod@4.0.10: + resolution: {integrity: sha512-3vB+UU3/VmLL2lvwcY/4RV2i9z/YU0DTV/tDuYjrwmx5WeJ7hwy+rGEEx8glHp6Yxw7ibRbKSaIFBgReRPe5KA==} - get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} - get-tsconfig@4.10.1: - resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} +snapshots: - git-raw-commits@4.0.0: - resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} - engines: {node: '>=16'} - hasBin: true + '@angular-devkit/core@19.2.24(chokidar@4.0.3)': + dependencies: + ajv: 8.18.0 + ajv-formats: 3.0.1(ajv@8.18.0) + jsonc-parser: 3.3.1 + picomatch: 4.0.4 + rxjs: 7.8.1 + source-map: 0.7.4 + optionalDependencies: + chokidar: 4.0.3 - github-slugger@2.0.0: - resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + '@angular-devkit/schematics-cli@19.2.24(@types/node@22.15.29)(chokidar@4.0.3)': + dependencies: + '@angular-devkit/core': 19.2.24(chokidar@4.0.3) + '@angular-devkit/schematics': 19.2.24(chokidar@4.0.3) + '@inquirer/prompts': 7.3.2(@types/node@22.15.29) + ansi-colors: 4.1.3 + symbol-observable: 4.0.0 + yargs-parser: 21.1.1 + transitivePeerDependencies: + - '@types/node' + - chokidar - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + '@angular-devkit/schematics@19.2.24(chokidar@4.0.3)': + dependencies: + '@angular-devkit/core': 19.2.24(chokidar@4.0.3) + jsonc-parser: 3.3.1 + magic-string: 0.30.17 + ora: 5.4.1 + rxjs: 7.8.1 + transitivePeerDependencies: + - chokidar - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 - global-directory@4.0.1: - resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} - engines: {node: '>=18'} + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 - globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} + '@babel/compat-data@7.29.0': {} + + '@babel/core@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helpers': 7.29.2 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color - globals@16.2.0: - resolution: {integrity: sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==} - engines: {node: '>=18'} + '@babel/generator@7.29.1': + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 - globby@13.2.2: - resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + '@babel/helper-compilation-targets@7.28.6': + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.2 + lru-cache: 5.1.1 + semver: 6.3.1 - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} + '@babel/helper-globals@7.28.0': {} - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + '@babel/helper-module-imports@7.28.6': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} + '@babel/helper-plugin-utils@7.28.6': {} - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} + '@babel/helper-string-parser@7.27.1': {} - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} + '@babel/helper-validator-identifier@7.27.1': {} - he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true + '@babel/helper-validator-identifier@7.28.5': {} - helmet@8.1.0: - resolution: {integrity: sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==} - engines: {node: '>=18.0.0'} + '@babel/helper-validator-option@7.27.1': {} - help-me@5.0.0: - resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + '@babel/helpers@7.29.2': + dependencies: + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 - human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} + '@babel/parser@7.29.2': + dependencies: + '@babel/types': 7.29.0 - husky@9.1.7: - resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} - engines: {node: '>=18'} - hasBin: true + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - ignore@7.0.5: - resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} - engines: {node: '>= 4'} + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - import-fresh@3.3.1: - resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} - engines: {node: '>=6'} + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - import-meta-resolve@4.1.0: - resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - indent-string@5.0.0: - resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} - engines: {node: '>=12'} + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - ini@4.1.1: - resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - ioredis@5.6.1: - resolution: {integrity: sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==} - engines: {node: '>=12.22.0'} + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - ipaddr.js@2.2.0: - resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} - engines: {node: '>= 10'} + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - is-fullwidth-code-point@4.0.0: - resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} - engines: {node: '>=12'} + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - is-fullwidth-code-point@5.0.0: - resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} - engines: {node: '>=18'} + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} + '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - is-obj@2.0.0: - resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} - engines: {node: '>=8'} + '@babel/template@7.28.6': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + '@babel/traverse@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color - is-text-path@2.0.0: - resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} - engines: {node: '>=8'} + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + '@bcoe/v8-coverage@0.2.3': {} - jiti@2.4.2: - resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} - hasBin: true + '@bcoe/v8-coverage@1.0.2': {} - joycon@3.1.1: - resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} - engines: {node: '>=10'} + '@borewit/text-codec@0.2.2': {} - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + '@clack/core@0.5.0': + dependencies: + picocolors: 1.1.1 + sisteransi: 1.0.5 - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true + '@clack/prompts@0.11.0': + dependencies: + '@clack/core': 0.5.0 + picocolors: 1.1.1 + sisteransi: 1.0.5 - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + '@colors/colors@1.5.0': + optional: true - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + '@commitlint/cli@19.8.1(@types/node@22.15.29)(typescript@5.8.3)': + dependencies: + '@commitlint/format': 19.8.1 + '@commitlint/lint': 19.8.1 + '@commitlint/load': 19.8.1(@types/node@22.15.29)(typescript@5.8.3) + '@commitlint/read': 19.8.1 + '@commitlint/types': 19.8.1 + tinyexec: 1.0.1 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - typescript - json-schema-ref-resolver@2.0.1: - resolution: {integrity: sha512-HG0SIB9X4J8bwbxCbnd5FfPEbcXAJYTi1pBJeP/QPON+w8ovSME8iRG+ElHNxZNX2Qh6eYn1GdzJFS4cDFfx0Q==} + '@commitlint/config-conventional@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + conventional-changelog-conventionalcommits: 7.0.2 - json-schema-resolver@3.0.0: - resolution: {integrity: sha512-HqMnbz0tz2DaEJ3ntsqtx3ezzZyDE7G56A/pPY/NGmrPu76UzsWquOpHFRAf5beTNXoH2LU5cQePVvRli1nchA==} - engines: {node: '>=20'} + '@commitlint/config-validator@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + ajv: 8.17.1 - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + '@commitlint/ensure@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + lodash.camelcase: 4.3.0 + lodash.kebabcase: 4.1.1 + lodash.snakecase: 4.1.1 + lodash.startcase: 4.4.0 + lodash.upperfirst: 4.3.1 - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + '@commitlint/execute-rule@19.8.1': {} - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + '@commitlint/format@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + chalk: 5.4.1 - jsonparse@1.3.1: - resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} - engines: {'0': node >= 0.2.0} + '@commitlint/is-ignored@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + semver: 7.7.2 - jsonpointer@5.0.1: - resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} - engines: {node: '>=0.10.0'} + '@commitlint/lint@19.8.1': + dependencies: + '@commitlint/is-ignored': 19.8.1 + '@commitlint/parse': 19.8.1 + '@commitlint/rules': 19.8.1 + '@commitlint/types': 19.8.1 - junk@4.0.1: - resolution: {integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==} - engines: {node: '>=12.20'} + '@commitlint/load@19.8.1(@types/node@22.15.29)(typescript@5.8.3)': + dependencies: + '@commitlint/config-validator': 19.8.1 + '@commitlint/execute-rule': 19.8.1 + '@commitlint/resolve-extends': 19.8.1 + '@commitlint/types': 19.8.1 + chalk: 5.4.1 + cosmiconfig: 9.0.0(typescript@5.8.3) + cosmiconfig-typescript-loader: 6.1.0(@types/node@22.15.29)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + transitivePeerDependencies: + - '@types/node' + - typescript - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + '@commitlint/message@19.8.1': {} - leven@4.0.0: - resolution: {integrity: sha512-puehA3YKku3osqPlNuzGDUHq8WpwXupUg1V6NXdV38G+gr+gkBwFC8g1b/+YcIvp8gnqVIus+eJCH/eGsRmJNw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + '@commitlint/parse@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + conventional-changelog-angular: 7.0.0 + conventional-commits-parser: 5.0.0 - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} + '@commitlint/read@19.8.1': + dependencies: + '@commitlint/top-level': 19.8.1 + '@commitlint/types': 19.8.1 + git-raw-commits: 4.0.0 + minimist: 1.2.8 + tinyexec: 1.0.1 - light-my-request@6.6.0: - resolution: {integrity: sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==} + '@commitlint/resolve-extends@19.8.1': + dependencies: + '@commitlint/config-validator': 19.8.1 + '@commitlint/types': 19.8.1 + global-directory: 4.0.1 + import-meta-resolve: 4.1.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 - lilconfig@3.1.3: - resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} - engines: {node: '>=14'} + '@commitlint/rules@19.8.1': + dependencies: + '@commitlint/ensure': 19.8.1 + '@commitlint/message': 19.8.1 + '@commitlint/to-lines': 19.8.1 + '@commitlint/types': 19.8.1 - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + '@commitlint/to-lines@19.8.1': {} - lint-staged@15.5.2: - resolution: {integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==} - engines: {node: '>=18.12.0'} - hasBin: true + '@commitlint/top-level@19.8.1': + dependencies: + find-up: 7.0.0 - listr2@8.3.3: - resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==} - engines: {node: '>=18.0.0'} + '@commitlint/types@19.8.1': + dependencies: + '@types/conventional-commits-parser': 5.0.1 + chalk: 5.4.1 - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 - locate-path@7.2.0: - resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + '@drizzle-team/brocli@0.10.2': {} - lodash.camelcase@4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + '@emnapi/core@1.10.0': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true - lodash.defaults@4.2.0: - resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 + optional: true - lodash.isarguments@3.1.0: - resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true - lodash.isplainobject@4.0.6: - resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + '@esbuild-kit/core-utils@3.3.2': + dependencies: + esbuild: 0.18.20 + source-map-support: 0.5.21 - lodash.kebabcase@4.1.1: - resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + '@esbuild-kit/esm-loader@2.6.5': + dependencies: + '@esbuild-kit/core-utils': 3.3.2 + get-tsconfig: 4.10.1 - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + '@esbuild/aix-ppc64@0.25.5': + optional: true - lodash.mergewith@4.6.2: - resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + '@esbuild/android-arm64@0.18.20': + optional: true - lodash.snakecase@4.1.1: - resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + '@esbuild/android-arm64@0.25.5': + optional: true - lodash.startcase@4.4.0: - resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + '@esbuild/android-arm@0.18.20': + optional: true - lodash.uniq@4.5.0: - resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + '@esbuild/android-arm@0.25.5': + optional: true - lodash.upperfirst@4.3.1: - resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + '@esbuild/android-x64@0.18.20': + optional: true - log-update@6.1.0: - resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} - engines: {node: '>=18'} + '@esbuild/android-x64@0.25.5': + optional: true - lower-case@2.0.2: - resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + '@esbuild/darwin-arm64@0.18.20': + optional: true - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} + '@esbuild/darwin-arm64@0.25.5': + optional: true - meow@12.1.1: - resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} - engines: {node: '>=16.10'} + '@esbuild/darwin-x64@0.18.20': + optional: true - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + '@esbuild/darwin-x64@0.25.5': + optional: true - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} + '@esbuild/freebsd-arm64@0.18.20': + optional: true - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} + '@esbuild/freebsd-arm64@0.25.5': + optional: true - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} + '@esbuild/freebsd-x64@0.18.20': + optional: true - mimic-function@5.0.1: - resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} - engines: {node: '>=18'} + '@esbuild/freebsd-x64@0.25.5': + optional: true - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + '@esbuild/linux-arm64@0.18.20': + optional: true - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} + '@esbuild/linux-arm64@0.25.5': + optional: true - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + '@esbuild/linux-arm@0.18.20': + optional: true - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + '@esbuild/linux-arm@0.25.5': + optional: true - nanoid@5.1.5: - resolution: {integrity: sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==} - engines: {node: ^18 || >=20} - hasBin: true + '@esbuild/linux-ia32@0.18.20': + optional: true - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + '@esbuild/linux-ia32@0.25.5': + optional: true - nested-error-stacks@2.1.1: - resolution: {integrity: sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==} + '@esbuild/linux-loong64@0.18.20': + optional: true - no-case@3.0.4: - resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + '@esbuild/linux-loong64@0.25.5': + optional: true - node-html-markdown@2.0.0: - resolution: {integrity: sha512-DqUC3GGP7pwSYxS93SwHoP+qCw78xcMP6C6H2DuC8rPD2AweJRjBzQb5SdXpKtDlqAQ7hVotJcfhgU7hU5Gthw==} - engines: {node: '>=20.0.0'} + '@esbuild/linux-mips64el@0.18.20': + optional: true - node-html-parser@6.1.13: - resolution: {integrity: sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==} + '@esbuild/linux-mips64el@0.25.5': + optional: true - node-object-hash@3.1.1: - resolution: {integrity: sha512-A32kRGjXtwQ+uSa3GrXiCl8HVFY0Jy6IiKFO7UjagAKSaOOrruxB2Qf/w7TP5QtNfB3uOiHTu3cjhp8k/C0PCg==} - engines: {node: '>=16', pnpm: '>=8'} + '@esbuild/linux-ppc64@0.18.20': + optional: true - npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + '@esbuild/linux-ppc64@0.25.5': + optional: true - nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + '@esbuild/linux-riscv64@0.18.20': + optional: true - object-inspect@1.13.4: - resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} - engines: {node: '>= 0.4'} + '@esbuild/linux-riscv64@0.25.5': + optional: true - on-exit-leak-free@2.1.2: - resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} - engines: {node: '>=14.0.0'} + '@esbuild/linux-s390x@0.18.20': + optional: true - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + '@esbuild/linux-s390x@0.25.5': + optional: true - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} + '@esbuild/linux-x64@0.18.20': + optional: true - onetime@7.0.0: - resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} - engines: {node: '>=18'} + '@esbuild/linux-x64@0.25.5': + optional: true - openapi-types@12.1.3: - resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + '@esbuild/netbsd-arm64@0.25.5': + optional: true - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} + '@esbuild/netbsd-x64@0.18.20': + optional: true - p-event@5.0.1: - resolution: {integrity: sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + '@esbuild/netbsd-x64@0.25.5': + optional: true - p-filter@3.0.0: - resolution: {integrity: sha512-QtoWLjXAW++uTX67HZQz1dbTpqBfiidsB6VtQUC9iR85S120+s0T5sO6s+B5MLzFcZkrEd/DGMmCjR+f2Qpxwg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + '@esbuild/openbsd-arm64@0.25.5': + optional: true - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} + '@esbuild/openbsd-x64@0.18.20': + optional: true - p-limit@4.0.0: - resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + '@esbuild/openbsd-x64@0.25.5': + optional: true - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} + '@esbuild/sunos-x64@0.18.20': + optional: true - p-locate@6.0.0: - resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + '@esbuild/sunos-x64@0.25.5': + optional: true - p-map@5.5.0: - resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==} - engines: {node: '>=12'} + '@esbuild/win32-arm64@0.18.20': + optional: true - p-map@6.0.0: - resolution: {integrity: sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==} - engines: {node: '>=16'} + '@esbuild/win32-arm64@0.25.5': + optional: true - p-timeout@5.1.0: - resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==} - engines: {node: '>=12'} + '@esbuild/win32-ia32@0.18.20': + optional: true - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} + '@esbuild/win32-ia32@0.25.5': + optional: true - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} + '@esbuild/win32-x64@0.18.20': + optional: true - pascal-case@3.1.2: - resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + '@esbuild/win32-x64@0.25.5': + optional: true - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} + '@eslint-community/eslint-utils@4.7.0(eslint@9.28.0(jiti@2.4.2))': + dependencies: + eslint: 9.28.0(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 - path-exists@5.0.0: - resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + '@eslint-community/regexpp@4.12.1': {} - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} + '@eslint/config-array@0.20.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.1 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} + '@eslint/config-helpers@0.2.2': {} - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} + '@eslint/core@0.14.0': + dependencies: + '@types/json-schema': 7.0.15 - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.1 + espree: 10.3.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} + '@eslint/js@9.28.0': {} - pidtree@0.6.0: - resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} - engines: {node: '>=0.10'} - hasBin: true + '@eslint/object-schema@2.1.6': {} - pino-abstract-transport@2.0.0: - resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + '@eslint/plugin-kit@0.3.1': + dependencies: + '@eslint/core': 0.14.0 + levn: 0.4.1 - pino-pretty@13.0.0: - resolution: {integrity: sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==} - hasBin: true + '@fastify/accept-negotiator@2.0.1': {} - pino-std-serializers@7.0.0: - resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + '@fastify/ajv-compiler@4.0.2': + dependencies: + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) + fast-uri: 3.0.6 - pino@9.7.0: - resolution: {integrity: sha512-vnMCM6xZTb1WDmLvtG2lE/2p+t9hDEIvTWJsu6FejkE62vB7gDhvzrpFR4Cw2to+9JNQxVnkAKVPA1KPB98vWg==} - hasBin: true + '@fastify/ajv-compiler@4.0.5': + dependencies: + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) + fast-uri: 3.0.6 - postgres@3.4.7: - resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==} - engines: {node: '>=12'} + '@fastify/awilix@7.0.0(awilix@12.0.5)(fastify@5.3.3)': + dependencies: + awilix: 12.0.5 + awilix-manager: 6.1.0(awilix@12.0.5) + fastify: 5.3.3 + fastify-plugin: 5.0.1 - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} + '@fastify/cookie@11.0.2': + dependencies: + cookie: 1.0.2 + fastify-plugin: 5.0.1 - prettier-linter-helpers@1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} - engines: {node: '>=6.0.0'} + '@fastify/cors@11.0.1': + dependencies: + fastify-plugin: 5.0.1 + toad-cache: 3.7.0 - prettier@3.5.3: - resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} - engines: {node: '>=14'} - hasBin: true + '@fastify/cors@11.2.0': + dependencies: + fastify-plugin: 5.1.0 + toad-cache: 3.7.0 - process-warning@4.0.1: - resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==} + '@fastify/error@4.2.0': {} - process-warning@5.0.0: - resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + '@fastify/fast-json-stringify-compiler@5.0.3': + dependencies: + fast-json-stringify: 6.0.1 - pump@3.0.2: - resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + '@fastify/formbody@8.0.2': + dependencies: + fast-querystring: 1.1.2 + fastify-plugin: 5.1.0 - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} + '@fastify/forwarded@3.0.0': {} - qs@6.14.0: - resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} - engines: {node: '>=0.6'} + '@fastify/helmet@13.0.1': + dependencies: + fastify-plugin: 5.0.1 + helmet: 8.1.0 - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + '@fastify/merge-json-schemas@0.2.1': + dependencies: + dequal: 2.0.3 - quick-format-unescaped@4.0.4: - resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + '@fastify/proxy-addr@5.0.0': + dependencies: + '@fastify/forwarded': 3.0.0 + ipaddr.js: 2.2.0 - real-require@0.2.0: - resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} - engines: {node: '>= 12.13.0'} + '@fastify/rate-limit@10.3.0': + dependencies: + '@lukeed/ms': 2.0.2 + fastify-plugin: 5.0.1 + toad-cache: 3.7.0 - redis-errors@1.2.0: - resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} - engines: {node: '>=4'} + '@fastify/schedule@6.0.0(toad-scheduler@3.1.0)': + dependencies: + fastify-plugin: 5.0.1 + toad-scheduler: 3.1.0 - redis-parser@3.0.0: - resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} - engines: {node: '>=4'} + '@fastify/send@4.1.0': + dependencies: + '@lukeed/ms': 2.0.2 + escape-html: 1.0.3 + fast-decode-uri-component: 1.0.1 + http-errors: 2.0.1 + mime: 3.0.0 - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} + '@fastify/static@9.1.3': + dependencies: + '@fastify/accept-negotiator': 2.0.1 + '@fastify/send': 4.1.0 + content-disposition: 1.1.0 + fastify-plugin: 5.1.0 + fastq: 1.19.1 + glob: 13.0.6 - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} + '@fastify/swagger@9.5.1': + dependencies: + fastify-plugin: 5.0.1 + json-schema-resolver: 3.0.0 + openapi-types: 12.1.3 + rfdc: 1.4.1 + yaml: 2.8.0 + transitivePeerDependencies: + - supports-color - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} + '@humanfs/core@0.19.1': {} - resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 - resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + '@humanwhocodes/module-importer@1.0.1': {} - resolve-tspaths@0.8.23: - resolution: {integrity: sha512-VMZPjXnYLHnNHXOmJ9Unkkls08zDc+0LSBUo8Rp+SKzRt8rfD9dMpBudQJ5PNG8Szex/fnwdNKzd7rqipIH/zg==} - hasBin: true - peerDependencies: - typescript: '>=3.0.3' + '@humanwhocodes/retry@0.3.1': {} - restore-cursor@5.1.0: - resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} - engines: {node: '>=18'} + '@humanwhocodes/retry@0.4.3': {} - ret@0.5.0: - resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==} - engines: {node: '>=10'} + '@inquirer/ansi@1.0.2': {} - reusify@1.1.0: - resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + '@inquirer/checkbox@4.3.2(@types/node@22.15.29)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.2(@types/node@22.15.29) + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@22.15.29) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 22.15.29 - rfdc@1.4.1: - resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + '@inquirer/confirm@5.1.21(@types/node@22.15.29)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@22.15.29) + '@inquirer/type': 3.0.10(@types/node@22.15.29) + optionalDependencies: + '@types/node': 22.15.29 - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + '@inquirer/core@10.3.2(@types/node@22.15.29)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@22.15.29) + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 22.15.29 - safe-regex2@5.0.0: - resolution: {integrity: sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw==} + '@inquirer/editor@4.2.23(@types/node@22.15.29)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@22.15.29) + '@inquirer/external-editor': 1.0.3(@types/node@22.15.29) + '@inquirer/type': 3.0.10(@types/node@22.15.29) + optionalDependencies: + '@types/node': 22.15.29 - safe-stable-stringify@2.5.0: - resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} - engines: {node: '>=10'} + '@inquirer/expand@4.0.23(@types/node@22.15.29)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@22.15.29) + '@inquirer/type': 3.0.10(@types/node@22.15.29) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 22.15.29 - secure-json-parse@2.7.0: - resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + '@inquirer/external-editor@1.0.3(@types/node@22.15.29)': + dependencies: + chardet: 2.1.1 + iconv-lite: 0.7.2 + optionalDependencies: + '@types/node': 22.15.29 - secure-json-parse@4.0.0: - resolution: {integrity: sha512-dxtLJO6sc35jWidmLxo7ij+Eg48PM/kleBsxpC8QJE0qJICe+KawkDQmvCMZUr9u7WKVHgMW6vy3fQ7zMiFZMA==} + '@inquirer/figures@1.0.15': {} - semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} - engines: {node: '>=10'} - hasBin: true + '@inquirer/input@4.3.1(@types/node@22.15.29)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@22.15.29) + '@inquirer/type': 3.0.10(@types/node@22.15.29) + optionalDependencies: + '@types/node': 22.15.29 - set-cookie-parser@2.7.1: - resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} + '@inquirer/number@3.0.23(@types/node@22.15.29)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@22.15.29) + '@inquirer/type': 3.0.10(@types/node@22.15.29) + optionalDependencies: + '@types/node': 22.15.29 - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + '@inquirer/password@4.0.23(@types/node@22.15.29)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.2(@types/node@22.15.29) + '@inquirer/type': 3.0.10(@types/node@22.15.29) + optionalDependencies: + '@types/node': 22.15.29 - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} + '@inquirer/prompts@7.10.1(@types/node@22.15.29)': + dependencies: + '@inquirer/checkbox': 4.3.2(@types/node@22.15.29) + '@inquirer/confirm': 5.1.21(@types/node@22.15.29) + '@inquirer/editor': 4.2.23(@types/node@22.15.29) + '@inquirer/expand': 4.0.23(@types/node@22.15.29) + '@inquirer/input': 4.3.1(@types/node@22.15.29) + '@inquirer/number': 3.0.23(@types/node@22.15.29) + '@inquirer/password': 4.0.23(@types/node@22.15.29) + '@inquirer/rawlist': 4.1.11(@types/node@22.15.29) + '@inquirer/search': 3.2.2(@types/node@22.15.29) + '@inquirer/select': 4.4.2(@types/node@22.15.29) + optionalDependencies: + '@types/node': 22.15.29 - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - engines: {node: '>= 0.4'} + '@inquirer/prompts@7.3.2(@types/node@22.15.29)': + dependencies: + '@inquirer/checkbox': 4.3.2(@types/node@22.15.29) + '@inquirer/confirm': 5.1.21(@types/node@22.15.29) + '@inquirer/editor': 4.2.23(@types/node@22.15.29) + '@inquirer/expand': 4.0.23(@types/node@22.15.29) + '@inquirer/input': 4.3.1(@types/node@22.15.29) + '@inquirer/number': 3.0.23(@types/node@22.15.29) + '@inquirer/password': 4.0.23(@types/node@22.15.29) + '@inquirer/rawlist': 4.1.11(@types/node@22.15.29) + '@inquirer/search': 3.2.2(@types/node@22.15.29) + '@inquirer/select': 4.4.2(@types/node@22.15.29) + optionalDependencies: + '@types/node': 22.15.29 - side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} + '@inquirer/rawlist@4.1.11(@types/node@22.15.29)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@22.15.29) + '@inquirer/type': 3.0.10(@types/node@22.15.29) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 22.15.29 - side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} + '@inquirer/search@3.2.2(@types/node@22.15.29)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@22.15.29) + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@22.15.29) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 22.15.29 - side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} + '@inquirer/select@4.4.2(@types/node@22.15.29)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.2(@types/node@22.15.29) + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@22.15.29) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 22.15.29 - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} + '@inquirer/type@3.0.10(@types/node@22.15.29)': + optionalDependencies: + '@types/node': 22.15.29 - sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + '@ioredis/commands@1.2.0': {} - slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 - slice-ansi@5.0.0: - resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} - engines: {node: '>=12'} + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.2 + resolve-from: 5.0.0 - slice-ansi@7.1.0: - resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} - engines: {node: '>=18'} + '@istanbuljs/schema@0.1.6': {} - sonic-boom@4.2.0: - resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} + '@jest/console@30.3.0': + dependencies: + '@jest/types': 30.3.0 + '@types/node': 22.15.29 + chalk: 4.1.2 + jest-message-util: 30.3.0 + jest-util: 30.3.0 + slash: 3.0.0 + + '@jest/core@30.3.0(esbuild-register@3.6.0(esbuild@0.25.5))(ts-node@10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3))': + dependencies: + '@jest/console': 30.3.0 + '@jest/pattern': 30.0.1 + '@jest/reporters': 30.3.0 + '@jest/test-result': 30.3.0 + '@jest/transform': 30.3.0 + '@jest/types': 30.3.0 + '@types/node': 22.15.29 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 4.4.0 + exit-x: 0.2.2 + graceful-fs: 4.2.11 + jest-changed-files: 30.3.0 + jest-config: 30.3.0(@types/node@22.15.29)(esbuild-register@3.6.0(esbuild@0.25.5))(ts-node@10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3)) + jest-haste-map: 30.3.0 + jest-message-util: 30.3.0 + jest-regex-util: 30.0.1 + jest-resolve: 30.3.0 + jest-resolve-dependencies: 30.3.0 + jest-runner: 30.3.0 + jest-runtime: 30.3.0 + jest-snapshot: 30.3.0 + jest-util: 30.3.0 + jest-validate: 30.3.0 + jest-watcher: 30.3.0 + pretty-format: 30.3.0 + slash: 3.0.0 + transitivePeerDependencies: + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node - source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + '@jest/diff-sequences@30.3.0': {} - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} + '@jest/environment@30.3.0': + dependencies: + '@jest/fake-timers': 30.3.0 + '@jest/types': 30.3.0 + '@types/node': 22.15.29 + jest-mock: 30.3.0 - split2@4.2.0: - resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} - engines: {node: '>= 10.x'} + '@jest/expect-utils@30.3.0': + dependencies: + '@jest/get-type': 30.1.0 - standard-as-callback@2.1.0: - resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} + '@jest/expect@30.3.0': + dependencies: + expect: 30.3.0 + jest-snapshot: 30.3.0 + transitivePeerDependencies: + - supports-color - string-argv@0.3.2: - resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} - engines: {node: '>=0.6.19'} + '@jest/fake-timers@30.3.0': + dependencies: + '@jest/types': 30.3.0 + '@sinonjs/fake-timers': 15.3.2 + '@types/node': 22.15.29 + jest-message-util: 30.3.0 + jest-mock: 30.3.0 + jest-util: 30.3.0 - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + '@jest/get-type@30.1.0': {} - string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} - engines: {node: '>=18'} + '@jest/globals@30.3.0': + dependencies: + '@jest/environment': 30.3.0 + '@jest/expect': 30.3.0 + '@jest/types': 30.3.0 + jest-mock: 30.3.0 + transitivePeerDependencies: + - supports-color - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + '@jest/pattern@30.0.1': + dependencies: + '@types/node': 22.15.29 + jest-regex-util: 30.0.1 - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} + '@jest/reporters@30.3.0': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 30.3.0 + '@jest/test-result': 30.3.0 + '@jest/transform': 30.3.0 + '@jest/types': 30.3.0 + '@jridgewell/trace-mapping': 0.3.31 + '@types/node': 22.15.29 + chalk: 4.1.2 + collect-v8-coverage: 1.0.3 + exit-x: 0.2.2 + glob: 10.5.0 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.2.0 + jest-message-util: 30.3.0 + jest-util: 30.3.0 + jest-worker: 30.3.0 + slash: 3.0.0 + string-length: 4.0.2 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} + '@jest/schemas@30.0.5': + dependencies: + '@sinclair/typebox': 0.34.49 - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} + '@jest/snapshot-utils@30.3.0': + dependencies: + '@jest/types': 30.3.0 + chalk: 4.1.2 + graceful-fs: 4.2.11 + natural-compare: 1.4.0 - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} + '@jest/source-map@30.0.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + callsites: 3.1.0 + graceful-fs: 4.2.11 - synckit@0.11.8: - resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==} - engines: {node: ^14.18.0 || >=16.0.0} + '@jest/test-result@30.3.0': + dependencies: + '@jest/console': 30.3.0 + '@jest/types': 30.3.0 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.3 - text-extensions@2.4.0: - resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} - engines: {node: '>=8'} + '@jest/test-sequencer@30.3.0': + dependencies: + '@jest/test-result': 30.3.0 + graceful-fs: 4.2.11 + jest-haste-map: 30.3.0 + slash: 3.0.0 - thread-stream@3.1.0: - resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + '@jest/transform@30.3.0': + dependencies: + '@babel/core': 7.29.0 + '@jest/types': 30.3.0 + '@jridgewell/trace-mapping': 0.3.31 + babel-plugin-istanbul: 7.0.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 30.3.0 + jest-regex-util: 30.0.1 + jest-util: 30.3.0 + pirates: 4.0.7 + slash: 3.0.0 + write-file-atomic: 5.0.1 + transitivePeerDependencies: + - supports-color - through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + '@jest/types@30.3.0': + dependencies: + '@jest/pattern': 30.0.1 + '@jest/schemas': 30.0.5 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.15.29 + '@types/yargs': 17.0.35 + chalk: 4.1.2 - tinyexec@1.0.1: - resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 - toad-cache@3.7.0: - resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} - engines: {node: '>=12'} + '@jridgewell/resolve-uri@3.1.2': {} - toad-scheduler@3.1.0: - resolution: {integrity: sha512-ZTwsGMWyKTOokgTmIvjPIvkT3ZiPFgkAi8L0OLONOcSc/BUDPRzNMOfVWZzugIAxyntvY0Nzy1etNk+31Q4FXQ==} + '@jridgewell/source-map@0.3.11': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 - ts-api-utils@2.1.0: - resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} - engines: {node: '>=18.12'} - peerDependencies: - typescript: '>=4.8.4' + '@jridgewell/sourcemap-codec@1.5.5': {} - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 - tsx@4.19.4: - resolution: {integrity: sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==} - engines: {node: '>=18.0.0'} - hasBin: true + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} + '@keyv/serialize@1.1.1': {} - typescript-eslint@8.33.1: - resolution: {integrity: sha512-AgRnV4sKkWOiZ0Kjbnf5ytTJXMUZQ0qhSVdQtDNYLPLnjsATEYhaO94GlRQwi4t4gO8FfjM6NnikHeKjUm8D7A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + '@lukeed/csprng@1.1.0': {} - typescript@5.8.3: - resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} - engines: {node: '>=14.17'} - hasBin: true + '@lukeed/ms@2.0.2': {} - undici-types@6.21.0: - resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + '@microsoft/tsdoc@0.16.0': {} - unicorn-magic@0.1.0: - resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} - engines: {node: '>=18'} + '@mindenit/cist-crawler@0.1.4': {} - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + '@napi-rs/nice-android-arm-eabi@1.1.1': + optional: true - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + '@napi-rs/nice-android-arm64@1.1.1': + optional: true - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} + '@napi-rs/nice-darwin-arm64@1.1.1': + optional: true - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + '@napi-rs/nice-darwin-x64@1.1.1': + optional: true - wrap-ansi@9.0.0: - resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} - engines: {node: '>=18'} + '@napi-rs/nice-freebsd-x64@1.1.1': + optional: true - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + '@napi-rs/nice-linux-arm-gnueabihf@1.1.1': + optional: true - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} + '@napi-rs/nice-linux-arm64-gnu@1.1.1': + optional: true - yaml@2.8.0: - resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==} - engines: {node: '>= 14.6'} - hasBin: true + '@napi-rs/nice-linux-arm64-musl@1.1.1': + optional: true - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} + '@napi-rs/nice-linux-ppc64-gnu@1.1.1': + optional: true - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} + '@napi-rs/nice-linux-riscv64-gnu@1.1.1': + optional: true - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} + '@napi-rs/nice-linux-s390x-gnu@1.1.1': + optional: true - yocto-queue@1.2.1: - resolution: {integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==} - engines: {node: '>=12.20'} + '@napi-rs/nice-linux-x64-gnu@1.1.1': + optional: true - zod@3.24.1: - resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} + '@napi-rs/nice-linux-x64-musl@1.1.1': + optional: true - zod@4.0.10: - resolution: {integrity: sha512-3vB+UU3/VmLL2lvwcY/4RV2i9z/YU0DTV/tDuYjrwmx5WeJ7hwy+rGEEx8glHp6Yxw7ibRbKSaIFBgReRPe5KA==} + '@napi-rs/nice-openharmony-arm64@1.1.1': + optional: true -snapshots: + '@napi-rs/nice-win32-arm64-msvc@1.1.1': + optional: true - '@babel/code-frame@7.27.1': - dependencies: - '@babel/helper-validator-identifier': 7.27.1 - js-tokens: 4.0.0 - picocolors: 1.1.1 + '@napi-rs/nice-win32-ia32-msvc@1.1.1': + optional: true - '@babel/helper-validator-identifier@7.27.1': {} + '@napi-rs/nice-win32-x64-msvc@1.1.1': + optional: true - '@clack/core@0.5.0': - dependencies: - picocolors: 1.1.1 - sisteransi: 1.0.5 + '@napi-rs/nice@1.1.1': + optionalDependencies: + '@napi-rs/nice-android-arm-eabi': 1.1.1 + '@napi-rs/nice-android-arm64': 1.1.1 + '@napi-rs/nice-darwin-arm64': 1.1.1 + '@napi-rs/nice-darwin-x64': 1.1.1 + '@napi-rs/nice-freebsd-x64': 1.1.1 + '@napi-rs/nice-linux-arm-gnueabihf': 1.1.1 + '@napi-rs/nice-linux-arm64-gnu': 1.1.1 + '@napi-rs/nice-linux-arm64-musl': 1.1.1 + '@napi-rs/nice-linux-ppc64-gnu': 1.1.1 + '@napi-rs/nice-linux-riscv64-gnu': 1.1.1 + '@napi-rs/nice-linux-s390x-gnu': 1.1.1 + '@napi-rs/nice-linux-x64-gnu': 1.1.1 + '@napi-rs/nice-linux-x64-musl': 1.1.1 + '@napi-rs/nice-openharmony-arm64': 1.1.1 + '@napi-rs/nice-win32-arm64-msvc': 1.1.1 + '@napi-rs/nice-win32-ia32-msvc': 1.1.1 + '@napi-rs/nice-win32-x64-msvc': 1.1.1 + optional: true - '@clack/prompts@0.11.0': + '@napi-rs/wasm-runtime@0.2.12': dependencies: - '@clack/core': 0.5.0 - picocolors: 1.1.1 - sisteransi: 1.0.5 + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.1 + optional: true - '@commitlint/cli@19.8.1(@types/node@22.15.29)(typescript@5.8.3)': + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: - '@commitlint/format': 19.8.1 - '@commitlint/lint': 19.8.1 - '@commitlint/load': 19.8.1(@types/node@22.15.29)(typescript@5.8.3) - '@commitlint/read': 19.8.1 - '@commitlint/types': 19.8.1 - tinyexec: 1.0.1 - yargs: 17.7.2 + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@nestjs/cli@11.0.21(@swc/cli@0.8.1(@swc/core@1.15.30)(chokidar@4.0.3))(@swc/core@1.15.30)(@types/node@22.15.29)(esbuild@0.25.5)(prettier@3.5.3)': + dependencies: + '@angular-devkit/core': 19.2.24(chokidar@4.0.3) + '@angular-devkit/schematics': 19.2.24(chokidar@4.0.3) + '@angular-devkit/schematics-cli': 19.2.24(@types/node@22.15.29)(chokidar@4.0.3) + '@inquirer/prompts': 7.10.1(@types/node@22.15.29) + '@nestjs/schematics': 11.1.0(chokidar@4.0.3)(prettier@3.5.3)(typescript@5.9.3) + ansis: 4.2.0 + chokidar: 4.0.3 + cli-table3: 0.6.5 + commander: 4.1.1 + fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.9.3)(webpack@5.106.0(@swc/core@1.15.30)(esbuild@0.25.5)) + glob: 13.0.6 + node-emoji: 1.11.0 + ora: 5.4.1 + tsconfig-paths: 4.2.0 + tsconfig-paths-webpack-plugin: 4.2.0 + typescript: 5.9.3 + webpack: 5.106.0(@swc/core@1.15.30)(esbuild@0.25.5) + webpack-node-externals: 3.0.0 + optionalDependencies: + '@swc/cli': 0.8.1(@swc/core@1.15.30)(chokidar@4.0.3) + '@swc/core': 1.15.30 transitivePeerDependencies: - '@types/node' - - typescript - - '@commitlint/config-conventional@19.8.1': - dependencies: - '@commitlint/types': 19.8.1 - conventional-changelog-conventionalcommits: 7.0.2 - - '@commitlint/config-validator@19.8.1': - dependencies: - '@commitlint/types': 19.8.1 - ajv: 8.17.1 + - esbuild + - prettier + - uglify-js + - webpack-cli + + '@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2)': + dependencies: + file-type: 21.3.4 + iterare: 1.2.1 + load-esm: 1.0.3 + reflect-metadata: 0.2.2 + rxjs: 7.8.2 + tslib: 2.8.1 + uid: 2.0.2 + transitivePeerDependencies: + - supports-color - '@commitlint/ensure@19.8.1': + '@nestjs/core@11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: - '@commitlint/types': 19.8.1 - lodash.camelcase: 4.3.0 - lodash.kebabcase: 4.1.1 - lodash.snakecase: 4.1.1 - lodash.startcase: 4.4.0 - lodash.upperfirst: 4.3.1 - - '@commitlint/execute-rule@19.8.1': {} + '@nestjs/common': 11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nuxt/opencollective': 0.4.1 + fast-safe-stringify: 2.1.1 + iterare: 1.2.1 + path-to-regexp: 8.4.2 + reflect-metadata: 0.2.2 + rxjs: 7.8.2 + tslib: 2.8.1 + uid: 2.0.2 - '@commitlint/format@19.8.1': + '@nestjs/mapped-types@2.1.1(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)': dependencies: - '@commitlint/types': 19.8.1 - chalk: 5.4.1 + '@nestjs/common': 11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2) + reflect-metadata: 0.2.2 - '@commitlint/is-ignored@19.8.1': + '@nestjs/platform-fastify@11.1.19(@fastify/static@9.1.3)(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2))': dependencies: - '@commitlint/types': 19.8.1 - semver: 7.7.2 + '@fastify/cors': 11.2.0 + '@fastify/formbody': 8.0.2 + '@nestjs/common': 11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2) + fast-querystring: 1.1.2 + fastify: 5.8.4 + fastify-plugin: 5.1.0 + find-my-way: 9.5.0 + light-my-request: 6.6.0 + path-to-regexp: 8.4.2 + reusify: 1.1.0 + tslib: 2.8.1 + optionalDependencies: + '@fastify/static': 9.1.3 - '@commitlint/lint@19.8.1': + '@nestjs/schedule@6.1.3(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2))': dependencies: - '@commitlint/is-ignored': 19.8.1 - '@commitlint/parse': 19.8.1 - '@commitlint/rules': 19.8.1 - '@commitlint/types': 19.8.1 + '@nestjs/common': 11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2) + cron: 4.4.0 - '@commitlint/load@19.8.1(@types/node@22.15.29)(typescript@5.8.3)': + '@nestjs/schematics@11.1.0(chokidar@4.0.3)(prettier@3.5.3)(typescript@5.8.3)': dependencies: - '@commitlint/config-validator': 19.8.1 - '@commitlint/execute-rule': 19.8.1 - '@commitlint/resolve-extends': 19.8.1 - '@commitlint/types': 19.8.1 - chalk: 5.4.1 - cosmiconfig: 9.0.0(typescript@5.8.3) - cosmiconfig-typescript-loader: 6.1.0(@types/node@22.15.29)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3) - lodash.isplainobject: 4.0.6 - lodash.merge: 4.6.2 - lodash.uniq: 4.5.0 + '@angular-devkit/core': 19.2.24(chokidar@4.0.3) + '@angular-devkit/schematics': 19.2.24(chokidar@4.0.3) + comment-json: 5.0.0 + jsonc-parser: 3.3.1 + pluralize: 8.0.0 + typescript: 5.8.3 + optionalDependencies: + prettier: 3.5.3 transitivePeerDependencies: - - '@types/node' - - typescript - - '@commitlint/message@19.8.1': {} + - chokidar - '@commitlint/parse@19.8.1': + '@nestjs/schematics@11.1.0(chokidar@4.0.3)(prettier@3.5.3)(typescript@5.9.3)': dependencies: - '@commitlint/types': 19.8.1 - conventional-changelog-angular: 7.0.0 - conventional-commits-parser: 5.0.0 + '@angular-devkit/core': 19.2.24(chokidar@4.0.3) + '@angular-devkit/schematics': 19.2.24(chokidar@4.0.3) + comment-json: 5.0.0 + jsonc-parser: 3.3.1 + pluralize: 8.0.0 + typescript: 5.9.3 + optionalDependencies: + prettier: 3.5.3 + transitivePeerDependencies: + - chokidar + + '@nestjs/swagger@11.4.1(@fastify/static@9.1.3)(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)': + dependencies: + '@microsoft/tsdoc': 0.16.0 + '@nestjs/common': 11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/mapped-types': 2.1.1(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2) + js-yaml: 4.1.1 + lodash: 4.18.1 + path-to-regexp: 8.4.2 + reflect-metadata: 0.2.2 + swagger-ui-dist: 5.32.4 + optionalDependencies: + '@fastify/static': 9.1.3 - '@commitlint/read@19.8.1': + '@nestjs/testing@11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2))': dependencies: - '@commitlint/top-level': 19.8.1 - '@commitlint/types': 19.8.1 - git-raw-commits: 4.0.0 - minimist: 1.2.8 - tinyexec: 1.0.1 + '@nestjs/common': 11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2) + tslib: 2.8.1 - '@commitlint/resolve-extends@19.8.1': - dependencies: - '@commitlint/config-validator': 19.8.1 - '@commitlint/types': 19.8.1 - global-directory: 4.0.1 - import-meta-resolve: 4.1.0 - lodash.mergewith: 4.6.2 - resolve-from: 5.0.0 + '@noble/hashes@1.8.0': {} - '@commitlint/rules@19.8.1': + '@nodelib/fs.scandir@2.1.5': dependencies: - '@commitlint/ensure': 19.8.1 - '@commitlint/message': 19.8.1 - '@commitlint/to-lines': 19.8.1 - '@commitlint/types': 19.8.1 + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 - '@commitlint/to-lines@19.8.1': {} + '@nodelib/fs.stat@2.0.5': {} - '@commitlint/top-level@19.8.1': + '@nodelib/fs.walk@1.2.8': dependencies: - find-up: 7.0.0 + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 - '@commitlint/types@19.8.1': + '@nuxt/opencollective@0.4.1': dependencies: - '@types/conventional-commits-parser': 5.0.1 - chalk: 5.4.1 + consola: 3.4.2 - '@drizzle-team/brocli@0.10.2': {} + '@oxc-project/types@0.127.0': {} - '@esbuild-kit/core-utils@3.3.2': + '@paralleldrive/cuid2@2.3.1': dependencies: - esbuild: 0.18.20 - source-map-support: 0.5.21 + '@noble/hashes': 1.8.0 - '@esbuild-kit/esm-loader@2.6.5': - dependencies: - '@esbuild-kit/core-utils': 3.3.2 - get-tsconfig: 4.10.1 + '@pinojs/redact@0.4.0': {} - '@esbuild/aix-ppc64@0.25.5': + '@pkgjs/parseargs@0.11.0': optional: true - '@esbuild/android-arm64@0.18.20': - optional: true + '@pkgr/core@0.2.7': {} - '@esbuild/android-arm64@0.25.5': + '@rolldown/binding-android-arm64@1.0.0-rc.17': optional: true - '@esbuild/android-arm@0.18.20': + '@rolldown/binding-darwin-arm64@1.0.0-rc.17': optional: true - '@esbuild/android-arm@0.25.5': + '@rolldown/binding-darwin-x64@1.0.0-rc.17': optional: true - '@esbuild/android-x64@0.18.20': + '@rolldown/binding-freebsd-x64@1.0.0-rc.17': optional: true - '@esbuild/android-x64@0.25.5': + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': optional: true - '@esbuild/darwin-arm64@0.18.20': + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': optional: true - '@esbuild/darwin-arm64@0.25.5': + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': optional: true - '@esbuild/darwin-x64@0.18.20': + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': optional: true - '@esbuild/darwin-x64@0.25.5': + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': optional: true - '@esbuild/freebsd-arm64@0.18.20': + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': optional: true - '@esbuild/freebsd-arm64@0.25.5': + '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': optional: true - '@esbuild/freebsd-x64@0.18.20': + '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': optional: true - '@esbuild/freebsd-x64@0.25.5': + '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@esbuild/linux-arm64@0.18.20': + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': optional: true - '@esbuild/linux-arm64@0.25.5': + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': optional: true - '@esbuild/linux-arm@0.18.20': + '@rolldown/pluginutils@1.0.0-rc.17': {} + + '@rollup/pluginutils@5.3.0': + dependencies: + '@types/estree': 1.0.7 + estree-walker: 2.0.2 + picomatch: 4.0.4 + + '@scalar/client-side-rendering@0.1.3': + dependencies: + '@scalar/types': 0.9.2 + + '@scalar/core@0.3.1': + dependencies: + '@scalar/types': 0.2.1 + + '@scalar/fastify-api-reference@1.31.3': + dependencies: + '@scalar/core': 0.3.1 + '@scalar/openapi-parser': 0.14.0 + '@scalar/openapi-types': 0.3.1 + '@scalar/types': 0.2.1 + fastify-plugin: 4.5.1 + github-slugger: 2.0.0 + + '@scalar/helpers@0.5.2': {} + + '@scalar/nestjs-api-reference@1.1.10': + dependencies: + '@scalar/client-side-rendering': 0.1.3 + + '@scalar/openapi-parser@0.14.0': + dependencies: + ajv: 8.17.1 + ajv-draft-04: 1.0.0(ajv@8.17.1) + ajv-formats: 3.0.1(ajv@8.17.1) + jsonpointer: 5.0.1 + leven: 4.0.0 + yaml: 2.8.0 + + '@scalar/openapi-types@0.3.1': + dependencies: + zod: 3.24.1 + + '@scalar/types@0.2.1': + dependencies: + '@scalar/openapi-types': 0.3.1 + nanoid: 5.1.5 + zod: 3.24.1 + + '@scalar/types@0.9.2': + dependencies: + '@scalar/helpers': 0.5.2 + nanoid: 5.1.9 + type-fest: 5.6.0 + zod: 4.3.6 + + '@scarf/scarf@1.4.0': {} + + '@sec-ant/readable-stream@0.4.1': {} + + '@sinclair/typebox@0.34.49': {} + + '@sindresorhus/is@7.2.0': {} + + '@sindresorhus/merge-streams@4.0.0': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@15.3.2': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@standard-schema/spec@1.1.0': {} + + '@swc/cli@0.8.1(@swc/core@1.15.30)(chokidar@4.0.3)': + dependencies: + '@swc/core': 1.15.30 + '@swc/counter': 0.1.3 + '@xhmikosr/bin-wrapper': 14.2.3 + commander: 8.3.0 + minimatch: 9.0.5 + piscina: 4.9.2 + semver: 7.7.2 + slash: 3.0.0 + source-map: 0.7.6 + tinyglobby: 0.2.16 + optionalDependencies: + chokidar: 4.0.3 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + - supports-color + + '@swc/core-darwin-arm64@1.15.30': optional: true - '@esbuild/linux-arm@0.25.5': + '@swc/core-darwin-x64@1.15.30': optional: true - '@esbuild/linux-ia32@0.18.20': + '@swc/core-linux-arm-gnueabihf@1.15.30': optional: true - '@esbuild/linux-ia32@0.25.5': + '@swc/core-linux-arm64-gnu@1.15.30': optional: true - '@esbuild/linux-loong64@0.18.20': + '@swc/core-linux-arm64-musl@1.15.30': optional: true - '@esbuild/linux-loong64@0.25.5': + '@swc/core-linux-ppc64-gnu@1.15.30': optional: true - '@esbuild/linux-mips64el@0.18.20': + '@swc/core-linux-s390x-gnu@1.15.30': optional: true - '@esbuild/linux-mips64el@0.25.5': + '@swc/core-linux-x64-gnu@1.15.30': optional: true - '@esbuild/linux-ppc64@0.18.20': + '@swc/core-linux-x64-musl@1.15.30': optional: true - '@esbuild/linux-ppc64@0.25.5': + '@swc/core-win32-arm64-msvc@1.15.30': optional: true - '@esbuild/linux-riscv64@0.18.20': + '@swc/core-win32-ia32-msvc@1.15.30': optional: true - '@esbuild/linux-riscv64@0.25.5': + '@swc/core-win32-x64-msvc@1.15.30': optional: true - '@esbuild/linux-s390x@0.18.20': + '@swc/core@1.15.30': + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.26 + optionalDependencies: + '@swc/core-darwin-arm64': 1.15.30 + '@swc/core-darwin-x64': 1.15.30 + '@swc/core-linux-arm-gnueabihf': 1.15.30 + '@swc/core-linux-arm64-gnu': 1.15.30 + '@swc/core-linux-arm64-musl': 1.15.30 + '@swc/core-linux-ppc64-gnu': 1.15.30 + '@swc/core-linux-s390x-gnu': 1.15.30 + '@swc/core-linux-x64-gnu': 1.15.30 + '@swc/core-linux-x64-musl': 1.15.30 + '@swc/core-win32-arm64-msvc': 1.15.30 + '@swc/core-win32-ia32-msvc': 1.15.30 + '@swc/core-win32-x64-msvc': 1.15.30 + + '@swc/counter@0.1.3': {} + + '@swc/types@0.1.26': + dependencies: + '@swc/counter': 0.1.3 + + '@tokenizer/inflate@0.4.1': + dependencies: + debug: 4.4.3 + token-types: 6.1.2 + transitivePeerDependencies: + - supports-color + + '@tokenizer/token@0.3.0': {} + + '@total-typescript/ts-reset@0.6.1': {} + + '@tsconfig/node10@1.0.12': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 optional: true - '@esbuild/linux-s390x@0.25.5': - optional: true + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/conventional-commits-parser@5.0.1': + dependencies: + '@types/node': 22.15.29 + + '@types/cookiejar@2.1.5': {} + + '@types/deep-eql@4.0.2': {} + + '@types/eslint-scope@3.7.7': + dependencies: + '@types/eslint': 9.6.1 + '@types/estree': 1.0.8 + + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + + '@types/estree@1.0.7': {} - '@esbuild/linux-x64@0.18.20': - optional: true + '@types/estree@1.0.8': {} - '@esbuild/linux-x64@0.25.5': - optional: true + '@types/http-cache-semantics@4.2.0': {} - '@esbuild/netbsd-arm64@0.25.5': - optional: true + '@types/istanbul-lib-coverage@2.0.6': {} - '@esbuild/netbsd-x64@0.18.20': - optional: true + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 - '@esbuild/netbsd-x64@0.25.5': - optional: true + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 - '@esbuild/openbsd-arm64@0.25.5': - optional: true + '@types/jest@30.0.0': + dependencies: + expect: 30.3.0 + pretty-format: 30.3.0 - '@esbuild/openbsd-x64@0.18.20': - optional: true + '@types/json-schema@7.0.15': {} - '@esbuild/openbsd-x64@0.25.5': - optional: true + '@types/luxon@3.7.1': {} - '@esbuild/sunos-x64@0.18.20': - optional: true + '@types/methods@1.1.4': {} - '@esbuild/sunos-x64@0.25.5': - optional: true + '@types/node@22.15.29': + dependencies: + undici-types: 6.21.0 - '@esbuild/win32-arm64@0.18.20': - optional: true + '@types/qs@6.14.0': {} - '@esbuild/win32-arm64@0.25.5': - optional: true + '@types/stack-utils@2.0.3': {} - '@esbuild/win32-ia32@0.18.20': - optional: true + '@types/superagent@8.1.9': + dependencies: + '@types/cookiejar': 2.1.5 + '@types/methods': 1.1.4 + '@types/node': 22.15.29 + form-data: 4.0.5 - '@esbuild/win32-ia32@0.25.5': - optional: true + '@types/supertest@7.2.0': + dependencies: + '@types/methods': 1.1.4 + '@types/superagent': 8.1.9 - '@esbuild/win32-x64@0.18.20': - optional: true + '@types/yargs-parser@21.0.3': {} - '@esbuild/win32-x64@0.25.5': - optional: true + '@types/yargs@17.0.35': + dependencies: + '@types/yargs-parser': 21.0.3 - '@eslint-community/eslint-utils@4.7.0(eslint@9.28.0(jiti@2.4.2))': + '@typescript-eslint/eslint-plugin@8.33.1(@typescript-eslint/parser@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)': dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.33.1 + '@typescript-eslint/type-utils': 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/utils': 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.33.1 eslint: 9.28.0(jiti@2.4.2) - eslint-visitor-keys: 3.4.3 + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color - '@eslint-community/regexpp@4.12.1': {} + '@typescript-eslint/parser@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.33.1 + '@typescript-eslint/types': 8.33.1 + '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.33.1 + debug: 4.4.1 + eslint: 9.28.0(jiti@2.4.2) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color - '@eslint/config-array@0.20.0': + '@typescript-eslint/project-service@8.33.1(typescript@5.8.3)': dependencies: - '@eslint/object-schema': 2.1.6 + '@typescript-eslint/tsconfig-utils': 8.33.1(typescript@5.8.3) + '@typescript-eslint/types': 8.33.1 debug: 4.4.1 - minimatch: 3.1.2 + typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.2.2': {} + '@typescript-eslint/scope-manager@8.33.1': + dependencies: + '@typescript-eslint/types': 8.33.1 + '@typescript-eslint/visitor-keys': 8.33.1 - '@eslint/core@0.14.0': + '@typescript-eslint/tsconfig-utils@8.33.1(typescript@5.8.3)': dependencies: - '@types/json-schema': 7.0.15 + typescript: 5.8.3 - '@eslint/eslintrc@3.3.1': + '@typescript-eslint/type-utils@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)': dependencies: - ajv: 6.12.6 + '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) + '@typescript-eslint/utils': 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) debug: 4.4.1 - espree: 10.3.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.1 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 + eslint: 9.28.0(jiti@2.4.2) + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@eslint/js@9.28.0': {} - - '@eslint/object-schema@2.1.6': {} + '@typescript-eslint/types@8.33.1': {} - '@eslint/plugin-kit@0.3.1': + '@typescript-eslint/typescript-estree@8.33.1(typescript@5.8.3)': dependencies: - '@eslint/core': 0.14.0 - levn: 0.4.1 + '@typescript-eslint/project-service': 8.33.1(typescript@5.8.3) + '@typescript-eslint/tsconfig-utils': 8.33.1(typescript@5.8.3) + '@typescript-eslint/types': 8.33.1 + '@typescript-eslint/visitor-keys': 8.33.1 + debug: 4.4.1 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color - '@fastify/ajv-compiler@4.0.2': + '@typescript-eslint/utils@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)': dependencies: - ajv: 8.17.1 - ajv-formats: 3.0.1(ajv@8.17.1) - fast-uri: 3.0.6 + '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.33.1 + '@typescript-eslint/types': 8.33.1 + '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) + eslint: 9.28.0(jiti@2.4.2) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color - '@fastify/awilix@7.0.0(awilix@12.0.5)(fastify@5.3.3)': + '@typescript-eslint/visitor-keys@8.33.1': dependencies: - awilix: 12.0.5 - awilix-manager: 6.1.0(awilix@12.0.5) - fastify: 5.3.3 - fastify-plugin: 5.0.1 + '@typescript-eslint/types': 8.33.1 + eslint-visitor-keys: 4.2.0 - '@fastify/cookie@11.0.2': - dependencies: - cookie: 1.0.2 - fastify-plugin: 5.0.1 + '@ungap/structured-clone@1.3.0': {} - '@fastify/cors@11.0.1': - dependencies: - fastify-plugin: 5.0.1 - toad-cache: 3.7.0 + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + optional: true - '@fastify/error@4.2.0': {} + '@unrs/resolver-binding-android-arm64@1.11.1': + optional: true - '@fastify/fast-json-stringify-compiler@5.0.3': - dependencies: - fast-json-stringify: 6.0.1 + '@unrs/resolver-binding-darwin-arm64@1.11.1': + optional: true - '@fastify/forwarded@3.0.0': {} + '@unrs/resolver-binding-darwin-x64@1.11.1': + optional: true - '@fastify/helmet@13.0.1': - dependencies: - fastify-plugin: 5.0.1 - helmet: 8.1.0 + '@unrs/resolver-binding-freebsd-x64@1.11.1': + optional: true - '@fastify/merge-json-schemas@0.2.1': - dependencies: - dequal: 2.0.3 + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + optional: true - '@fastify/proxy-addr@5.0.0': - dependencies: - '@fastify/forwarded': 3.0.0 - ipaddr.js: 2.2.0 + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + optional: true - '@fastify/rate-limit@10.3.0': - dependencies: - '@lukeed/ms': 2.0.2 - fastify-plugin: 5.0.1 - toad-cache: 3.7.0 + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + optional: true - '@fastify/schedule@6.0.0(toad-scheduler@3.1.0)': - dependencies: - fastify-plugin: 5.0.1 - toad-scheduler: 3.1.0 + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + optional: true - '@fastify/swagger@9.5.1': - dependencies: - fastify-plugin: 5.0.1 - json-schema-resolver: 3.0.0 - openapi-types: 12.1.3 - rfdc: 1.4.1 - yaml: 2.8.0 - transitivePeerDependencies: - - supports-color + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + optional: true - '@humanfs/core@0.19.1': {} + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + optional: true - '@humanfs/node@0.16.6': - dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.3.1 + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + optional: true - '@humanwhocodes/module-importer@1.0.1': {} + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + optional: true - '@humanwhocodes/retry@0.3.1': {} + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + optional: true - '@humanwhocodes/retry@0.4.3': {} + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + optional: true - '@ioredis/commands@1.2.0': {} + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + dependencies: + '@napi-rs/wasm-runtime': 0.2.12 + optional: true - '@lukeed/ms@2.0.2': {} + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + optional: true - '@nodelib/fs.scandir@2.1.5': + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + optional: true + + '@vitest/coverage-v8@4.1.5(vitest@4.1.5)': + dependencies: + '@bcoe/v8-coverage': 1.0.2 + '@vitest/utils': 4.1.5 + ast-v8-to-istanbul: 1.0.0 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-reports: 3.2.0 + magicast: 0.5.2 + obug: 2.1.1 + std-env: 4.1.0 + tinyrainbow: 3.1.0 + vitest: 4.1.5(@types/node@22.15.29)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@22.15.29)(esbuild@0.25.5)(jiti@2.4.2)(terser@5.46.2)(tsx@4.19.4)(yaml@2.8.0)) + + '@vitest/expect@4.1.5': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.5 + '@vitest/utils': 4.1.5 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + '@vitest/mocker@4.1.5(vite@8.0.10(@types/node@22.15.29)(esbuild@0.25.5)(jiti@2.4.2)(terser@5.46.2)(tsx@4.19.4)(yaml@2.8.0))': + dependencies: + '@vitest/spy': 4.1.5 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.10(@types/node@22.15.29)(esbuild@0.25.5)(jiti@2.4.2)(terser@5.46.2)(tsx@4.19.4)(yaml@2.8.0) + + '@vitest/pretty-format@4.1.5': dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 + tinyrainbow: 3.1.0 - '@nodelib/fs.stat@2.0.5': {} + '@vitest/runner@4.1.5': + dependencies: + '@vitest/utils': 4.1.5 + pathe: 2.0.3 - '@nodelib/fs.walk@1.2.8': + '@vitest/snapshot@4.1.5': dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.19.1 + '@vitest/pretty-format': 4.1.5 + '@vitest/utils': 4.1.5 + magic-string: 0.30.21 + pathe: 2.0.3 - '@pkgr/core@0.2.7': {} + '@vitest/spy@4.1.5': {} - '@scalar/core@0.3.1': + '@vitest/utils@4.1.5': dependencies: - '@scalar/types': 0.2.1 + '@vitest/pretty-format': 4.1.5 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 - '@scalar/fastify-api-reference@1.31.3': + '@webassemblyjs/ast@1.14.1': dependencies: - '@scalar/core': 0.3.1 - '@scalar/openapi-parser': 0.14.0 - '@scalar/openapi-types': 0.3.1 - '@scalar/types': 0.2.1 - fastify-plugin: 4.5.1 - github-slugger: 2.0.0 + '@webassemblyjs/helper-numbers': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@scalar/openapi-parser@0.14.0': + '@webassemblyjs/floating-point-hex-parser@1.13.2': {} + + '@webassemblyjs/helper-api-error@1.13.2': {} + + '@webassemblyjs/helper-buffer@1.14.1': {} + + '@webassemblyjs/helper-numbers@1.13.2': dependencies: - ajv: 8.17.1 - ajv-draft-04: 1.0.0(ajv@8.17.1) - ajv-formats: 3.0.1(ajv@8.17.1) - jsonpointer: 5.0.1 - leven: 4.0.0 - yaml: 2.8.0 + '@webassemblyjs/floating-point-hex-parser': 1.13.2 + '@webassemblyjs/helper-api-error': 1.13.2 + '@xtuc/long': 4.2.2 + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} + + '@webassemblyjs/helper-wasm-section@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/wasm-gen': 1.14.1 - '@scalar/openapi-types@0.3.1': + '@webassemblyjs/ieee754@1.13.2': dependencies: - zod: 3.24.1 + '@xtuc/ieee754': 1.2.0 - '@scalar/types@0.2.1': + '@webassemblyjs/leb128@1.13.2': dependencies: - '@scalar/openapi-types': 0.3.1 - nanoid: 5.1.5 - zod: 3.24.1 + '@xtuc/long': 4.2.2 - '@types/conventional-commits-parser@5.0.1': + '@webassemblyjs/utf8@1.13.2': {} + + '@webassemblyjs/wasm-edit@1.14.1': dependencies: - '@types/node': 22.15.29 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/helper-wasm-section': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-opt': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + '@webassemblyjs/wast-printer': 1.14.1 - '@types/estree@1.0.7': {} + '@webassemblyjs/wasm-gen@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 - '@types/json-schema@7.0.15': {} + '@webassemblyjs/wasm-opt@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 - '@types/node@22.15.29': + '@webassemblyjs/wasm-parser@1.14.1': dependencies: - undici-types: 6.21.0 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-api-error': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 - '@types/qs@6.14.0': {} + '@webassemblyjs/wast-printer@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@xtuc/long': 4.2.2 - '@typescript-eslint/eslint-plugin@8.33.1(@typescript-eslint/parser@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)': + '@xhmikosr/archive-type@8.0.1': dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) - '@typescript-eslint/scope-manager': 8.33.1 - '@typescript-eslint/type-utils': 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) - '@typescript-eslint/utils': 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.33.1 - eslint: 9.28.0(jiti@2.4.2) - graphemer: 1.4.0 - ignore: 7.0.5 - natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.8.3) - typescript: 5.8.3 + file-type: 21.3.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)': + '@xhmikosr/bin-check@8.2.1': dependencies: - '@typescript-eslint/scope-manager': 8.33.1 - '@typescript-eslint/types': 8.33.1 - '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.33.1 - debug: 4.4.1 - eslint: 9.28.0(jiti@2.4.2) - typescript: 5.8.3 + execa: 9.6.1 + isexe: 4.0.0 + + '@xhmikosr/bin-wrapper@14.2.3': + dependencies: + '@xhmikosr/bin-check': 8.2.1 + '@xhmikosr/downloader': 16.1.2 + '@xhmikosr/os-filter-obj': 4.0.0 + binary-version-check: 6.1.0 transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a - supports-color - '@typescript-eslint/project-service@8.33.1(typescript@5.8.3)': + '@xhmikosr/decompress-tar@9.0.1': dependencies: - '@typescript-eslint/tsconfig-utils': 8.33.1(typescript@5.8.3) - '@typescript-eslint/types': 8.33.1 - debug: 4.4.1 - typescript: 5.8.3 + file-type: 21.3.4 + is-stream: 4.0.1 + tar-stream: 3.1.7 transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a - supports-color - '@typescript-eslint/scope-manager@8.33.1': + '@xhmikosr/decompress-tarbz2@9.0.1': dependencies: - '@typescript-eslint/types': 8.33.1 - '@typescript-eslint/visitor-keys': 8.33.1 + '@xhmikosr/decompress-tar': 9.0.1 + file-type: 21.3.4 + is-stream: 4.0.1 + seek-bzip: 2.0.0 + unbzip2-stream: 1.4.3 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + - supports-color - '@typescript-eslint/tsconfig-utils@8.33.1(typescript@5.8.3)': + '@xhmikosr/decompress-targz@9.0.1': dependencies: - typescript: 5.8.3 + '@xhmikosr/decompress-tar': 9.0.1 + file-type: 21.3.4 + is-stream: 4.0.1 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + - supports-color - '@typescript-eslint/type-utils@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)': + '@xhmikosr/decompress-unzip@8.1.0': dependencies: - '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) - '@typescript-eslint/utils': 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) - debug: 4.4.1 - eslint: 9.28.0(jiti@2.4.2) - ts-api-utils: 2.1.0(typescript@5.8.3) - typescript: 5.8.3 + file-type: 21.3.4 + get-stream: 9.0.1 + yauzl: 3.3.0 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.33.1': {} - - '@typescript-eslint/typescript-estree@8.33.1(typescript@5.8.3)': + '@xhmikosr/decompress@11.1.2': dependencies: - '@typescript-eslint/project-service': 8.33.1(typescript@5.8.3) - '@typescript-eslint/tsconfig-utils': 8.33.1(typescript@5.8.3) - '@typescript-eslint/types': 8.33.1 - '@typescript-eslint/visitor-keys': 8.33.1 - debug: 4.4.1 - fast-glob: 3.3.3 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.7.2 - ts-api-utils: 2.1.0(typescript@5.8.3) - typescript: 5.8.3 + '@xhmikosr/decompress-tar': 9.0.1 + '@xhmikosr/decompress-tarbz2': 9.0.1 + '@xhmikosr/decompress-targz': 9.0.1 + '@xhmikosr/decompress-unzip': 8.1.0 + graceful-fs: 4.2.11 + strip-dirs: 3.0.0 transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a - supports-color - '@typescript-eslint/utils@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)': + '@xhmikosr/downloader@16.1.2': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0(jiti@2.4.2)) - '@typescript-eslint/scope-manager': 8.33.1 - '@typescript-eslint/types': 8.33.1 - '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) - eslint: 9.28.0(jiti@2.4.2) - typescript: 5.8.3 + '@xhmikosr/archive-type': 8.0.1 + '@xhmikosr/decompress': 11.1.2 + content-disposition: 1.1.0 + ext-name: 5.0.0 + file-type: 21.3.4 + filenamify: 7.0.1 + get-stream: 9.0.1 + got: 14.6.6 transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a - supports-color - '@typescript-eslint/visitor-keys@8.33.1': + '@xhmikosr/os-filter-obj@4.0.0': dependencies: - '@typescript-eslint/types': 8.33.1 - eslint-visitor-keys: 4.2.0 + arch: 3.0.0 + + '@xtuc/ieee754@1.2.0': {} + + '@xtuc/long@4.2.2': {} JSONStream@1.3.5: dependencies: @@ -2739,12 +7378,22 @@ snapshots: abstract-logging@2.0.1: {} + acorn-import-phases@1.0.4(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + acorn-jsx@5.3.2(acorn@8.14.1): dependencies: acorn: 8.14.1 + acorn-walk@8.3.5: + dependencies: + acorn: 8.16.0 + acorn@8.14.1: {} + acorn@8.16.0: {} + aggregate-error@4.0.1: dependencies: clean-stack: 4.2.0 @@ -2754,10 +7403,27 @@ snapshots: optionalDependencies: ajv: 8.17.1 + ajv-formats@2.1.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + ajv-formats@3.0.1(ajv@8.17.1): optionalDependencies: ajv: 8.17.1 + ajv-formats@3.0.1(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + + ajv-keywords@3.5.2(ajv@6.12.6): + dependencies: + ajv: 6.12.6 + + ajv-keywords@5.1.0(ajv@8.17.1): + dependencies: + ajv: 8.17.1 + fast-deep-equal: 3.1.3 + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -2772,8 +7438,19 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + ajv@8.18.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.6 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + ansi-colors@4.1.3: {} + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + ansi-escapes@7.0.0: dependencies: environment: 1.1.0 @@ -2786,14 +7463,45 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@5.2.0: {} + ansi-styles@6.2.1: {} + ansis@4.2.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arch@3.0.0: {} + + arg@4.1.3: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + argparse@2.0.1: {} array-ify@1.0.0: {} + array-timsort@1.0.3: {} + arrify@3.0.0: {} + asap@2.0.6: {} + + assertion-error@2.0.1: {} + + ast-v8-to-istanbul@1.0.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + estree-walker: 3.0.3 + js-tokens: 10.0.0 + + asynckit@0.4.0: {} + atomic-sleep@1.0.0: {} avvio@9.1.0: @@ -2810,12 +7518,91 @@ snapshots: camel-case: 4.1.2 fast-glob: 3.3.3 + b4a@1.8.0: {} + + babel-jest@30.3.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@jest/transform': 30.3.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 7.0.1 + babel-preset-jest: 30.3.0(@babel/core@7.29.0) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-istanbul@7.0.1: + dependencies: + '@babel/helper-plugin-utils': 7.28.6 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.6 + istanbul-lib-instrument: 6.0.3 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@30.3.0: + dependencies: + '@types/babel__core': 7.20.5 + + babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.0) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.0) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.0) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.0) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.0) + + babel-preset-jest@30.3.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + babel-plugin-jest-hoist: 30.3.0 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0) + balanced-match@1.0.2: {} + balanced-match@4.0.4: {} + + bare-events@2.8.2: {} + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.10.22: {} + better-result@2.7.0: dependencies: '@clack/prompts': 0.11.0 + binary-version-check@6.1.0: + dependencies: + binary-version: 7.1.0 + semver: 7.7.2 + semver-truncate: 3.0.0 + + binary-version@7.1.0: + dependencies: + execa: 8.0.1 + find-versions: 6.0.0 + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + boolbase@1.0.0: {} brace-expansion@1.1.11: @@ -2827,12 +7614,53 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.5: + dependencies: + balanced-match: 4.0.4 + braces@3.0.3: dependencies: fill-range: 7.1.1 + browserslist@4.28.2: + dependencies: + baseline-browser-mapping: 2.10.22 + caniuse-lite: 1.0.30001790 + electron-to-chromium: 1.5.344 + node-releases: 2.0.38 + update-browserslist-db: 1.2.3(browserslist@4.28.2) + + bs-logger@0.2.6: + dependencies: + fast-json-stable-stringify: 2.1.0 + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-crc32@0.2.13: {} + buffer-from@1.1.2: {} + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + byte-counter@0.1.0: {} + + cacheable-lookup@7.0.0: {} + + cacheable-request@13.0.18: + dependencies: + '@types/http-cache-semantics': 4.2.0 + get-stream: 9.0.1 + http-cache-semantics: 4.2.0 + keyv: 5.6.0 + mimic-response: 4.0.0 + normalize-url: 8.1.1 + responselike: 4.0.2 + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -2850,6 +7678,14 @@ snapshots: pascal-case: 3.1.2 tslib: 2.8.1 + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001790: {} + + chai@6.2.2: {} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -2857,27 +7693,61 @@ snapshots: chalk@5.4.1: {} + char-regex@1.0.2: {} + + chardet@2.1.1: {} + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + chrome-trace-event@1.0.4: {} + + ci-info@4.4.0: {} + + cjs-module-lexer@2.2.0: {} + clean-stack@4.2.0: dependencies: escape-string-regexp: 5.0.0 + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + cli-cursor@5.0.0: dependencies: restore-cursor: 5.1.0 + cli-spinners@2.9.2: {} + + cli-table3@0.6.5: + dependencies: + string-width: 4.2.3 + optionalDependencies: + '@colors/colors': 1.5.0 + cli-truncate@4.0.0: dependencies: slice-ansi: 5.0.0 string-width: 7.2.0 + cli-width@4.1.0: {} + cliui@8.0.1: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + clone@1.0.4: {} + cluster-key-slot@1.1.2: {} + co@4.6.0: {} + + collect-v8-coverage@1.0.3: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -2886,17 +7756,40 @@ snapshots: colorette@2.0.20: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + commander@12.1.0: {} commander@13.1.0: {} + commander@2.20.3: {} + + commander@4.1.1: {} + + commander@6.2.1: {} + + commander@8.3.0: {} + + comment-json@5.0.0: + dependencies: + array-timsort: 1.0.3 + esprima: 4.0.1 + compare-func@2.0.0: dependencies: array-ify: 1.0.0 dot-prop: 5.3.0 + component-emitter@1.3.1: {} + concat-map@0.0.1: {} + consola@3.4.2: {} + + content-disposition@1.1.0: {} + conventional-changelog-angular@7.0.0: dependencies: compare-func: 2.0.0 @@ -2912,8 +7805,16 @@ snapshots: meow: 12.1.1 split2: 4.2.0 + convert-hrtime@5.0.0: {} + + convert-source-map@2.0.0: {} + + cookie-signature@1.2.2: {} + cookie@1.0.2: {} + cookiejar@2.1.4: {} + cosmiconfig-typescript-loader@6.1.0(@types/node@22.15.29)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3): dependencies: '@types/node': 22.15.29 @@ -2921,6 +7822,15 @@ snapshots: jiti: 2.4.2 typescript: 5.8.3 + cosmiconfig@8.3.6(typescript@5.9.3): + dependencies: + import-fresh: 3.3.1 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + optionalDependencies: + typescript: 5.9.3 + cosmiconfig@9.0.0(typescript@5.8.3): dependencies: env-paths: 2.2.1 @@ -2952,6 +7862,13 @@ snapshots: p-filter: 3.0.0 p-map: 6.0.0 + create-require@1.1.1: {} + + cron@4.4.0: + dependencies: + '@types/luxon': 3.7.1 + luxon: 3.7.2 + croner@8.1.2: {} cross-spawn@7.0.6: @@ -2978,12 +7895,43 @@ snapshots: dependencies: ms: 2.1.3 + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decompress-response@10.0.0: + dependencies: + mimic-response: 4.0.0 + + dedent@1.7.2: {} + deep-is@0.1.4: {} + deepmerge@4.3.1: {} + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + delayed-stream@1.0.0: {} + denque@2.1.0: {} + depd@2.0.0: {} + dequal@2.0.3: {} + detect-libc@2.1.2: {} + + detect-newline@3.1.0: {} + + dezalgo@1.0.4: + dependencies: + asap: 2.0.6 + wrappy: 1.0.2 + + diff@4.0.4: {} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 @@ -3031,14 +7979,27 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + eastasianwidth@0.2.0: {} + + electron-to-chromium@1.5.344: {} + + emittery@0.13.1: {} + emoji-regex@10.4.0: {} emoji-regex@8.0.0: {} + emoji-regex@9.2.2: {} + end-of-stream@1.4.4: dependencies: once: 1.4.0 + enhanced-resolve@5.21.0: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + entities@4.5.0: {} env-paths@2.2.1: {} @@ -3053,10 +8014,19 @@ snapshots: es-errors@1.3.0: {} + es-module-lexer@2.1.0: {} + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + esbuild-register@3.6.0(esbuild@0.25.5): dependencies: debug: 4.4.1 @@ -3119,6 +8089,10 @@ snapshots: escalade@3.2.0: {} + escape-html@1.0.3: {} + + escape-string-regexp@2.0.0: {} + escape-string-regexp@4.0.0: {} escape-string-regexp@5.0.0: {} @@ -3127,15 +8101,21 @@ snapshots: dependencies: eslint: 9.28.0(jiti@2.4.2) - eslint-plugin-prettier@5.4.1(eslint-config-prettier@10.1.5(eslint@9.28.0(jiti@2.4.2)))(eslint@9.28.0(jiti@2.4.2))(prettier@3.5.3): + eslint-plugin-prettier@5.4.1(@types/eslint@9.6.1)(eslint-config-prettier@10.1.5(eslint@9.28.0(jiti@2.4.2)))(eslint@9.28.0(jiti@2.4.2))(prettier@3.5.3): dependencies: eslint: 9.28.0(jiti@2.4.2) prettier: 3.5.3 prettier-linter-helpers: 1.0.0 synckit: 0.11.8 optionalDependencies: + '@types/eslint': 9.6.1 eslint-config-prettier: 10.1.5(eslint@9.28.0(jiti@2.4.2)) + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + eslint-scope@8.3.0: dependencies: esrecurse: 4.3.0 @@ -3193,6 +8173,8 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.14.1) eslint-visitor-keys: 4.2.0 + esprima@4.0.1: {} + esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -3201,12 +8183,40 @@ snapshots: dependencies: estraverse: 5.3.0 + estraverse@4.3.0: {} + estraverse@5.3.0: {} + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.7 + esutils@2.0.3: {} eventemitter3@5.0.1: {} + events-universal@1.0.1: + dependencies: + bare-events: 2.8.2 + transitivePeerDependencies: + - bare-abort-controller + + events@3.3.0: {} + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + execa@8.0.1: dependencies: cross-spawn: 7.0.6 @@ -3219,6 +8229,43 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 + execa@9.6.1: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.6 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 8.0.1 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 6.0.0 + pretty-ms: 9.3.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.2 + + exit-x@0.2.2: {} + + expect-type@1.3.0: {} + + expect@30.3.0: + dependencies: + '@jest/expect-utils': 30.3.0 + '@jest/get-type': 30.1.0 + jest-matcher-utils: 30.3.0 + jest-message-util: 30.3.0 + jest-mock: 30.3.0 + jest-util: 30.3.0 + + ext-list@2.2.2: + dependencies: + mime-db: 1.54.0 + + ext-name@5.0.0: + dependencies: + ext-list: 2.2.2 + sort-keys-length: 1.0.1 + fast-copy@3.0.2: {} fast-decode-uri-component@1.0.1: {} @@ -3227,6 +8274,8 @@ snapshots: fast-diff@1.3.0: {} + fast-fifo@1.3.2: {} + fast-glob@3.3.2: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -3270,6 +8319,8 @@ snapshots: fastify-plugin@5.0.1: {} + fastify-plugin@5.1.0: {} + fastify-type-provider-zod@5.0.2(@fastify/swagger@9.5.1)(fastify@5.3.3)(zod@4.0.10): dependencies: '@fastify/error': 4.2.0 @@ -3295,14 +8346,59 @@ snapshots: semver: 7.7.2 toad-cache: 3.7.0 + fastify@5.8.4: + dependencies: + '@fastify/ajv-compiler': 4.0.5 + '@fastify/error': 4.2.0 + '@fastify/fast-json-stringify-compiler': 5.0.3 + '@fastify/proxy-addr': 5.0.0 + abstract-logging: 2.0.1 + avvio: 9.1.0 + fast-json-stringify: 6.0.1 + find-my-way: 9.5.0 + light-my-request: 6.6.0 + pino: 10.3.1 + process-warning: 5.0.0 + rfdc: 1.4.1 + secure-json-parse: 4.0.0 + semver: 7.7.2 + toad-cache: 3.7.0 + fastq@1.19.1: dependencies: reusify: 1.1.0 + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + + figures@6.1.0: + dependencies: + is-unicode-supported: 2.1.0 + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 + file-type@21.3.4: + dependencies: + '@tokenizer/inflate': 0.4.1 + strtok3: 10.3.5 + token-types: 6.1.2 + uint8array-extras: 1.5.0 + transitivePeerDependencies: + - supports-color + + filename-reserved-regex@4.0.0: {} + + filenamify@7.0.1: + dependencies: + filename-reserved-regex: 4.0.0 + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -3313,6 +8409,17 @@ snapshots: fast-querystring: 1.1.2 safe-regex2: 5.0.0 + find-my-way@9.5.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-querystring: 1.1.2 + safe-regex2: 5.0.0 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -3324,6 +8431,11 @@ snapshots: path-exists: 5.0.0 unicorn-magic: 0.1.0 + find-versions@6.0.0: + dependencies: + semver-regex: 4.0.5 + super-regex: 1.1.0 + flat-cache@4.0.1: dependencies: flatted: 3.3.3 @@ -3331,11 +8443,63 @@ snapshots: flatted@3.3.3: {} + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.106.0(@swc/core@1.15.30)(esbuild@0.25.5)): + dependencies: + '@babel/code-frame': 7.27.1 + chalk: 4.1.2 + chokidar: 4.0.3 + cosmiconfig: 8.3.6(typescript@5.9.3) + deepmerge: 4.3.1 + fs-extra: 10.1.0 + memfs: 3.5.3 + minimatch: 3.1.2 + node-abort-controller: 3.1.1 + schema-utils: 3.3.0 + semver: 7.7.2 + tapable: 2.3.3 + typescript: 5.9.3 + webpack: 5.106.0(@swc/core@1.15.30)(esbuild@0.25.5) + + form-data-encoder@4.1.0: {} + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + formidable@3.5.4: + dependencies: + '@paralleldrive/cuid2': 2.3.1 + dezalgo: 1.0.4 + once: 1.4.0 + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fs-monkey@1.1.0: {} + + fs.realpath@1.0.0: {} + fsevents@2.3.3: optional: true function-bind@1.1.2: {} + function-timeout@1.0.2: {} + + gensync@1.0.0-beta.2: {} + get-caller-file@2.0.5: {} get-east-asian-width@1.3.0: {} @@ -3353,13 +8517,22 @@ snapshots: hasown: 2.0.2 math-intrinsics: 1.1.0 + get-package-type@0.1.0: {} + get-proto@1.0.1: dependencies: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 + get-stream@6.0.1: {} + get-stream@8.0.1: {} + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + get-tsconfig@4.10.1: dependencies: resolve-pkg-maps: 1.0.0 @@ -3380,6 +8553,32 @@ snapshots: dependencies: is-glob: 4.0.3 + glob-to-regexp@0.4.1: {} + + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@13.0.6: + dependencies: + minimatch: 10.2.5 + minipass: 7.1.3 + path-scurry: 2.0.2 + + glob@7.2.3: + 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 + global-directory@4.0.1: dependencies: ini: 4.1.1 @@ -3398,99 +8597,558 @@ snapshots: gopd@1.2.0: {} + got@14.6.6: + dependencies: + '@sindresorhus/is': 7.2.0 + byte-counter: 0.1.0 + cacheable-lookup: 7.0.0 + cacheable-request: 13.0.18 + decompress-response: 10.0.0 + form-data-encoder: 4.1.0 + http2-wrapper: 2.2.1 + keyv: 5.6.0 + lowercase-keys: 3.0.0 + p-cancelable: 4.0.1 + responselike: 4.0.2 + type-fest: 4.41.0 + graceful-fs@4.2.11: {} graphemer@1.4.0: {} + handlebars@4.7.9: + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.19.3 + has-flag@4.0.0: {} has-symbols@1.1.0: {} + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + hasown@2.0.2: dependencies: function-bind: 1.1.2 he@1.2.0: {} - helmet@8.1.0: {} + helmet@8.1.0: {} + + help-me@5.0.0: {} + + html-escaper@2.0.2: {} + + http-cache-semantics@4.2.0: {} + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + http2-wrapper@2.2.1: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + + human-signals@2.1.0: {} + + human-signals@5.0.0: {} + + human-signals@8.0.1: {} + + husky@9.1.7: {} + + iconv-lite@0.7.2: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-local@3.2.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + import-meta-resolve@4.1.0: {} + + imurmurhash@0.1.4: {} + + indent-string@5.0.0: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + ini@4.1.1: {} + + inspect-with-kind@1.0.5: + dependencies: + kind-of: 6.0.3 + + ioredis@5.6.1: + dependencies: + '@ioredis/commands': 1.2.0 + cluster-key-slot: 1.1.2 + debug: 4.4.1 + denque: 2.1.0 + lodash.defaults: 4.2.0 + lodash.isarguments: 3.1.0 + redis-errors: 1.2.0 + redis-parser: 3.0.0 + standard-as-callback: 2.1.0 + transitivePeerDependencies: + - supports-color + + ipaddr.js@2.2.0: {} + + is-arrayish@0.2.1: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.0.0: + dependencies: + get-east-asian-width: 1.3.0 + + is-generator-fn@2.1.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-interactive@1.0.0: {} + + is-number@7.0.0: {} + + is-obj@2.0.0: {} + + is-plain-obj@1.1.0: {} + + is-plain-obj@4.1.0: {} + + is-stream@2.0.1: {} + + is-stream@3.0.0: {} + + is-stream@4.0.1: {} + + is-text-path@2.0.0: + dependencies: + text-extensions: 2.4.0 + + is-unicode-supported@0.1.0: {} + + is-unicode-supported@2.1.0: {} + + isexe@2.0.0: {} + + isexe@4.0.0: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-instrument@6.0.3: + dependencies: + '@babel/core': 7.29.0 + '@babel/parser': 7.29.2 + '@istanbuljs/schema': 0.1.6 + istanbul-lib-coverage: 3.2.2 + semver: 7.7.2 + transitivePeerDependencies: + - supports-color + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + debug: 4.4.3 + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + iterare@1.2.1: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jest-changed-files@30.3.0: + dependencies: + execa: 5.1.1 + jest-util: 30.3.0 + p-limit: 3.1.0 + + jest-circus@30.3.0: + dependencies: + '@jest/environment': 30.3.0 + '@jest/expect': 30.3.0 + '@jest/test-result': 30.3.0 + '@jest/types': 30.3.0 + '@types/node': 22.15.29 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.7.2 + is-generator-fn: 2.1.0 + jest-each: 30.3.0 + jest-matcher-utils: 30.3.0 + jest-message-util: 30.3.0 + jest-runtime: 30.3.0 + jest-snapshot: 30.3.0 + jest-util: 30.3.0 + p-limit: 3.1.0 + pretty-format: 30.3.0 + pure-rand: 7.0.1 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-cli@30.3.0(@types/node@22.15.29)(esbuild-register@3.6.0(esbuild@0.25.5))(ts-node@10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3)): + dependencies: + '@jest/core': 30.3.0(esbuild-register@3.6.0(esbuild@0.25.5))(ts-node@10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3)) + '@jest/test-result': 30.3.0 + '@jest/types': 30.3.0 + chalk: 4.1.2 + exit-x: 0.2.2 + import-local: 3.2.0 + jest-config: 30.3.0(@types/node@22.15.29)(esbuild-register@3.6.0(esbuild@0.25.5))(ts-node@10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3)) + jest-util: 30.3.0 + jest-validate: 30.3.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + + jest-config@30.3.0(@types/node@22.15.29)(esbuild-register@3.6.0(esbuild@0.25.5))(ts-node@10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3)): + dependencies: + '@babel/core': 7.29.0 + '@jest/get-type': 30.1.0 + '@jest/pattern': 30.0.1 + '@jest/test-sequencer': 30.3.0 + '@jest/types': 30.3.0 + babel-jest: 30.3.0(@babel/core@7.29.0) + chalk: 4.1.2 + ci-info: 4.4.0 + deepmerge: 4.3.1 + glob: 10.5.0 + graceful-fs: 4.2.11 + jest-circus: 30.3.0 + jest-docblock: 30.2.0 + jest-environment-node: 30.3.0 + jest-regex-util: 30.0.1 + jest-resolve: 30.3.0 + jest-runner: 30.3.0 + jest-util: 30.3.0 + jest-validate: 30.3.0 + parse-json: 5.2.0 + pretty-format: 30.3.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 22.15.29 + esbuild-register: 3.6.0(esbuild@0.25.5) + ts-node: 10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-diff@30.3.0: + dependencies: + '@jest/diff-sequences': 30.3.0 + '@jest/get-type': 30.1.0 + chalk: 4.1.2 + pretty-format: 30.3.0 - help-me@5.0.0: {} + jest-docblock@30.2.0: + dependencies: + detect-newline: 3.1.0 - human-signals@5.0.0: {} + jest-each@30.3.0: + dependencies: + '@jest/get-type': 30.1.0 + '@jest/types': 30.3.0 + chalk: 4.1.2 + jest-util: 30.3.0 + pretty-format: 30.3.0 - husky@9.1.7: {} + jest-environment-node@30.3.0: + dependencies: + '@jest/environment': 30.3.0 + '@jest/fake-timers': 30.3.0 + '@jest/types': 30.3.0 + '@types/node': 22.15.29 + jest-mock: 30.3.0 + jest-util: 30.3.0 + jest-validate: 30.3.0 - ignore@5.3.2: {} + jest-haste-map@30.3.0: + dependencies: + '@jest/types': 30.3.0 + '@types/node': 22.15.29 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 30.0.1 + jest-util: 30.3.0 + jest-worker: 30.3.0 + picomatch: 4.0.4 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 - ignore@7.0.5: {} + jest-leak-detector@30.3.0: + dependencies: + '@jest/get-type': 30.1.0 + pretty-format: 30.3.0 - import-fresh@3.3.1: + jest-matcher-utils@30.3.0: dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 + '@jest/get-type': 30.1.0 + chalk: 4.1.2 + jest-diff: 30.3.0 + pretty-format: 30.3.0 - import-meta-resolve@4.1.0: {} + jest-message-util@30.3.0: + dependencies: + '@babel/code-frame': 7.27.1 + '@jest/types': 30.3.0 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + picomatch: 4.0.4 + pretty-format: 30.3.0 + slash: 3.0.0 + stack-utils: 2.0.6 - imurmurhash@0.1.4: {} + jest-mock@30.3.0: + dependencies: + '@jest/types': 30.3.0 + '@types/node': 22.15.29 + jest-util: 30.3.0 - indent-string@5.0.0: {} + jest-pnp-resolver@1.2.3(jest-resolve@30.3.0): + optionalDependencies: + jest-resolve: 30.3.0 - ini@4.1.1: {} + jest-regex-util@30.0.1: {} - ioredis@5.6.1: + jest-resolve-dependencies@30.3.0: dependencies: - '@ioredis/commands': 1.2.0 - cluster-key-slot: 1.1.2 - debug: 4.4.1 - denque: 2.1.0 - lodash.defaults: 4.2.0 - lodash.isarguments: 3.1.0 - redis-errors: 1.2.0 - redis-parser: 3.0.0 - standard-as-callback: 2.1.0 + jest-regex-util: 30.0.1 + jest-snapshot: 30.3.0 transitivePeerDependencies: - supports-color - ipaddr.js@2.2.0: {} - - is-arrayish@0.2.1: {} - - is-extglob@2.1.1: {} + jest-resolve@30.3.0: + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 30.3.0 + jest-pnp-resolver: 1.2.3(jest-resolve@30.3.0) + jest-util: 30.3.0 + jest-validate: 30.3.0 + slash: 3.0.0 + unrs-resolver: 1.11.1 + + jest-runner@30.3.0: + dependencies: + '@jest/console': 30.3.0 + '@jest/environment': 30.3.0 + '@jest/test-result': 30.3.0 + '@jest/transform': 30.3.0 + '@jest/types': 30.3.0 + '@types/node': 22.15.29 + chalk: 4.1.2 + emittery: 0.13.1 + exit-x: 0.2.2 + graceful-fs: 4.2.11 + jest-docblock: 30.2.0 + jest-environment-node: 30.3.0 + jest-haste-map: 30.3.0 + jest-leak-detector: 30.3.0 + jest-message-util: 30.3.0 + jest-resolve: 30.3.0 + jest-runtime: 30.3.0 + jest-util: 30.3.0 + jest-watcher: 30.3.0 + jest-worker: 30.3.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color - is-fullwidth-code-point@3.0.0: {} + jest-runtime@30.3.0: + dependencies: + '@jest/environment': 30.3.0 + '@jest/fake-timers': 30.3.0 + '@jest/globals': 30.3.0 + '@jest/source-map': 30.0.1 + '@jest/test-result': 30.3.0 + '@jest/transform': 30.3.0 + '@jest/types': 30.3.0 + '@types/node': 22.15.29 + chalk: 4.1.2 + cjs-module-lexer: 2.2.0 + collect-v8-coverage: 1.0.3 + glob: 10.5.0 + graceful-fs: 4.2.11 + jest-haste-map: 30.3.0 + jest-message-util: 30.3.0 + jest-mock: 30.3.0 + jest-regex-util: 30.0.1 + jest-resolve: 30.3.0 + jest-snapshot: 30.3.0 + jest-util: 30.3.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color - is-fullwidth-code-point@4.0.0: {} + jest-snapshot@30.3.0: + dependencies: + '@babel/core': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) + '@babel/types': 7.29.0 + '@jest/expect-utils': 30.3.0 + '@jest/get-type': 30.1.0 + '@jest/snapshot-utils': 30.3.0 + '@jest/transform': 30.3.0 + '@jest/types': 30.3.0 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0) + chalk: 4.1.2 + expect: 30.3.0 + graceful-fs: 4.2.11 + jest-diff: 30.3.0 + jest-matcher-utils: 30.3.0 + jest-message-util: 30.3.0 + jest-util: 30.3.0 + pretty-format: 30.3.0 + semver: 7.7.2 + synckit: 0.11.8 + transitivePeerDependencies: + - supports-color - is-fullwidth-code-point@5.0.0: + jest-util@30.3.0: dependencies: - get-east-asian-width: 1.3.0 + '@jest/types': 30.3.0 + '@types/node': 22.15.29 + chalk: 4.1.2 + ci-info: 4.4.0 + graceful-fs: 4.2.11 + picomatch: 4.0.4 - is-glob@4.0.3: + jest-validate@30.3.0: dependencies: - is-extglob: 2.1.1 - - is-number@7.0.0: {} + '@jest/get-type': 30.1.0 + '@jest/types': 30.3.0 + camelcase: 6.3.0 + chalk: 4.1.2 + leven: 3.1.0 + pretty-format: 30.3.0 - is-obj@2.0.0: {} + jest-watcher@30.3.0: + dependencies: + '@jest/test-result': 30.3.0 + '@jest/types': 30.3.0 + '@types/node': 22.15.29 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 30.3.0 + string-length: 4.0.2 - is-stream@3.0.0: {} + jest-worker@27.5.1: + dependencies: + '@types/node': 22.15.29 + merge-stream: 2.0.0 + supports-color: 8.1.1 - is-text-path@2.0.0: + jest-worker@30.3.0: dependencies: - text-extensions: 2.4.0 + '@types/node': 22.15.29 + '@ungap/structured-clone': 1.3.0 + jest-util: 30.3.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 - isexe@2.0.0: {} + jest@30.3.0(@types/node@22.15.29)(esbuild-register@3.6.0(esbuild@0.25.5))(ts-node@10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3)): + dependencies: + '@jest/core': 30.3.0(esbuild-register@3.6.0(esbuild@0.25.5))(ts-node@10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3)) + '@jest/types': 30.3.0 + import-local: 3.2.0 + jest-cli: 30.3.0(@types/node@22.15.29)(esbuild-register@3.6.0(esbuild@0.25.5))(ts-node@10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3)) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node jiti@2.4.2: {} joycon@3.1.1: {} + js-tokens@10.0.0: {} + js-tokens@4.0.0: {} + js-yaml@3.14.2: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + js-yaml@4.1.0: dependencies: argparse: 2.0.1 + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + json-buffer@3.0.1: {} json-parse-even-better-errors@2.3.1: {} @@ -3513,6 +9171,16 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + json5@2.2.3: {} + + jsonc-parser@3.3.1: {} + + jsonfile@6.2.1: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + jsonparse@1.3.1: {} jsonpointer@5.0.1: {} @@ -3523,6 +9191,14 @@ snapshots: dependencies: json-buffer: 3.0.1 + keyv@5.6.0: + dependencies: + '@keyv/serialize': 1.1.1 + + kind-of@6.0.3: {} + + leven@3.1.0: {} + leven@4.0.0: {} levn@0.4.1: @@ -3536,6 +9212,55 @@ snapshots: process-warning: 4.0.1 set-cookie-parser: 2.7.1 + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + lilconfig@3.1.3: {} lines-and-columns@1.2.4: {} @@ -3564,6 +9289,16 @@ snapshots: rfdc: 1.4.1 wrap-ansi: 9.0.0 + load-esm@1.0.3: {} + + load-tsconfig@0.2.5: {} + + loader-runner@4.3.2: {} + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -3582,6 +9317,8 @@ snapshots: lodash.kebabcase@4.1.1: {} + lodash.memoize@4.1.2: {} + lodash.merge@4.6.2: {} lodash.mergewith@4.6.2: {} @@ -3594,6 +9331,13 @@ snapshots: lodash.upperfirst@4.3.1: {} + lodash@4.18.1: {} + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + log-update@6.1.0: dependencies: ansi-escapes: 7.0.0 @@ -3606,23 +9350,91 @@ snapshots: dependencies: tslib: 2.8.1 + lowercase-keys@3.0.0: {} + + lru-cache@10.4.3: {} + + lru-cache@11.3.5: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + luxon@3.7.2: {} + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + magicast@0.5.2: + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + source-map-js: 1.2.1 + + make-asynchronous@1.1.0: + dependencies: + p-event: 6.0.1 + type-fest: 4.41.0 + web-worker: 1.5.0 + + make-dir@4.0.0: + dependencies: + semver: 7.7.2 + + make-error@1.3.6: {} + + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + math-intrinsics@1.1.0: {} + memfs@3.5.3: + dependencies: + fs-monkey: 1.1.0 + meow@12.1.1: {} merge-stream@2.0.0: {} merge2@1.4.1: {} + methods@1.1.2: {} + micromatch@4.0.8: dependencies: braces: 3.0.3 picomatch: 2.3.1 + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@2.6.0: {} + + mime@3.0.0: {} + + mimic-fn@2.1.0: {} + mimic-fn@4.0.0: {} mimic-function@5.0.1: {} + mimic-response@4.0.0: {} + + minimatch@10.2.5: + dependencies: + brace-expansion: 5.0.5 + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -3633,19 +9445,53 @@ snapshots: minimist@1.2.8: {} + minipass@7.1.3: {} + ms@2.1.3: {} + mute-stream@2.0.0: {} + + nanoid@3.3.11: {} + nanoid@5.1.5: {} + nanoid@5.1.9: {} + + napi-postinstall@0.3.4: {} + natural-compare@1.4.0: {} + neo-async@2.6.2: {} + nested-error-stacks@2.1.1: {} + nestjs-pino@4.6.1(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(pino-http@11.0.0)(pino@10.3.1)(rxjs@7.8.2): + dependencies: + '@nestjs/common': 11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2) + pino: 10.3.1 + pino-http: 11.0.0 + rxjs: 7.8.2 + + nestjs-zod@5.3.0(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/swagger@11.4.1(@fastify/static@9.1.3)(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2))(rxjs@7.8.2)(zod@4.0.10): + dependencies: + '@nestjs/common': 11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2) + deepmerge: 4.3.1 + rxjs: 7.8.2 + zod: 4.0.10 + optionalDependencies: + '@nestjs/swagger': 11.4.1(@fastify/static@9.1.3)(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19(@nestjs/common@11.1.19(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2) + no-case@3.0.4: dependencies: lower-case: 2.0.2 tslib: 2.8.1 + node-abort-controller@3.1.1: {} + + node-emoji@1.11.0: + dependencies: + lodash: 4.18.1 + node-html-markdown@2.0.0: dependencies: node-html-parser: 6.1.13 @@ -3655,24 +9501,47 @@ snapshots: css-select: 5.2.2 he: 1.2.0 + node-int64@0.4.0: {} + node-object-hash@3.1.1: {} + node-releases@2.0.38: {} + + normalize-path@3.0.0: {} + + normalize-url@8.1.1: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + npm-run-path@5.3.0: dependencies: path-key: 4.0.0 + npm-run-path@6.0.0: + dependencies: + path-key: 4.0.0 + unicorn-magic: 0.3.0 + nth-check@2.1.1: dependencies: boolbase: 1.0.0 object-inspect@1.13.4: {} + obug@2.1.1: {} + on-exit-leak-free@2.1.2: {} once@1.4.0: dependencies: wrappy: 1.0.2 + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + onetime@6.0.0: dependencies: mimic-fn: 4.0.0 @@ -3692,14 +9561,36 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 + ora@5.4.1: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + + p-cancelable@4.0.1: {} + p-event@5.0.1: dependencies: p-timeout: 5.1.0 + p-event@6.0.1: + dependencies: + p-timeout: 6.1.4 + p-filter@3.0.0: dependencies: p-map: 5.5.0 + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 @@ -3708,6 +9599,10 @@ snapshots: dependencies: yocto-queue: 1.2.1 + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + p-locate@5.0.0: dependencies: p-limit: 3.1.0 @@ -3724,6 +9619,12 @@ snapshots: p-timeout@5.1.0: {} + p-timeout@6.1.4: {} + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -3735,6 +9636,8 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + parse-ms@4.0.0: {} + pascal-case@3.1.2: dependencies: no-case: 3.0.4 @@ -3744,22 +9647,53 @@ snapshots: path-exists@5.0.0: {} + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} path-key@4.0.0: {} + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 + + path-scurry@2.0.2: + dependencies: + lru-cache: 11.3.5 + minipass: 7.1.3 + + path-to-regexp@8.4.2: {} + path-type@4.0.0: {} + pathe@2.0.3: {} + + pend@1.2.0: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} + picomatch@4.0.4: {} + pidtree@0.6.0: {} pino-abstract-transport@2.0.0: dependencies: split2: 4.2.0 + pino-abstract-transport@3.0.0: + dependencies: + split2: 4.2.0 + + pino-http@11.0.0: + dependencies: + get-caller-file: 2.0.5 + pino: 10.3.1 + pino-std-serializers: 7.0.0 + process-warning: 5.0.0 + pino-pretty@13.0.0: dependencies: colorette: 2.0.20 @@ -3778,6 +9712,20 @@ snapshots: pino-std-serializers@7.0.0: {} + pino@10.3.1: + dependencies: + '@pinojs/redact': 0.4.0 + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 3.0.0 + pino-std-serializers: 7.0.0 + process-warning: 5.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 4.0.0 + pino@9.7.0: dependencies: atomic-sleep: 1.0.0 @@ -3792,6 +9740,24 @@ snapshots: sonic-boom: 4.2.0 thread-stream: 3.1.0 + pirates@4.0.7: {} + + piscina@4.9.2: + optionalDependencies: + '@napi-rs/nice': 1.1.1 + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + + pluralize@8.0.0: {} + + postcss@8.5.10: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + postgres@3.4.7: {} prelude-ls@1.2.1: {} @@ -3802,6 +9768,16 @@ snapshots: prettier@3.5.3: {} + pretty-format@30.3.0: + dependencies: + '@jest/schemas': 30.0.5 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + pretty-ms@9.3.0: + dependencies: + parse-ms: 4.0.0 + process-warning@4.0.1: {} process-warning@5.0.0: {} @@ -3813,14 +9789,32 @@ snapshots: punycode@2.3.1: {} + pure-rand@7.0.1: {} + qs@6.14.0: dependencies: side-channel: 1.1.0 + qs@6.15.1: + dependencies: + side-channel: 1.1.0 + queue-microtask@1.2.3: {} quick-format-unescaped@4.0.4: {} + quick-lru@5.1.1: {} + + react-is@18.3.1: {} + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@4.1.2: {} + real-require@0.2.0: {} redis-errors@1.2.0: {} @@ -3829,10 +9823,18 @@ snapshots: dependencies: redis-errors: 1.2.0 + reflect-metadata@0.2.2: {} + require-directory@2.1.1: {} require-from-string@2.0.2: {} + resolve-alpn@1.2.1: {} + + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + resolve-from@4.0.0: {} resolve-from@5.0.0: {} @@ -3846,6 +9848,15 @@ snapshots: fast-glob: 3.3.2 typescript: 5.8.3 + responselike@4.0.2: + dependencies: + lowercase-keys: 3.0.0 + + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + restore-cursor@5.1.0: dependencies: onetime: 7.0.0 @@ -3857,24 +9868,91 @@ snapshots: rfdc@1.4.1: {} + rimraf@6.1.3: + dependencies: + glob: 13.0.6 + package-json-from-dist: 1.0.1 + + rolldown@1.0.0-rc.17: + dependencies: + '@oxc-project/types': 0.127.0 + '@rolldown/pluginutils': 1.0.0-rc.17 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-rc.17 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.17 + '@rolldown/binding-darwin-x64': 1.0.0-rc.17 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.17 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.17 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.17 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.17 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.17 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.17 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.17 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.17 + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 + rxjs@7.8.1: + dependencies: + tslib: 2.8.1 + + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + + safe-buffer@5.2.1: {} + safe-regex2@5.0.0: dependencies: ret: 0.5.0 safe-stable-stringify@2.5.0: {} + safer-buffer@2.1.2: {} + + schema-utils@3.3.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + + schema-utils@4.3.3: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + ajv-keywords: 5.1.0(ajv@8.17.1) + secure-json-parse@2.7.0: {} secure-json-parse@4.0.0: {} + seek-bzip@2.0.0: + dependencies: + commander: 6.2.1 + + semver-regex@4.0.5: {} + + semver-truncate@3.0.0: + dependencies: + semver: 7.7.2 + + semver@6.3.1: {} + semver@7.7.2: {} + semver@7.7.4: {} + set-cookie-parser@2.7.1: {} + setprototypeof@1.2.0: {} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -3909,10 +9987,16 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} + + signal-exit@3.0.7: {} + signal-exit@4.1.0: {} sisteransi@1.0.5: {} + slash@3.0.0: {} + slash@4.0.0: {} slice-ansi@5.0.0: @@ -3929,6 +10013,21 @@ snapshots: dependencies: atomic-sleep: 1.0.0 + sort-keys-length@1.0.1: + dependencies: + sort-keys: 1.1.2 + + sort-keys@1.1.2: + dependencies: + is-plain-obj: 1.1.0 + + source-map-js@1.2.1: {} + + source-map-support@0.5.13: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 @@ -3936,24 +10035,64 @@ snapshots: source-map@0.6.1: {} + source-map@0.7.4: {} + + source-map@0.7.6: {} + split2@4.2.0: {} + sprintf-js@1.0.3: {} + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + + stackback@0.0.2: {} + standard-as-callback@2.1.0: {} + statuses@2.0.2: {} + + std-env@4.1.0: {} + + streamx@2.25.0: + dependencies: + events-universal: 1.0.1 + fast-fifo: 1.3.2 + text-decoder: 1.2.7 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + string-argv@0.3.2: {} + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + string-width@7.2.0: dependencies: emoji-regex: 10.4.0 get-east-asian-width: 1.3.0 strip-ansi: 7.1.0 + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -3962,28 +10101,153 @@ snapshots: dependencies: ansi-regex: 6.1.0 + strip-bom@3.0.0: {} + + strip-bom@4.0.0: {} + + strip-dirs@3.0.0: + dependencies: + inspect-with-kind: 1.0.5 + is-plain-obj: 1.1.0 + + strip-final-newline@2.0.0: {} + strip-final-newline@3.0.0: {} + strip-final-newline@4.0.0: {} + strip-json-comments@3.1.1: {} + strtok3@10.3.5: + dependencies: + '@tokenizer/token': 0.3.0 + + super-regex@1.1.0: + dependencies: + function-timeout: 1.0.2 + make-asynchronous: 1.1.0 + time-span: 5.1.0 + + superagent@10.3.0: + dependencies: + component-emitter: 1.3.1 + cookiejar: 2.1.4 + debug: 4.4.3 + fast-safe-stringify: 2.1.1 + form-data: 4.0.5 + formidable: 3.5.4 + methods: 1.1.2 + mime: 2.6.0 + qs: 6.15.1 + transitivePeerDependencies: + - supports-color + + supertest@7.2.2: + dependencies: + cookie-signature: 1.2.2 + methods: 1.1.2 + superagent: 10.3.0 + transitivePeerDependencies: + - supports-color + supports-color@7.2.0: dependencies: has-flag: 4.0.0 + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + swagger-ui-dist@5.32.4: + dependencies: + '@scarf/scarf': 1.4.0 + + symbol-observable@4.0.0: {} + synckit@0.11.8: dependencies: '@pkgr/core': 0.2.7 + tagged-tag@1.0.0: {} + + tapable@2.3.3: {} + + tar-stream@3.1.7: + dependencies: + b4a: 1.8.0 + fast-fifo: 1.3.2 + streamx: 2.25.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + temporal-polyfill@0.3.2: + dependencies: + temporal-spec: 0.3.1 + + temporal-spec@0.3.1: {} + + terser-webpack-plugin@5.5.0(@swc/core@1.15.30)(esbuild@0.25.5)(webpack@5.106.0(@swc/core@1.15.30)(esbuild@0.25.5)): + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + jest-worker: 27.5.1 + schema-utils: 4.3.3 + terser: 5.46.2 + webpack: 5.106.0(@swc/core@1.15.30)(esbuild@0.25.5) + optionalDependencies: + '@swc/core': 1.15.30 + esbuild: 0.25.5 + + terser@5.46.2: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.16.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.6 + glob: 7.2.3 + minimatch: 3.1.2 + + text-decoder@1.2.7: + dependencies: + b4a: 1.8.0 + transitivePeerDependencies: + - react-native-b4a + text-extensions@2.4.0: {} thread-stream@3.1.0: dependencies: real-require: 0.2.0 + thread-stream@4.0.0: + dependencies: + real-require: 0.2.0 + through@2.3.8: {} + time-span@5.1.0: + dependencies: + convert-hrtime: 5.0.0 + + tinybench@2.9.0: {} + tinyexec@1.0.1: {} + tinyexec@1.1.1: {} + + tinyglobby@0.2.16: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + tinyrainbow@3.1.0: {} + + tmpl@1.0.5: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -3994,10 +10258,82 @@ snapshots: dependencies: croner: 8.1.2 + toidentifier@1.0.1: {} + + token-types@6.1.2: + dependencies: + '@borewit/text-codec': 0.2.2 + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + ts-api-utils@2.1.0(typescript@5.8.3): dependencies: typescript: 5.8.3 + ts-jest@29.4.9(@babel/core@7.29.0)(@jest/transform@30.3.0)(@jest/types@30.3.0)(babel-jest@30.3.0(@babel/core@7.29.0))(esbuild@0.25.5)(jest-util@30.3.0)(jest@30.3.0(@types/node@22.15.29)(esbuild-register@3.6.0(esbuild@0.25.5))(ts-node@10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3)))(typescript@5.8.3): + dependencies: + bs-logger: 0.2.6 + fast-json-stable-stringify: 2.1.0 + handlebars: 4.7.9 + jest: 30.3.0(@types/node@22.15.29)(esbuild-register@3.6.0(esbuild@0.25.5))(ts-node@10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3)) + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.7.4 + type-fest: 4.41.0 + typescript: 5.8.3 + yargs-parser: 21.1.1 + optionalDependencies: + '@babel/core': 7.29.0 + '@jest/transform': 30.3.0 + '@jest/types': 30.3.0 + babel-jest: 30.3.0(@babel/core@7.29.0) + esbuild: 0.25.5 + jest-util: 30.3.0 + + ts-loader@9.5.7(typescript@5.8.3)(webpack@5.106.0(@swc/core@1.15.30)(esbuild@0.25.5)): + dependencies: + chalk: 4.1.2 + enhanced-resolve: 5.21.0 + micromatch: 4.0.8 + semver: 7.7.2 + source-map: 0.7.6 + typescript: 5.8.3 + webpack: 5.106.0(@swc/core@1.15.30)(esbuild@0.25.5) + + ts-node@10.9.2(@swc/core@1.15.30)(@types/node@22.15.29)(typescript@5.8.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.12 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 22.15.29 + acorn: 8.16.0 + acorn-walk: 8.3.5 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.4 + make-error: 1.3.6 + typescript: 5.8.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optionalDependencies: + '@swc/core': 1.15.30 + + tsconfig-paths-webpack-plugin@4.2.0: + dependencies: + chalk: 4.1.2 + enhanced-resolve: 5.21.0 + tapable: 2.3.3 + tsconfig-paths: 4.2.0 + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + tslib@2.8.1: {} tsx@4.19.4: @@ -4011,6 +10347,16 @@ snapshots: dependencies: prelude-ls: 1.2.1 + type-detect@4.0.8: {} + + type-fest@0.21.3: {} + + type-fest@4.41.0: {} + + type-fest@5.6.0: + dependencies: + tagged-tag: 1.0.0 + typescript-eslint@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3): dependencies: '@typescript-eslint/eslint-plugin': 8.33.1(@typescript-eslint/parser@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) @@ -4023,26 +10369,218 @@ snapshots: typescript@5.8.3: {} + typescript@5.9.3: {} + + uglify-js@3.19.3: + optional: true + + uid@2.0.2: + dependencies: + '@lukeed/csprng': 1.1.0 + + uint8array-extras@1.5.0: {} + + unbzip2-stream@1.4.3: + dependencies: + buffer: 5.7.1 + through: 2.3.8 + undici-types@6.21.0: {} unicorn-magic@0.1.0: {} + unicorn-magic@0.3.0: {} + + universalify@2.0.1: {} + + unplugin-swc@1.5.9(@swc/core@1.15.30): + dependencies: + '@rollup/pluginutils': 5.3.0 + '@swc/core': 1.15.30 + load-tsconfig: 0.2.5 + unplugin: 2.3.11 + transitivePeerDependencies: + - rollup + + unplugin@2.3.11: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.16.0 + picomatch: 4.0.4 + webpack-virtual-modules: 0.6.2 + + unrs-resolver@1.11.1: + dependencies: + napi-postinstall: 0.3.4 + optionalDependencies: + '@unrs/resolver-binding-android-arm-eabi': 1.11.1 + '@unrs/resolver-binding-android-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-x64': 1.11.1 + '@unrs/resolver-binding-freebsd-x64': 1.11.1 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 + '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-musl': 1.11.1 + '@unrs/resolver-binding-wasm32-wasi': 1.11.1 + '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 + '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 + '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 + + update-browserslist-db@1.2.3(browserslist@4.28.2): + dependencies: + browserslist: 4.28.2 + escalade: 3.2.0 + picocolors: 1.1.1 + uri-js@4.4.1: dependencies: punycode: 2.3.1 + util-deprecate@1.0.2: {} + + v8-compile-cache-lib@3.0.1: {} + + v8-to-istanbul@9.3.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + + vite@8.0.10(@types/node@22.15.29)(esbuild@0.25.5)(jiti@2.4.2)(terser@5.46.2)(tsx@4.19.4)(yaml@2.8.0): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.10 + rolldown: 1.0.0-rc.17 + tinyglobby: 0.2.16 + optionalDependencies: + '@types/node': 22.15.29 + esbuild: 0.25.5 + fsevents: 2.3.3 + jiti: 2.4.2 + terser: 5.46.2 + tsx: 4.19.4 + yaml: 2.8.0 + + vitest@4.1.5(@types/node@22.15.29)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@22.15.29)(esbuild@0.25.5)(jiti@2.4.2)(terser@5.46.2)(tsx@4.19.4)(yaml@2.8.0)): + dependencies: + '@vitest/expect': 4.1.5 + '@vitest/mocker': 4.1.5(vite@8.0.10(@types/node@22.15.29)(esbuild@0.25.5)(jiti@2.4.2)(terser@5.46.2)(tsx@4.19.4)(yaml@2.8.0)) + '@vitest/pretty-format': 4.1.5 + '@vitest/runner': 4.1.5 + '@vitest/snapshot': 4.1.5 + '@vitest/spy': 4.1.5 + '@vitest/utils': 4.1.5 + es-module-lexer: 2.1.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.1.0 + tinybench: 2.9.0 + tinyexec: 1.1.1 + tinyglobby: 0.2.16 + tinyrainbow: 3.1.0 + vite: 8.0.10(@types/node@22.15.29)(esbuild@0.25.5)(jiti@2.4.2)(terser@5.46.2)(tsx@4.19.4)(yaml@2.8.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.15.29 + '@vitest/coverage-v8': 4.1.5(vitest@4.1.5) + transitivePeerDependencies: + - msw + + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + + watchpack@2.5.1: + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + + web-worker@1.5.0: {} + + webpack-node-externals@3.0.0: {} + + webpack-sources@3.4.0: {} + + webpack-virtual-modules@0.6.2: {} + + webpack@5.106.0(@swc/core@1.15.30)(esbuild@0.25.5): + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/wasm-edit': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + acorn: 8.16.0 + acorn-import-phases: 1.0.4(acorn@8.16.0) + browserslist: 4.28.2 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.21.0 + es-module-lexer: 2.1.0 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.2 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 4.3.3 + tapable: 2.3.3 + terser-webpack-plugin: 5.5.0(@swc/core@1.15.30)(esbuild@0.25.5)(webpack@5.106.0(@swc/core@1.15.30)(esbuild@0.25.5)) + watchpack: 2.5.1 + webpack-sources: 3.4.0 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + which@2.0.2: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + word-wrap@1.2.5: {} + wordwrap@1.0.0: {} + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + wrap-ansi@9.0.0: dependencies: ansi-styles: 6.2.1 @@ -4051,8 +10589,15 @@ snapshots: wrappy@1.0.2: {} + write-file-atomic@5.0.1: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + y18n@5.0.8: {} + yallist@3.1.1: {} + yaml@2.8.0: {} yargs-parser@21.1.1: {} @@ -4067,10 +10612,23 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yauzl@3.3.0: + dependencies: + buffer-crc32: 0.2.13 + pend: 1.2.0 + + yn@3.1.1: {} + yocto-queue@0.1.0: {} yocto-queue@1.2.1: {} + yoctocolors-cjs@2.1.3: {} + + yoctocolors@2.1.2: {} + zod@3.24.1: {} zod@4.0.10: {} + + zod@4.3.6: {} diff --git a/reset.d.ts b/reset.d.ts new file mode 100644 index 0000000..69fc8bf --- /dev/null +++ b/reset.d.ts @@ -0,0 +1 @@ +import '@total-typescript/ts-reset' diff --git a/scripts/depsCheck.js b/scripts/depsCheck.js deleted file mode 100644 index 4965c9b..0000000 --- a/scripts/depsCheck.js +++ /dev/null @@ -1,59 +0,0 @@ -import { execSync } from 'node:child_process' -import { createHash } from 'node:crypto' -import { readFile, writeFile, mkdir } from 'node:fs/promises' -import { existsSync } from 'node:fs' -import { resolve, dirname } from 'node:path' - -const installCmd = new Map([ - ['npm', 'npm i'], - ['yarn', 'yarn'], - ['pnpm', 'pnpm i'], -]) - -const lockFiles = new Map([ - ['npm', 'package-lock.json'], - ['yarn', 'yarn.lock'], - ['pnpm', 'pnpm-lock.yaml'], -]) - -const isLockfileExist = (pm) => { - return existsSync(resolve(dirname('../'), `./${lockFiles.get(pm)}`)) -} - -const identifyPackageManager = () => { - if (isLockfileExist('npm')) { - return 'npm' - } else if (isLockfileExist('yarn')) { - return 'yarn' - } else if (isLockfileExist('pnpm')) { - return 'pnpm' - } else { - console.error('No lockfile found') - process.exit(1) - } -} - -const packageManager = identifyPackageManager() - -await mkdir(resolve(dirname('../'), './node_modules/.cache')).catch(() => {}) - -const cachePath = resolve( - dirname('../'), - './node_modules/.cache/deps_check_lock_hash.txt', -) - -const lockFilePath = resolve(dirname('../'), lockFiles.get(packageManager)) - -const lockHashCache = await readFile(cachePath, { - encoding: 'utf-8', - flag: 'a+', -}).catch(() => {}) - -const lockHash = createHash('sha256') - .update(await readFile(lockFilePath, { encoding: 'utf-8' })) - .digest('hex') - -if (lockHashCache !== lockHash) { - execSync(installCmd.get(packageManager), { stdio: 'inherit' }) - await writeFile(cachePath, lockHash) -} diff --git a/src/app.module.ts b/src/app.module.ts new file mode 100644 index 0000000..b8e04da --- /dev/null +++ b/src/app.module.ts @@ -0,0 +1,28 @@ +import { Module } from '@nestjs/common' +import { CacheModule } from './components/cache/cache.module' +import { ConfigModule } from './components/config/config.module' +import { HealthModule } from './components/health/health.module' +import { DatabaseModule } from './components/database/database.module' +import { ScheduleModule } from '@nestjs/schedule' +import { LoggerModule } from 'nestjs-pino' + +@Module({ + imports: [ + LoggerModule.forRoot({ + pinoHttp: { + transport: + process.env.NODE_ENV !== 'production' + ? { target: 'pino-pretty' } + : undefined, + }, + }), + ScheduleModule.forRoot(), + + // Components + ConfigModule, + CacheModule, + DatabaseModule, + HealthModule, + ], +}) +export class AppModule {} diff --git a/src/app.ts b/src/app.ts deleted file mode 100644 index 6c9b886..0000000 --- a/src/app.ts +++ /dev/null @@ -1,172 +0,0 @@ -import type { AppInstance } from '@/core/types/common.js' -import { env } from '@/env.js' -import { registerDependencies } from '@/infrastructure/parentDiConfig.js' -import { diContainer, fastifyAwilixPlugin } from '@fastify/awilix' -import fastifyCookie from '@fastify/cookie' -import fastifyCors from '@fastify/cors' -import fastifyHelmet from '@fastify/helmet' -import fastifyRateLimit from '@fastify/rate-limit' -import fastifySchedule from '@fastify/schedule' -import fastifySwagger from '@fastify/swagger' -import scalarApiReference from '@scalar/fastify-api-reference' -import fastify from 'fastify' -import { - createJsonSchemaTransform, - serializerCompiler, - validatorCompiler, - type ZodTypeProvider, -} from 'fastify-type-provider-zod' -import { AsyncTask, CronJob } from 'toad-scheduler' -import { getRoutes } from './modules/index.js' -import qs from 'qs' -import { CLIENT_COOKIE_NAME } from './modules/links/constants/index.js' -import { cistPostmanJob } from './modules/schedule/jobs/postman.js' - -export class App { - private readonly app: AppInstance - - constructor() { - this.app = fastify({ - querystringParser: qs.parse, - logger: { - transport: { - target: 'pino-pretty', - options: { - colorize: true, - }, - }, - }, - }) - } - - private async registerPlugins(): Promise { - this.app.setValidatorCompiler(validatorCompiler) - this.app.setSerializerCompiler(serializerCompiler) - - await this.app.register(fastifyCors, { - origin: env.ALLOWED_ORIGINS, - credentials: true, - methods: ['GET', 'PUT', 'PATCH', 'POST', 'DELETE', 'OPTIONS'], - }) - - await this.app.register(fastifyHelmet, { - contentSecurityPolicy: { - directives: { - 'script-src': [ - "'self'", - "'sha256-rEoKEh+ixY/s4bkl+CNhaCR+cWdAJ6YviVnKiRKmB9o='", - ], - }, - }, - }) - - await this.app.register(fastifySwagger, { - transform: createJsonSchemaTransform({ - skipList: [ - '/documentation', - '/documentation/initOAuth', - '/documentation/json', - '/documentation/uiConfig', - '/documentation/yaml', - '/documentation/*', - '/documentation/static/*', - '*', - ], - }), - openapi: { - info: { - title: 'Mindenit Schedule API', - description: 'API for Mindenit Schedule application', - version: '1.0.0', - }, - components: { - securitySchemes: { - CookieAuth: { - type: 'apiKey', - in: 'cookie', - name: CLIENT_COOKIE_NAME, - }, - }, - }, - }, - }) - - await this.app.register(scalarApiReference, { - routePrefix: '/api', - }) - - await this.app.register(fastifyAwilixPlugin, { - disposeOnClose: true, - asyncDispose: true, - asyncInit: true, - eagerInject: true, - disposeOnResponse: true, - }) - - await this.app.register(fastifyCookie, { - secret: env.COOKIE_SECRET, - hook: 'preHandler', - }) - - await this.app.register(fastifyRateLimit, { - max: 100, - ban: 150, - timeWindow: 15 * 1000, - allowList: ['127.0.0.1'], - }) - - this.app.register(fastifySchedule) - - registerDependencies(diContainer, { app: this.app }) - } - - private registerRoutes(): void { - const { routes } = getRoutes() - - this.app.register( - (instance, _, done) => { - for (const route of routes) { - instance.withTypeProvider().route(route) - } - - done() - }, - { prefix: '/api' }, - ) - } - - private async registerPeriodicJob() { - const task = new AsyncTask('cist-postman', async () => { - await cistPostmanJob(this.app) - }) - - return { - job: new CronJob({ cronExpression: '0 */12 * * *' }, task, { - id: 'cist-postman', - }), - task, - } - } - - async initialize(): Promise { - try { - await this.registerPlugins() - - this.app.after(() => { - this.registerRoutes() - }) - - const { job } = await this.registerPeriodicJob() - - await this.app.ready().then(() => { - this.app.scheduler.addCronJob(job) - }) - - return this.app - } catch (e: unknown) { - this.app.log.error('Error while initializing app ', e) - - throw e - } - } -} diff --git a/src/common/constants/health-status.ts b/src/common/constants/health-status.ts new file mode 100644 index 0000000..b76056c --- /dev/null +++ b/src/common/constants/health-status.ts @@ -0,0 +1,8 @@ +export const SYSTEM_HEALTH_STATUS = { + UPDATING: 'updating', + HEALTHY: 'healthy', + FAILED: 'failed', +} as const + +export type SystemHealthStatus = + (typeof SYSTEM_HEALTH_STATUS)[keyof typeof SYSTEM_HEALTH_STATUS] diff --git a/src/common/decorators/zod-result-response.decorator.ts b/src/common/decorators/zod-result-response.decorator.ts new file mode 100644 index 0000000..4a3bc96 --- /dev/null +++ b/src/common/decorators/zod-result-response.decorator.ts @@ -0,0 +1,15 @@ +import { ZodDto, ZodResponse } from 'nestjs-zod' + +type AnyZodDto = ZodDto + +type ZodResultResponseOptions = { + status?: number + description?: string + type: AnyZodDto | [AnyZodDto] +} + +type SingleOptions = { status?: number; description?: string; type: AnyZodDto } + +export const ZodResultResponse = ( + options: ZodResultResponseOptions, +): MethodDecorator => ZodResponse(options as SingleOptions) as MethodDecorator diff --git a/src/common/exceptions/app.exception.ts b/src/common/exceptions/app.exception.ts new file mode 100644 index 0000000..16ee9a4 --- /dev/null +++ b/src/common/exceptions/app.exception.ts @@ -0,0 +1,12 @@ +import { HttpException, HttpStatus } from '@nestjs/common' + +export class AppException extends HttpException { + constructor( + public readonly code: T, + message: string, + status: HttpStatus = HttpStatus.INTERNAL_SERVER_ERROR, + public readonly details?: Record, + ) { + super({ code, message, details }, status) + } +} diff --git a/src/common/exceptions/config.exception.ts b/src/common/exceptions/config.exception.ts new file mode 100644 index 0000000..682f33f --- /dev/null +++ b/src/common/exceptions/config.exception.ts @@ -0,0 +1,26 @@ +import { HttpStatus } from '@nestjs/common' +import { AppException } from './app.exception' +import { CommonErrorCodes } from './error-codes' + +class ConfigInvalidException extends AppException { + constructor(details: Record) { + super( + CommonErrorCodes.CONFIG_INVALID, + 'Config is invalid', + HttpStatus.INTERNAL_SERVER_ERROR, + details, + ) + } +} + +class ConfigNotFoundException extends AppException { + constructor(configKey: string) { + super( + CommonErrorCodes.CONFIG_INVALID, + `Config not found: ${configKey}`, + HttpStatus.INTERNAL_SERVER_ERROR, + ) + } +} + +export { ConfigInvalidException, ConfigNotFoundException } diff --git a/src/common/exceptions/error-codes.ts b/src/common/exceptions/error-codes.ts new file mode 100644 index 0000000..0f53530 --- /dev/null +++ b/src/common/exceptions/error-codes.ts @@ -0,0 +1,6 @@ +export const CommonErrorCodes = { + FAILED_VALIDATION: 'FAILED_VALIDATION_EXCEPTION', + CONFIG_INVALID: 'CONFIG_INVALID_EXCEPTION', + CONFIG_NOT_FOUND: 'CONFIG_NOT_FOUND_EXCEPTION', + UNKNOWN_EXCEPTION: 'UNKNOWN_EXCEPTION', +} as const diff --git a/src/common/filters/global-exception.filter.ts b/src/common/filters/global-exception.filter.ts new file mode 100644 index 0000000..5d4bc00 --- /dev/null +++ b/src/common/filters/global-exception.filter.ts @@ -0,0 +1,186 @@ +import { + ArgumentsHost, + Catch, + ExceptionFilter, + HttpException, + HttpStatus, +} from '@nestjs/common' +import type { FastifyRequest, FastifyReply } from 'fastify' +import { AppException } from '../exceptions/app.exception' +import { ZodSerializationException } from 'nestjs-zod' +import z, { ZodError } from 'zod' +import { CommonErrorCodes } from '../exceptions/error-codes' +import { Temporal } from 'temporal-polyfill' + +@Catch() +export class GlobalExceptionFilter implements ExceptionFilter { + catch(exception: T, host: ArgumentsHost) { + const ctx = host.switchToHttp() + const request = ctx.getRequest() + const reply = ctx.getResponse() + + // Handle ZodSerializationException. + if (this.isZodException(exception)) { + this.handleZodException(exception, reply, request) + return + } + + // Handle AppException. + if (this.isAppException(exception)) { + this.handleAppException(exception, reply, request) + return + } + + // Handle HttpException. + if (exception instanceof HttpException) { + this.handleHttpException(exception, reply, request) + return + } + + // Handle generic errors. + this.handleGenericError(exception, reply, request) + } + + private handleZodException( + exception: ZodSerializationException, + reply: FastifyReply, + request: FastifyRequest, + ): void { + const status = exception.getStatus() + const zodError = exception.getZodError() + + const base = { + code: CommonErrorCodes.FAILED_VALIDATION, + timestamp: Temporal.Now.plainDateISO(), + path: request.url, + } + + const error = + zodError instanceof ZodError + ? { + ...base, + message: 'Validation failed', + details: z.treeifyError(zodError), + } + : { + ...base, + message: 'Unknown validation error', + } + + reply.status(status).send({ success: false, error }) + } + + /** + * Handle AppException. + * @param {AppException} exception - The exception to handle. + * @param {FastifyReply} reply - The response object. + * @param {FastifyRequest} request - The request object. + */ + private handleAppException( + exception: AppException, + reply: FastifyReply, + request: FastifyRequest, + ): void { + const status = exception.getStatus() + + const errorResponse = { + success: false, + error: { + code: exception.code, + message: exception.message, + details: exception.details, + timestamp: Temporal.Now.plainDateISO(), + path: request.url, + }, + } + + reply.status(status).send(errorResponse) + } + + /** + * Handle HttpException. + * @param {HttpException} exception - The exception to handle. + * @param {FastifyReply} reply - The response object. + * @param {FastifyRequest} request - The request object. + */ + private handleHttpException( + exception: HttpException, + reply: FastifyReply, + request: FastifyRequest, + ): void { + const status = exception.getStatus() + const exceptionResponse = exception.getResponse() + + let message: string + let details: unknown + + if (typeof exceptionResponse === 'object' && exceptionResponse !== null) { + const responseObj = exceptionResponse as Record + message = (responseObj.message as string) || exception.message + details = responseObj + } else { + message = exception.message + } + + const errorResponse = { + success: false, + error: { + message, + details, + timestamp: Temporal.Now.plainDateISO(), + path: request.url, + }, + } + + reply.status(status).send(errorResponse) + } + + /** + * Handle generic errors. + * @param {unknown} exception - The exception to handle. + * @param {FastifyReply} reply - The response object. + * @param {FastifyRequest} request - The request object. + */ + private handleGenericError( + exception: unknown, + reply: FastifyReply, + request: FastifyRequest, + ): void { + const message = + exception instanceof Error ? exception.message : 'Internal Server Error' + const details = + exception instanceof Error ? { stack: exception.stack } : undefined + + const errorResponse = { + success: false, + error: { + message, + details, + timestamp: Temporal.Now.plainDateISO(), + path: request.url, + }, + } + + reply.status(HttpStatus.INTERNAL_SERVER_ERROR).send(errorResponse) + } + + /** + * Type guard to check if exception is AppException. + * @param {unknown} exception - The exception to check. + * @returns {boolean} True if the exception is an AppException, false otherwise. + */ + private isAppException(exception: unknown): exception is AppException { + return exception instanceof AppException + } + + /** + * Type guard to check if exception is ZodSerializationException. + * @param {unknown} exception - The exception to check. + * @returns {boolean} True if the exception is an ZodSerializationException, false otherwise. + */ + private isZodException( + exception: unknown, + ): exception is ZodSerializationException { + return exception instanceof ZodSerializationException + } +} diff --git a/src/common/interceptors/error.interceptor.ts b/src/common/interceptors/error.interceptor.ts new file mode 100644 index 0000000..1ba503b --- /dev/null +++ b/src/common/interceptors/error.interceptor.ts @@ -0,0 +1,159 @@ +import { + Injectable, + NestInterceptor, + ExecutionContext, + CallHandler, + HttpException, + InternalServerErrorException, + Logger, +} from '@nestjs/common' +import { FastifyReply, FastifyRequest } from 'fastify' +import { Observable, throwError } from 'rxjs' +import { catchError } from 'rxjs/operators' +import { AppException } from '../exceptions/app.exception' + +@Injectable() +export class ErrorsInterceptor implements NestInterceptor { + private readonly logger: Logger = new Logger(ErrorsInterceptor.name) + + /** + * Intercepts the request and handles any errors that occur. + * @param {ExecutionContext} context - The execution context. + * @param {CallHandler} next - The next handler in the chain. + * @returns {Observable} The observable stream. + */ + intercept(context: ExecutionContext, next: CallHandler): Observable { + const request = context.switchToHttp().getRequest() + const response = context.switchToHttp().getResponse() + + return next.handle().pipe( + catchError((err: unknown) => + throwError(() => { + this.logError(err, request, response) + this.recordErrorMetrics() + return this.transformError(err) + }), + ), + ) + } + + /** + * Logs error. + * @param {unknown} error - The error to log. + * @param {FastifyRequest} request - The request object. + * @param {FastifyReply} reply - The response object. + */ + private logError( + error: unknown, + request: FastifyRequest, + reply: FastifyReply, + ): void { + const errorInfo = this.extractErrorInfo(error) + const requestInfo = this.extractRequestInfo(request) + + this.logger.error('request-error', { + error: errorInfo, + request: requestInfo, + response: { + statusCode: reply.statusCode, + }, + timestamp: new Date().toISOString(), + }) + } + + /** + * Extracts error information for logging. + * @param {unknown} error - The error to extract information from. + * @returns {Record} The extracted error information. + */ + private extractErrorInfo(error: unknown): Record { + if (error instanceof AppException) { + return { + type: 'AppException', + code: error.code, + message: error.message, + status: error.getStatus(), + details: error.details, + } + } + + if (error instanceof HttpException) { + return { + type: 'HttpException', + message: error.message, + status: error.getStatus(), + } + } + + if (error instanceof Error) { + return { + type: 'Error', + name: error.name, + message: error.message, + cause: error.cause, + } + } + + return { + type: 'Unknown', + error: String(error), + } + } + + /** + * Extracts request information for logging. + * @param {FastifyRequest} request - The request object. + * @returns {Record} The extracted request information. + */ + private extractRequestInfo(request: FastifyRequest): Record { + return { + method: request.method, + url: request.url, + query: request.query, + params: request.params, + } + } + + /** + * Records error metrics for monitoring. + */ + private recordErrorMetrics(): void { + // TODO: Implement + } + + /** + * Transforms error to appropriate HTTP exception. + * @param {unknown} error - The error to transform. + * @returns {HttpException} The transformed HTTP exception. + */ + private transformError(error: unknown): HttpException { + if (error instanceof AppException) { + return error + } + + if (error instanceof HttpException) { + return error + } + + if (error instanceof Error) { + return new InternalServerErrorException({ + message: 'Internal server error', + error: 'InternalServerError', + statusCode: 500, + details: { + originalMessage: error.message, + originalName: error.name, + }, + }) + } + + return new InternalServerErrorException({ + message: 'Internal server error', + error: 'InternalServerError', + statusCode: 500, + details: { + originalError: String(error), + }, + }) + } +} diff --git a/src/common/interceptors/transform.interceptor.ts b/src/common/interceptors/transform.interceptor.ts new file mode 100644 index 0000000..0e3ab02 --- /dev/null +++ b/src/common/interceptors/transform.interceptor.ts @@ -0,0 +1,55 @@ +import { + CallHandler, + ExecutionContext, + Injectable, + NestInterceptor, + StreamableFile, +} from '@nestjs/common' +import { Result } from 'better-result' +import { map, Observable } from 'rxjs' + +@Injectable() +export class TransformInterceptor implements NestInterceptor { + /** + * Intercepts the request and transforms the data. + * @param {ExecutionContext} _context - The execution context. + * @param {CallHandler} next - The next handler in the chain. + * @returns {Observable} The observable stream. + */ + intercept( + _context: ExecutionContext, + next: CallHandler, + ): Observable { + return next.handle().pipe( + map((data: unknown) => { + if (data instanceof StreamableFile) { + return data + } + + if (!this.isResult(data)) { + return { data } + } + + if (data.isErr()) { + throw data.error + } + + return { success: true, data: data.unwrap() } + }), + ) + } + + private isResult(data: unknown): data is Result { + const acceptedStatuses = ['ok', 'err'] + + if (typeof data !== 'object' || data === null) { + return false + } + + if (!('status' in data) || typeof data.status !== 'string') { + return false + } + + return acceptedStatuses.includes(data.status) + } +} diff --git a/src/common/types/index.ts b/src/common/types/index.ts new file mode 100644 index 0000000..65d2729 --- /dev/null +++ b/src/common/types/index.ts @@ -0,0 +1,7 @@ +import { Result } from 'better-result' +import { AppException } from '../exceptions/app.exception' + +type PromiseResult = Promise> +type Maybe = T | null | undefined + +export type { PromiseResult, Maybe } diff --git a/src/common/utils/error-handling/error-handling.ts b/src/common/utils/error-handling/error-handling.ts new file mode 100644 index 0000000..b84d329 --- /dev/null +++ b/src/common/utils/error-handling/error-handling.ts @@ -0,0 +1,31 @@ +import { HttpStatus } from '@nestjs/common' +import { Result } from 'better-result' +import { AppException } from 'src/common/exceptions/app.exception' +import { CommonErrorCodes } from 'src/common/exceptions/error-codes' +import { PromiseResult } from 'src/common/types' + +type UnknownException = AppException + +/* + * Attempts to execute an async thunk and handles any errors by mapping them to an AppException or UnknownException. + * @param {() => Promise} thunk The async thunk to execute. + * @param {E} errorClass The error class to use for mapping errors, or undefined to use the default UnknownException. + * @returns {PromiseResult} PromiseResult containing the result of the thunk or an AppException/UnknownException. + */ +export const attemptAsync = async ( + thunk: () => Promise, + errorClass?: E, +): PromiseResult => { + const result = await Result.tryPromise(thunk) + + return result.mapError((e: unknown) => + errorClass + ? errorClass + : new AppException( + CommonErrorCodes.UNKNOWN_EXCEPTION, + e instanceof Error ? e.message : 'Unknown error', + HttpStatus.INTERNAL_SERVER_ERROR, + { cause: e }, + ), + ) +} diff --git a/src/common/utils/error-handling/index.ts b/src/common/utils/error-handling/index.ts new file mode 100644 index 0000000..3b0fbe6 --- /dev/null +++ b/src/common/utils/error-handling/index.ts @@ -0,0 +1 @@ +export * from './error-handling' diff --git a/src/common/utils/response/response.ts b/src/common/utils/response/response.ts new file mode 100644 index 0000000..4fa6f14 --- /dev/null +++ b/src/common/utils/response/response.ts @@ -0,0 +1,13 @@ +import z from 'zod' + +/* + Creates a response schema for a given data schema. + @param schema - The data schema to use for the response. + @returns A response schema that includes a `success` field and the given data schema. +*/ +export const createResponseSchema = (schema: T) => { + return z.object({ + success: z.literal(true).describe('Response status'), + data: schema.describe('Response data'), + }) +} diff --git a/src/common/utils/type-checkers/type-checkers.ts b/src/common/utils/type-checkers/type-checkers.ts new file mode 100644 index 0000000..3c96b4a --- /dev/null +++ b/src/common/utils/type-checkers/type-checkers.ts @@ -0,0 +1,7 @@ +/* + * Checks if the given value is a record (non-array object). + * @param {unknown} value The value to check. + * @returns {boolean} true if the value is a record, false otherwise. + */ +export const isRecord = (value: unknown): value is Record => + typeof value === 'object' && value !== null && !Array.isArray(value) diff --git a/src/components/cache/cache.module.ts b/src/components/cache/cache.module.ts new file mode 100644 index 0000000..6eb995c --- /dev/null +++ b/src/components/cache/cache.module.ts @@ -0,0 +1,18 @@ +import { Module, Provider } from '@nestjs/common' +import { CACHE_CONNECTION_TOKEN } from './di-tokens' +import { CacheService } from './cache.service' +import Redis from 'ioredis' +import { ConfigModule } from '../config/config.module' + +const cacheConnectionProvider = { + provide: CACHE_CONNECTION_TOKEN, + useFactory: (cacheService: CacheService): Redis => cacheService.cache, + inject: [CacheService], +} satisfies Provider + +@Module({ + imports: [ConfigModule], + providers: [CacheService, cacheConnectionProvider], + exports: [cacheConnectionProvider], +}) +export class CacheModule {} diff --git a/src/components/cache/cache.service.ts b/src/components/cache/cache.service.ts new file mode 100644 index 0000000..575eb8b --- /dev/null +++ b/src/components/cache/cache.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@nestjs/common' +import { ConfigService } from '../config/config.service' +import Redis from 'ioredis' + +@Injectable() +export class CacheService { + private _cache: Redis + + constructor(private readonly configService: ConfigService) { + const { port, host, user, password } = this.configService.get('cache') + + this._cache = new Redis({ + port, + host, + username: user, + password: password, + }) + } + + /* + * Gets the Redis cache instance. + * @returns {Redis} The Redis cache instance. + */ + get cache(): Redis { + return this._cache + } +} diff --git a/src/components/cache/di-tokens.ts b/src/components/cache/di-tokens.ts new file mode 100644 index 0000000..1fab1be --- /dev/null +++ b/src/components/cache/di-tokens.ts @@ -0,0 +1 @@ +export const CACHE_CONNECTION_TOKEN = Symbol('CACHE_CONNECTION_TOKEN') diff --git a/src/components/cist-crawler/cist-crawler.module.ts b/src/components/cist-crawler/cist-crawler.module.ts new file mode 100644 index 0000000..02fc98c --- /dev/null +++ b/src/components/cist-crawler/cist-crawler.module.ts @@ -0,0 +1,16 @@ +import { Module, Provider } from '@nestjs/common' +import { CistCrawlerService } from './cist-crawler.service' +import { CIST_CRAWLER_TOKEN } from './di-tokens' + +const cistCrawlerProvider = { + provide: CIST_CRAWLER_TOKEN, + useFactory: (cistCrawlerService: CistCrawlerService) => + cistCrawlerService.get(), + inject: [CistCrawlerService], +} satisfies Provider + +@Module({ + providers: [cistCrawlerProvider], + exports: [cistCrawlerProvider], +}) +export class CistCrawlerModule {} diff --git a/src/components/cist-crawler/cist-crawler.service.ts b/src/components/cist-crawler/cist-crawler.service.ts new file mode 100644 index 0000000..d564e19 --- /dev/null +++ b/src/components/cist-crawler/cist-crawler.service.ts @@ -0,0 +1,45 @@ +import CistCrawler from '@mindenit/cist-crawler' +import { Injectable } from '@nestjs/common' +import { ConfigNotFoundException } from 'src/common/exceptions/config.exception' +import { ConfigService } from '../config/config.service' + +@Injectable() +export class CistCrawlerService { + private readonly _crawler: CistCrawler + + constructor(private readonly configService: ConfigService) { + const integrationsConfig = this.configService.get('integrations') + if (!('cist' in integrationsConfig)) { + throw new ConfigNotFoundException( + 'Cist integration configuration not found', + ) + } + + const cistConfig = integrationsConfig?.cist + if (!cistConfig) { + throw new ConfigNotFoundException( + 'Cist integration configuration not found', + ) + } + + if ( + typeof cistConfig !== 'object' || + !('clientId' in cistConfig) || + typeof cistConfig.clientId !== 'string' + ) { + throw new ConfigNotFoundException( + 'Cist integration configuration not found', + ) + } + + this._crawler = new CistCrawler({ clientId: cistConfig.clientId }) + } + + /* + * Gets the Cist crawler instance. + * @returns {CistCrawler} The Cist crawler instance. + */ + get(): CistCrawler { + return this._crawler + } +} diff --git a/src/components/cist-crawler/di-tokens.ts b/src/components/cist-crawler/di-tokens.ts new file mode 100644 index 0000000..6956785 --- /dev/null +++ b/src/components/cist-crawler/di-tokens.ts @@ -0,0 +1 @@ +export const CIST_CRAWLER_TOKEN = Symbol('CIST_CRAWLER_TOKEN') diff --git a/src/components/config/config.module.ts b/src/components/config/config.module.ts new file mode 100644 index 0000000..c40891d --- /dev/null +++ b/src/components/config/config.module.ts @@ -0,0 +1,9 @@ +import { Global, Module } from '@nestjs/common' +import { ConfigService } from './config.service' + +@Global() +@Module({ + providers: [ConfigService], + exports: [ConfigService], +}) +export class ConfigModule {} diff --git a/src/components/config/config.schema.ts b/src/components/config/config.schema.ts new file mode 100644 index 0000000..e03d710 --- /dev/null +++ b/src/components/config/config.schema.ts @@ -0,0 +1,45 @@ +import z from 'zod' + +const PortSchema = z.number().int().min(1000).max(9999) + +const ServerConfigSchema = z.object({ + port: PortSchema, +}) + +const DbConfigSchema = z.object({ + user: z.string().nonempty(), + password: z.string().nonempty(), + host: z.string(), + port: z.number().int().min(1000).max(9999), + database: z.string().nonempty(), +}) + +const CacheConfigSchema = z.object({ + user: z.string().nonempty(), + host: z.string(), + port: PortSchema, + password: z.string().nonempty(), +}) + +const IntegrationConfigSchema = z.record( + z.string(), + z.object({ enabled: z.boolean() }).and(z.record(z.string(), z.unknown())), +) + +const WebhooksConfigSchema = z.object({ + enabled: z.boolean(), + webhookUrl: z.url(), +}) + +const ConfigSchema = z.object({ + server: ServerConfigSchema, + db: DbConfigSchema, + cache: CacheConfigSchema, + integrations: IntegrationConfigSchema, + webhooks: WebhooksConfigSchema, +}) + +type Config = z.infer + +export { ConfigSchema } +export type { Config } diff --git a/src/components/config/config.service.ts b/src/components/config/config.service.ts new file mode 100644 index 0000000..5f2b328 --- /dev/null +++ b/src/components/config/config.service.ts @@ -0,0 +1,108 @@ +import { Injectable, Logger } from '@nestjs/common' +import { existsSync, globSync, readFileSync } from 'node:fs' +import { basename, resolve } from 'node:path' +import { type Config, ConfigSchema } from './config.schema' +import { ConfigInvalidException } from 'src/common/exceptions/config.exception' +import { isRecord } from 'src/common/utils/type-checkers/type-checkers' + +const CONFIG_PATH = resolve('./configs') + +/* + Reads a JSON file and returns the parsed object. + @param {string} filePath - Path to the JSON file to read + @returns {Record} Parsed JSON object +*/ +const readJson = (filePath: string): Record => { + const content = readFileSync(filePath, 'utf-8') + const parsed = JSON.parse(content) + + if (!isRecord(parsed)) { + throw {} + } + + return parsed +} + +/* + Gets the config key from a file name. + @param {string} fileName - Name of the file + @returns {string} Config key +*/ +const getConfigKey = (fileName: string): string => { + return basename(fileName) + .replace('.default.json', '') + .replace('.config.json', '') +} + +@Injectable() +export class ConfigService { + private readonly logger: Logger = new Logger(ConfigService.name) + private config: Config + + constructor() { + try { + this.config = this.loadConfigs() + } catch (error: unknown) { + this.logger.error('config-service-config-error', { + error: error instanceof Error ? error.message : String(error), + }) + throw new ConfigInvalidException(isRecord(error) ? error : {}) + } + } + + /* + * Gets a config value by key. + * @param {K} key - Key of the config value + * @returns {Config[K]} Config value + */ + get(key: K): Config[K] { + return this.config[key] + } + + /* + * Loads config files by pattern and returns a merged result. + * @returns {Config} Merged config values + */ + private loadConfigs(): Config { + const defaults = this.loadFilesByPattern('*.default.json') + const overrides = this.loadFilesByPattern('*.config.json') + + const merged = { ...defaults } + + for (const [key, value] of Object.entries(overrides)) { + merged[key] = + typeof merged[key] === 'object' && typeof value === 'object' + ? { ...merged[key], ...value } + : value + } + + return ConfigSchema.parse(merged) + } + + /* + * Loads config files by pattern and returns a merged result. + * @param {string} pattern - Glob pattern for config files + * @returns {Record>} Merged config values + */ + private loadFilesByPattern( + pattern: string, + ): Record> { + const result: Record> = {} + + if (!existsSync(CONFIG_PATH)) { + this.logger.warn(`Config directory not found: ${CONFIG_PATH}`) + return result + } + + const files = globSync(resolve(CONFIG_PATH, pattern)) + + for (const file of files) { + const key = getConfigKey(file) + + result[key] = readJson(file) + this.logger.debug(`Loaded config: ${basename(file)} -> "${key}"`) + } + + return result + } +} diff --git a/src/components/database/database.module.ts b/src/components/database/database.module.ts new file mode 100644 index 0000000..e84a77b --- /dev/null +++ b/src/components/database/database.module.ts @@ -0,0 +1,17 @@ +import { Module, Provider } from '@nestjs/common' +import { DATABASE_CONNECTION_TOKEN } from './di-tokens' +import { DatabaseService } from './database.service' +import { ConfigModule } from '../config/config.module' + +const databaseConnectionProvider = { + provide: DATABASE_CONNECTION_TOKEN, + useFactory: (databaseService: DatabaseService) => databaseService.get(), + inject: [DatabaseService], +} satisfies Provider + +@Module({ + imports: [ConfigModule], + providers: [DatabaseService, databaseConnectionProvider], + exports: [DATABASE_CONNECTION_TOKEN], +}) +export class DatabaseModule {} diff --git a/src/components/database/database.repository.ts b/src/components/database/database.repository.ts new file mode 100644 index 0000000..fc3fac2 --- /dev/null +++ b/src/components/database/database.repository.ts @@ -0,0 +1,13 @@ +import { Table } from 'drizzle-orm' + +export class DatabaseRepository { + protected readonly table: Schema + + /* + * Creates a new DatabaseRepository instance with the provided table schema. + * @param table - The table schema to use for the repository. + */ + constructor(table: Schema) { + this.table = table + } +} diff --git a/src/components/database/database.service.ts b/src/components/database/database.service.ts new file mode 100644 index 0000000..d376f4c --- /dev/null +++ b/src/components/database/database.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@nestjs/common' +import { drizzle, PostgresJsDatabase } from 'drizzle-orm/postgres-js' +import { ConfigService } from '../config/config.service' +import postgres from 'postgres' + +@Injectable() +export class DatabaseService { + private _database: PostgresJsDatabase + + constructor(private readonly configService: ConfigService) { + const { user, password, host, port, database } = + this.configService.get('db') + + const queryClient = postgres({ + username: user, + password, + host, + port, + database, + }) + + this._database = drizzle(queryClient, { + casing: 'snake_case', + }) + } + + /* + * Gets the database instance. + * @returns {PostgresJsDatabase} The database instance. + */ + get(): PostgresJsDatabase { + return this._database + } +} diff --git a/src/components/database/di-tokens.ts b/src/components/database/di-tokens.ts new file mode 100644 index 0000000..f522718 --- /dev/null +++ b/src/components/database/di-tokens.ts @@ -0,0 +1 @@ +export const DATABASE_CONNECTION_TOKEN = Symbol('DATABASE_CONNECTION_TOKEN') diff --git a/src/components/health/dto/health.dto.ts b/src/components/health/dto/health.dto.ts new file mode 100644 index 0000000..082bd2b --- /dev/null +++ b/src/components/health/dto/health.dto.ts @@ -0,0 +1,19 @@ +import { createZodDto } from 'nestjs-zod' +import { SYSTEM_HEALTH_STATUS } from 'src/common/constants/health-status' +import { createResponseSchema } from 'src/common/utils/response/response' +import z from 'zod' + +const HealthResponseSchema = z.object({ + uptime: z.number().positive().describe('Uptime in milliseconds'), + status: z.enum(Object.values(SYSTEM_HEALTH_STATUS)).describe('Health status'), + lastUpdated: z.iso.datetime().describe('Last updated timestamp'), +}) + +type HealthResponse = z.infer + +class HealthResponseDto extends createZodDto( + createResponseSchema(HealthResponseSchema), +) {} + +export { HealthResponseDto } +export type { HealthResponse } diff --git a/src/components/health/health.controller.ts b/src/components/health/health.controller.ts new file mode 100644 index 0000000..2bc28f8 --- /dev/null +++ b/src/components/health/health.controller.ts @@ -0,0 +1,25 @@ +import { Controller, Get, HttpStatus } from '@nestjs/common' +import { HealthService } from './health.service' +import { ZodResultResponse } from 'src/common/decorators/zod-result-response.decorator' +import { HealthResponseDto } from './dto/health.dto' +import { ApiOperation, ApiTags } from '@nestjs/swagger' + +@ApiTags('System Check') +@Controller('health') +export class HealthController { + constructor(private readonly healthService: HealthService) {} + + @ApiOperation({ + summary: 'Get system status', + description: 'Returns the health status of the application', + }) + @ZodResultResponse({ + status: HttpStatus.OK, + description: 'Health check successful', + type: HealthResponseDto, + }) + @Get() + async checkHealth() { + return this.healthService.checkHealth() + } +} diff --git a/src/components/health/health.module.ts b/src/components/health/health.module.ts new file mode 100644 index 0000000..82a2bfb --- /dev/null +++ b/src/components/health/health.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common' +import { HealthController } from './health.controller' +import { HealthService } from './health.service' +import { CacheModule } from '../cache/cache.module' + +@Module({ + imports: [CacheModule], + providers: [HealthService], + controllers: [HealthController], +}) +export class HealthModule {} diff --git a/src/components/health/health.service.ts b/src/components/health/health.service.ts new file mode 100644 index 0000000..521608b --- /dev/null +++ b/src/components/health/health.service.ts @@ -0,0 +1,88 @@ +import { Inject, Injectable } from '@nestjs/common' +import { Result } from 'better-result' +import Redis from 'ioredis' +import { + SYSTEM_HEALTH_STATUS, + SystemHealthStatus, +} from 'src/common/constants/health-status' +import { AppException } from 'src/common/exceptions/app.exception' +import { PromiseResult } from 'src/common/types' +import { attemptAsync } from 'src/common/utils/error-handling' +import { CACHE_CONNECTION_TOKEN } from '../cache/di-tokens' +import { HealthResponse } from './dto/health.dto' + +// Constants +const HEALTH_CHECK_KEY = 'health-check' as const +const LAST_UPDATE_KEY = 'last-update' as const + +@Injectable() +export class HealthService { + constructor( + @Inject(CACHE_CONNECTION_TOKEN) + private readonly cache: Redis, + ) {} + + async checkHealth(): PromiseResult { + const healthResult = await attemptAsync(() => + this.cache.get(HEALTH_CHECK_KEY), + ) + + if (healthResult.isErr()) { + return Result.err(healthResult.error) + } + + const lastUpdatedResult = await attemptAsync(() => + this.cache.get(LAST_UPDATE_KEY), + ) + + if (lastUpdatedResult.isErr()) { + return Result.err(lastUpdatedResult.error) + } + + const health = healthResult.unwrap() + const lastUpdated = lastUpdatedResult.unwrap() + + const data = { + uptime: process.uptime(), + } + + if (!health || !lastUpdated) { + if (!health) { + await this.cache.set(HEALTH_CHECK_KEY, SYSTEM_HEALTH_STATUS.HEALTHY) + } + + if (!lastUpdated) { + await this.cache.set(LAST_UPDATE_KEY, new Date().toISOString()) + } + + return Result.ok({ + ...data, + status: this.isSystemHealthStatus(health) + ? health + : SYSTEM_HEALTH_STATUS.HEALTHY, + lastUpdated: lastUpdated ?? new Date().toISOString(), + }) + } + + return Result.ok({ + ...data, + status: this.isSystemHealthStatus(health) + ? health + : SYSTEM_HEALTH_STATUS.HEALTHY, + lastUpdated, + }) + } + + /* + * Checks if the given value is a valid system health status. + * @param {unknown} value The value to check. + * @returns {boolean} true if the value is a valid system health status, false otherwise. + */ + private isSystemHealthStatus(value: unknown): value is SystemHealthStatus { + if (typeof value !== 'string') { + return false + } + + return Object.values(SYSTEM_HEALTH_STATUS).includes(value) + } +} diff --git a/src/core/builders/RedisKeyBulder.ts b/src/core/builders/RedisKeyBulder.ts deleted file mode 100644 index 0f0a0e6..0000000 --- a/src/core/builders/RedisKeyBulder.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type { Event } from '@/db/types.js' -import { hasher } from 'node-object-hash' - -export class RedisKeyBuilder { - static auditoriumKey(auditoriumId: number): string { - return `auditoriums:${auditoriumId}` - } - - static auditoriumTypeKey(typeId: number): string { - return `auditorium-types:${typeId}` - } - - static buildingKey(buildingId: string): string { - return `buildings:${buildingId}` - } - - static departmentKey(departmentId: number): string { - return `departments:${departmentId}` - } - - static directionKey(directionId: number): string { - return `directions:${directionId}` - } - - static eventKey(event: Omit): string { - const hashFn = hasher({ coerce: true, sort: true }) - - const key = hashFn.hash(event) - - return `events:${key}` - } - - static facultyKey(facultyId: number): string { - return `faculties:${facultyId}` - } - - static groupKey(groupId: number): string { - return `groups:${groupId}` - } - - static groupEventKey(groupId: number, eventId: number): string { - return `group-event:${groupId}:${eventId}` - } - - static teacherKey(teacherId: number): string { - return `teachers:${teacherId}` - } - - static teacherEventKey(teacherId: number, eventId: number): string { - return `teacher-events:${teacherId}:${eventId}` - } - - static teacherSubjectKey(teacherId: number, subjectId: number): string { - return `teacher-subjects:${teacherId}:${subjectId}` - } - - static specialityKey(specialityId: number): string { - return `specialities:${specialityId}` - } - - static subjectKey(subjectId: number): string { - return `subjects:${subjectId}` - } -} diff --git a/src/core/constants/db.ts b/src/core/constants/db.ts deleted file mode 100644 index 6f30092..0000000 --- a/src/core/constants/db.ts +++ /dev/null @@ -1 +0,0 @@ -export const DUPLICATE_KEY_ERR_CODE = '23505' as const diff --git a/src/core/constants/errors.ts b/src/core/constants/errors.ts deleted file mode 100644 index ecb0c17..0000000 --- a/src/core/constants/errors.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { HttpError } from '../types/index.js' - -const INTERNAL_SERVER_ERR: HttpError = { - status: 500, - message: 'Something went wrong', -} - -export { INTERNAL_SERVER_ERR } diff --git a/src/core/constants/health.ts b/src/core/constants/health.ts deleted file mode 100644 index 5943e08..0000000 --- a/src/core/constants/health.ts +++ /dev/null @@ -1,24 +0,0 @@ -const HEALTH_CHECK_KEY = 'health-check' as const - -const LAST_UPDATE_KEY = 'last-update' as const - -const HEALTH_STATUS = { - UPDATING: 'updating', - HEALTHY: 'healthy', - FAILED: 'failed', -} - -const IS_UPDATE_IN_PROGRESS_KEY = 'is-update-in-progress' as const - -const UPDATE_STATUS = { - IN_PROGRESS: '1', - FINISHED: '0', -} - -export { - HEALTH_CHECK_KEY, - HEALTH_STATUS, - LAST_UPDATE_KEY, - IS_UPDATE_IN_PROGRESS_KEY, - UPDATE_STATUS, -} diff --git a/src/core/constants/http.ts b/src/core/constants/http.ts deleted file mode 100644 index 6b48dbf..0000000 --- a/src/core/constants/http.ts +++ /dev/null @@ -1,22 +0,0 @@ -const HTTP_STATUS = { - OK: 200, - CREATED: 201, - NO_CONTENT: 204, - BAD_REQUEST: 400, - UNAUTHORIZED: 401, - FORBIDDEN: 403, - NOT_FOUND: 404, - METHOD_NOT_ALLOWED: 405, - CONFLICT: 409, - UNPROCESSABLE_ENTITY: 422, - TOO_MANY_REQUESTS: 429, - INTERNAL_SERVER_ERR: 500, - BAD_GATEWAY: 502, - SERVICE_UNAVAILABLE: 503, - GATEWAY_TIMEOUT: 504, -} as const - -type HttpStatus = (typeof HTTP_STATUS)[keyof typeof HTTP_STATUS] - -export { HTTP_STATUS } -export type { HttpStatus } diff --git a/src/core/constants/index.ts b/src/core/constants/index.ts deleted file mode 100644 index 3deb4f9..0000000 --- a/src/core/constants/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './db.js' -export * from './errors.js' -export * from './health.js' -export * from './parsers.js' -export * from './db.js' diff --git a/src/core/constants/parsers.ts b/src/core/constants/parsers.ts deleted file mode 100644 index 59fd130..0000000 --- a/src/core/constants/parsers.ts +++ /dev/null @@ -1,10 +0,0 @@ -const SCHEDULE_TYPE = { - GROUP: 1, - TEACHER: 2, - AUDITORIUM: 3, -} as const - -type ScheduleType = (typeof SCHEDULE_TYPE)[keyof typeof SCHEDULE_TYPE] - -export { SCHEDULE_TYPE } -export type { ScheduleType } diff --git a/src/core/constants/time.ts b/src/core/constants/time.ts deleted file mode 100644 index d1a48db..0000000 --- a/src/core/constants/time.ts +++ /dev/null @@ -1,7 +0,0 @@ -const MINUTE = 1000 * 60 - -const HOUR = MINUTE * 60 - -const DAY = HOUR * 24 - -export { MINUTE, HOUR, DAY } diff --git a/src/core/entity.mapper.ts b/src/core/entity.mapper.ts new file mode 100644 index 0000000..7a8a263 --- /dev/null +++ b/src/core/entity.mapper.ts @@ -0,0 +1,7 @@ +import z from 'zod' + +export interface EntityMapper { + schema: z.ZodType + + toEntity(from: From): To +} diff --git a/src/core/exceptions/http.exception.ts b/src/core/exceptions/http.exception.ts deleted file mode 100644 index a6021b2..0000000 --- a/src/core/exceptions/http.exception.ts +++ /dev/null @@ -1,19 +0,0 @@ -export class HttpException extends Error { - constructor( - public readonly code: T, - message?: string, - public readonly status: number = 500, - ) { - super(message) - this.code = code - this.status = status - } - - toJSON() { - return { - code: this.code, - message: this.message, - status: this.status, - } - } -} diff --git a/src/core/schemas/index.ts b/src/core/schemas/index.ts deleted file mode 100644 index 225b075..0000000 --- a/src/core/schemas/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { z } from 'zod' -import { HEALTH_STATUS } from '../constants/health.js' - -const HEALTH_CHECK_SCHEMA = z - .object({ - uptime: z.number().positive(), - message: z.enum(Object.values(HEALTH_STATUS)), - lastUpdated: z.date(), - }) - .describe('Successful response') - -const GET_ENTITY_BY_ID_SCHEMA = z.object({ - id: z.coerce.number().int(), -}) - -type GET_ENTITY_BY_ID = z.infer - -export { GET_ENTITY_BY_ID_SCHEMA, HEALTH_CHECK_SCHEMA } -export type { GET_ENTITY_BY_ID } diff --git a/src/core/services/CookieService.ts b/src/core/services/CookieService.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/core/services/DrizzleWriter.ts b/src/core/services/DrizzleWriter.ts deleted file mode 100644 index 59196eb..0000000 --- a/src/core/services/DrizzleWriter.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { LogWriter } from 'drizzle-orm' -import type { CommonDependencies } from '../types/deps.js' -import type { FastifyBaseLogger } from 'fastify' - -export class DrizzleWriter implements LogWriter { - private readonly logger: FastifyBaseLogger - - constructor({ logger }: CommonDependencies) { - this.logger = logger - } - - write(message: string): void { - this.logger.info(message) - } -} diff --git a/src/core/types/cist.ts b/src/core/types/cist.ts deleted file mode 100644 index 0fadc1b..0000000 --- a/src/core/types/cist.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { Maybe } from './common.js' - -interface CistParser { - parse: () => Promise> -} - -interface CistProcessor { - process: () => Promise -} - -export type { CistParser, CistProcessor } diff --git a/src/core/types/common.ts b/src/core/types/common.ts deleted file mode 100644 index 9e32518..0000000 --- a/src/core/types/common.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { Result } from 'better-result' -import type { FastifyInstance } from 'fastify' -import type http from 'node:http' - -type Maybe = T | undefined | null - -type Bit = 0 | 1 - -type PromiseResult = Promise> - -interface EntityMapper { - toEntity: (from: From) => To -} - -type AppInstance = FastifyInstance< - http.Server, - http.IncomingMessage, - http.ServerResponse -> - -interface HttpError { - status: number - message: string -} - -type SuccessResponse = { - success: true - data: T - message?: string - error: null -} - -type FailureResponse = { - success: false - data: null - message?: string - error: HttpError -} - -type BaseResponse = SuccessResponse | FailureResponse - -type HttpExceptionOverrides = { - message: string | null - status: number -} - -type HttpExceptionMap = Partial< - Record -> - -export type { - AppInstance, - BaseResponse, - Bit, - EntityMapper, - FailureResponse, - HttpError, - HttpExceptionMap, - HttpExceptionOverrides, - Maybe, - PromiseResult, - SuccessResponse, -} diff --git a/src/core/types/config.ts b/src/core/types/config.ts deleted file mode 100644 index 66482da..0000000 --- a/src/core/types/config.ts +++ /dev/null @@ -1,43 +0,0 @@ -interface DbConfig { - user: string - password: string - host: string - port: number - database: string -} - -interface CacheConfig { - user: string - host: string - port: number - password: string -} - -interface ProxyConfig { - baseUrl: string -} - -interface IntegrationConfig { - discordWebhookUrl: string -} - -interface MoodleConfig { - baseUrl: string -} - -interface Config { - db: DbConfig - cache: CacheConfig - proxy: ProxyConfig - integration: IntegrationConfig - moodle: MoodleConfig -} - -export type { - Config, - DbConfig, - CacheConfig, - ProxyConfig, - IntegrationConfig, - MoodleConfig, -} diff --git a/src/core/types/deps.ts b/src/core/types/deps.ts deleted file mode 100644 index 92e4f59..0000000 --- a/src/core/types/deps.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type postgres from 'postgres' -import type { Resolver } from 'awilix' -import type { FastifyBaseLogger } from 'fastify' -import type { Config } from './config.js' -import type { AppInstance } from './common.js' -import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js' -import type { Redis } from 'ioredis' -import type { ExtractTablesFromSchema, Relations } from 'drizzle-orm' -import * as schema from '@/db/schema/index.js' - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type BaseDiConfig = Record> - -type DatabaseClient = PostgresJsDatabase< - Record, - Relations> -> - -interface CommonDependencies { - config: Config - db: { - connection: postgres.Sql - client: DatabaseClient - } - cache: Redis - logger: FastifyBaseLogger -} - -type InjectableDependencies = T & CommonDependencies - -interface ExternalDependencies { - app: AppInstance -} - -export type { - BaseDiConfig, - CommonDependencies, - InjectableDependencies, - ExternalDependencies, - DatabaseClient, -} diff --git a/src/core/types/index.ts b/src/core/types/index.ts deleted file mode 100644 index e995258..0000000 --- a/src/core/types/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './common.js' -export * from './config.js' -export * from './deps.js' -export * from './routes.js' diff --git a/src/core/types/proxy.ts b/src/core/types/proxy.ts deleted file mode 100644 index c4e5fa0..0000000 --- a/src/core/types/proxy.ts +++ /dev/null @@ -1,190 +0,0 @@ -import type { - Auditorium, - AuditoriumType, - Building, - Department, - Direction, - Event, - EventType, - Faculty, - Group, - Speciality, - Subject, - Teacher, -} from '@/db/types.js' -import type { Maybe } from './common.js' - -type RawAuditoriumType = { - id: string - short_name: string -} - -type RawAuditorium = { - id: string - short_name: string - floor: string - is_have_power: string - auditory_types: RawAuditoriumType[] -} - -type RawGroup = { - id: number - name: string -} - -type RawBuilding = { - id: string - short_name: string - full_name: string - auditories: RawAuditorium[] -} - -type RawSpeciality = { - id: number - short_name: string - full_name: string - groups: RawGroup[] -} - -type RawDirection = { - id: number - short_name: string - full_name: string - specialities: RawSpeciality[] - groups: RawGroup[] -} - -type RawFaculty = { - id: number - short_name: string - full_name: string -} - -type WithDirections = T & { directions: RawDirection[] } - -type RawTeacher = { - id: number - short_name: string - full_name: string -} - -type RawDepartment = { - id: number - short_name: string - full_name: string - teachers: RawTeacher[] - departments: RawDepartment[] -} - -type WithDepartments = T & { departments: RawDepartment[] } - -type RawEvent = { - subject_id: number - start_time: number - end_time: number - type: number - number_pair: number - auditory: string - teachers: number[] - groups: number[] -} - -type RawEventType = { - id: number - short_name: string - full_name: string - id_base: string - type: string -} - -type RawSubjectHour = { - type: number - val: number - teachers: number[] -} - -type RawSubject = { - id: number - brief: string - title: string - hours: RawSubjectHour[] -} - -type University = { - short_name: string - full_name: string -} - -type SubjectHour = { - type: EventType - hours: number - teacherId: Maybe - subjectId: number -} - -type CistAuditoriumsRawJson = { - university: University & { buildings: RawBuilding[] } -} - -type CistAuditoriumsOutput = { - buildings: Building[] - auditoriums: Auditorium[] - auditoriumTypes: AuditoriumType[] -} - -type CistGroupsOutput = { - groups: Group[] - faculties: Faculty[] - specialities: Speciality[] - directions: Direction[] -} - -type CistTeachersOutput = { - teachers: Teacher[] - faculties: Faculty[] - departments: Department[] -} - -type CistScheduleOutput = { - events: Omit[] - subjects: Subject[] - hours: SubjectHour[] -} - -type CistGroupsRawJson = { - university: University & { - faculties: WithDirections[] - } -} - -type CistTeachersRawJson = { - university: University & { - faculties: WithDepartments[] - } -} - -type CistScheduleRawJson = { - events: RawEvent[] - groups: Group[] - teachers: RawTeacher[] - subjects: RawSubject[] - types: RawEventType[] -} - -export type { - CistAuditoriumsOutput, - CistAuditoriumsRawJson, - CistGroupsOutput, - CistGroupsRawJson, - CistScheduleOutput, - CistScheduleRawJson, - CistTeachersOutput, - CistTeachersRawJson, - RawAuditorium, - RawBuilding, - RawDepartment, - RawDirection, - RawSubject, - RawTeacher, - SubjectHour, -} diff --git a/src/core/types/routes.ts b/src/core/types/routes.ts deleted file mode 100644 index 6a0ed5f..0000000 --- a/src/core/types/routes.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { RouteOptions } from 'fastify' -import type { ZodTypeProvider } from 'fastify-type-provider-zod' -import type http from 'node:http' - -type Route = RouteOptions< - http.Server, - http.IncomingMessage, - http.ServerResponse, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - any, - ZodTypeProvider -> - -interface Routes { - routes: Route[] -} - -export type { Routes } diff --git a/src/core/types/services.ts b/src/core/types/services.ts deleted file mode 100644 index 35ed002..0000000 --- a/src/core/types/services.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Schedule } from '@/db/types.js' -import type { GET_SCHEDULE_OPTIONS } from '@/modules/schedule/schemas/index.js' -import type { Maybe } from './index.js' - -interface FindableById { - findOne: (id: TIdentifier, params: TParams) => Promise> -} - -interface Schedulable { - getSchedule: (options: GET_SCHEDULE_OPTIONS) => Promise -} - -export type { FindableById, Schedulable } diff --git a/src/core/utils/common.ts b/src/core/utils/common.ts deleted file mode 100644 index 02de853..0000000 --- a/src/core/utils/common.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { FastifyReply } from 'fastify' -import { HTTP_STATUS } from '../constants/http.js' -import type { HttpError, HttpExceptionMap } from '../types/index.js' - -const throwHttpError = (reply: FastifyReply, error: HttpError) => { - const { status, message } = error - - return reply.status(status).send({ message }) -} - -const getContentType = (response: Response): string => { - return response.headers.get('content-type') || '' -} - -const mapHttpException = ( - code: K, - map: HttpExceptionMap, -) => { - return ( - map[code] ?? { - message: null, - status: HTTP_STATUS.INTERNAL_SERVER_ERR, - } - ) -} - -export { getContentType, mapHttpException, throwHttpError } diff --git a/src/core/utils/cookie.ts b/src/core/utils/cookie.ts deleted file mode 100644 index 50bcdcc..0000000 --- a/src/core/utils/cookie.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { CookieSerializeOptions } from '@fastify/cookie' -import type { FastifyReply } from 'fastify' - -interface SetCookieArgs { - name: string - value: string - expiresAt: Date -} - -const SHARED_COOKIE_OPTIONS: CookieSerializeOptions = { - httpOnly: true, - sameSite: 'lax', - path: '/', -} - -const setCookie = ({ name, value, expiresAt }: SetCookieArgs) => { - return (reply: FastifyReply): void => { - reply.setCookie(name, value, { - ...SHARED_COOKIE_OPTIONS, - expires: expiresAt, - secure: process.env.NODE_ENV === 'production', - }) - } -} - -const clearCookie = (name: string) => { - return (reply: FastifyReply): void => { - reply.clearCookie(name, { - ...SHARED_COOKIE_OPTIONS, - secure: process.env.NODE_ENV === 'production', - }) - } -} - -export { setCookie, clearCookie } diff --git a/src/core/utils/db.ts b/src/core/utils/db.ts deleted file mode 100644 index 64a785d..0000000 --- a/src/core/utils/db.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { buildingTable } from '@/db/schema/building.js' -import type { DatabaseClient } from '../types/deps.js' -import type { Redis } from 'ioredis' -import { - IS_UPDATE_IN_PROGRESS_KEY, - UPDATE_STATUS, -} from '../constants/health.js' - -const isDbEmpty = async (db: DatabaseClient): Promise => { - const rows = await db.select().from(buildingTable).limit(1) - - return rows.length === 0 -} - -const isScheduleUpdating = async (cache: Redis): Promise => { - const status = await cache.get(IS_UPDATE_IN_PROGRESS_KEY) - - if (!status) { - return false - } - - return status === UPDATE_STATUS.IN_PROGRESS -} - -export { isDbEmpty, isScheduleUpdating } diff --git a/src/core/utils/hash.ts b/src/core/utils/hash.ts deleted file mode 100644 index 42dbe6e..0000000 --- a/src/core/utils/hash.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createHash } from 'node:crypto' - -const hashObject = (o: object): string => { - const stringifiedObj = JSON.stringify(o, Object.keys(o).toSorted()) - - return createHash('sha256').update(stringifiedObj).digest('hex') -} - -export { hashObject } diff --git a/src/core/utils/index.ts b/src/core/utils/index.ts deleted file mode 100644 index d92b13f..0000000 --- a/src/core/utils/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './common.js' -export * from './db.js' -export * from './hash.js' -export * from './proxy.js' -export * from './response.js' diff --git a/src/core/utils/proxy.ts b/src/core/utils/proxy.ts deleted file mode 100644 index 0a913b9..0000000 --- a/src/core/utils/proxy.ts +++ /dev/null @@ -1,14 +0,0 @@ -const fetchProxy = async (endpoint: string): Promise => { - const response = await fetch(endpoint) - - // @ts-expect-error will be fixed soon - const data: T = await response.json() - - return data -} - -const delay = (ms: number): Promise => { - return new Promise((resolve) => setTimeout(resolve, ms)) -} - -export { fetchProxy, delay } diff --git a/src/core/utils/redis.ts b/src/core/utils/redis.ts deleted file mode 100644 index a01ce09..0000000 --- a/src/core/utils/redis.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { Redis } from 'ioredis' - -export const scanKeys = async ( - redis: Redis, - pattern: string, -): Promise => { - let cursor = '0' - const keys: string[] = [] - - do { - const result = await redis.scan(cursor, 'MATCH', pattern, 'COUNT', '1000') - cursor = result[0] - keys.push(...result[1]) - } while (cursor !== '0') - - return keys -} diff --git a/src/core/utils/response.ts b/src/core/utils/response.ts deleted file mode 100644 index d01ba84..0000000 --- a/src/core/utils/response.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { - FailureResponse, - HttpError, - SuccessResponse, -} from '../types/common.js' - -export const successResponse = ( - data: T, - message: string, -): SuccessResponse => ({ - success: true, - data, - message, - error: null, -}) - -export const failureResponse = (error: HttpError): FailureResponse => ({ - success: false, - data: null, - error, -}) diff --git a/src/core/utils/schemas.ts b/src/core/utils/schemas.ts deleted file mode 100644 index aa3bee4..0000000 --- a/src/core/utils/schemas.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { z, type ZodSchema } from 'zod' - -export const generateSuccessResponseSchema = (schema: ZodSchema) => { - return z.object({ - success: z.literal(true).describe('Flag if request completed successfully'), - data: schema.describe('Response data'), - message: z.string().optional().describe('Response message'), - error: z.null().describe('Response error'), - }) -} - -export const generateFailureResponseSchema = (statusCode: number) => { - return z.object({ - success: z.literal(false).describe('Flag if request failed'), - data: z.null().describe('Response data'), - message: z.string().optional().describe('Response message'), - error: z - .object({ - status: z.literal(statusCode).describe('HTTP status code'), - message: z.string().describe('Error message'), - }) - .describe('Response error'), - }) -} diff --git a/src/db/relations.ts b/src/db/relations.ts deleted file mode 100644 index 78eabaf..0000000 --- a/src/db/relations.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { defineRelations } from 'drizzle-orm' -import * as schema from './schema/index.js' - -export const relations = defineRelations(schema, (r) => ({ - academicGroupTable: { - events: r.many.eventToAcademicGroupTable(), - speciality: r.one.specialityTable({ - from: r.academicGroupTable.specialityId, - to: r.specialityTable.id, - optional: true, - }), - direction: r.one.directionTable({ - from: r.academicGroupTable.directionId, - to: r.directionTable.id, - optional: true, - }), - }, - auditoriumTypeToAuditoriumTable: { - auditorium: r.one.auditoriumTable({ - from: r.auditoriumTypeToAuditoriumTable.auditoriumId, - to: r.auditoriumTable.id, - optional: false, - }), - type: r.one.auditoriumTypeTable({ - from: r.auditoriumTypeToAuditoriumTable.auditoriumTypeId, - to: r.auditoriumTypeTable.id, - optional: false, - }), - }, - auditoriumTypeTable: { - auditoriums: r.many.auditoriumTypeToAuditoriumTable(), - }, - auditoriumTable: { - types: r.many.auditoriumTypeToAuditoriumTable(), - building: r.one.buildingTable({ - from: r.auditoriumTable.buildingId, - to: r.buildingTable.id, - optional: false, - }), - }, - buildingTable: { - auditoriums: r.many.auditoriumTable(), - }, - departmentTable: { - faculty: r.one.facultyTable({ - from: r.departmentTable.facultyId, - to: r.facultyTable.id, - optional: false, - }), - teachers: r.many.teacherTable(), - }, - directionTable: { - faculty: r.one.facultyTable({ - from: r.directionTable.facultyId, - to: r.facultyTable.id, - optional: false, - }), - specialities: r.many.specialityTable(), - groups: r.many.academicGroupTable(), - }, - eventToAcademicGroupTable: { - event: r.one.eventTable({ - from: r.eventToAcademicGroupTable.eventId, - to: r.eventTable.id, - optional: false, - }), - group: r.one.academicGroupTable({ - from: r.eventToAcademicGroupTable.groudId, - to: r.academicGroupTable.id, - optional: false, - }), - }, - eventToTeacherTable: { - event: r.one.eventTable({ - from: r.eventToTeacherTable.eventId, - to: r.eventTable.id, - optional: false, - }), - teacher: r.one.teacherTable({ - from: r.eventToTeacherTable.teacherId, - to: r.teacherTable.id, - optional: false, - }), - }, - eventTable: { - groups: r.many.eventToAcademicGroupTable(), - teachers: r.many.eventToTeacherTable(), - auditorium: r.one.auditoriumTable({ - from: r.eventTable.auditoriumId, - to: r.auditoriumTable.id, - optional: false, - }), - subject: r.one.subjectTable({ - from: r.eventTable.subjectId, - to: r.subjectTable.id, - optional: false, - }), - }, - facultyTable: { - departments: r.many.departmentTable(), - directions: r.many.directionTable(), - }, - specialityTable: { - groups: r.many.academicGroupTable(), - direction: r.one.directionTable({ - from: r.specialityTable.directionId, - to: r.directionTable.id, - optional: false, - }), - }, - subjectToTeacherTable: { - subject: r.one.subjectTable({ - from: r.subjectToTeacherTable.subjectId, - to: r.subjectTable.id, - optional: false, - }), - teacher: r.one.teacherTable({ - from: r.subjectToTeacherTable.teacherId, - to: r.teacherTable.id, - optional: false, - }), - }, - subjectTable: { - events: r.many.eventTable(), - teachers: r.many.subjectToTeacherTable(), - }, - teacherTable: { - department: r.one.departmentTable({ - from: r.teacherTable.departmentId, - to: r.departmentTable.id, - optional: false, - }), - events: r.many.eventToTeacherTable(), - subjects: r.many.subjectToTeacherTable(), - }, -})) diff --git a/src/db/schema/academic-group.ts b/src/db/schema/academic-group.ts deleted file mode 100644 index 6e308bd..0000000 --- a/src/db/schema/academic-group.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { pgTable } from 'drizzle-orm/pg-core' -import { baseTableAttrs, referencialIntegrityOptions } from '../utils.js' -import { directionTable } from './direction.js' -import { specialityTable } from './speciality.js' - -export const academicGroupTable = pgTable('academic_group', (t) => ({ - id: baseTableAttrs.id, - name: t.varchar({ length: 255 }).notNull(), - directionId: t - .integer() - .references(() => directionTable.id, referencialIntegrityOptions), - specialityId: t - .integer() - .references(() => specialityTable.id, referencialIntegrityOptions), -})) diff --git a/src/db/schema/auditorium-type-to-auditorium.ts b/src/db/schema/auditorium-type-to-auditorium.ts deleted file mode 100644 index 01c30f9..0000000 --- a/src/db/schema/auditorium-type-to-auditorium.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core' -import { auditoriumTable } from './auditorium.js' -import { auditoriumTypeTable } from './auditorium-type.js' -import { referencialIntegrityOptions } from '../utils.js' - -export const auditoriumTypeToAuditoriumTable = pgTable( - 'auditorium_type_to_auditorium', - { - auditoriumId: integer().references( - () => auditoriumTable.id, - referencialIntegrityOptions, - ), - auditoriumTypeId: integer().references( - () => auditoriumTypeTable.id, - referencialIntegrityOptions, - ), - }, - (t) => [primaryKey({ columns: [t.auditoriumId, t.auditoriumTypeId] })], -) diff --git a/src/db/schema/auditorium-type.ts b/src/db/schema/auditorium-type.ts deleted file mode 100644 index d5c925e..0000000 --- a/src/db/schema/auditorium-type.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { pgTable } from 'drizzle-orm/pg-core' -import { baseTableAttrs } from '../utils.js' - -export const auditoriumTypeTable = pgTable('auditorium_type', (t) => ({ - id: baseTableAttrs.id, - name: t.varchar({ length: 255 }).notNull(), -})) diff --git a/src/db/schema/auditorium.ts b/src/db/schema/auditorium.ts deleted file mode 100644 index be2d99c..0000000 --- a/src/db/schema/auditorium.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { pgTable } from 'drizzle-orm/pg-core' -import { baseTableAttrs, referencialIntegrityOptions } from '../utils.js' -import { buildingTable } from './building.js' - -export const auditoriumTable = pgTable('auditorium', (t) => ({ - id: baseTableAttrs.id, - name: t.varchar({ length: 255 }).notNull(), - floor: t.smallint(), - hasPower: t.boolean(), - buildingId: t - .varchar() - .notNull() - .references(() => buildingTable.id, referencialIntegrityOptions), -})) diff --git a/src/db/schema/building.ts b/src/db/schema/building.ts deleted file mode 100644 index 547eabd..0000000 --- a/src/db/schema/building.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { pgTable } from 'drizzle-orm/pg-core' -import { baseTableAttrs } from '../utils.js' - -const { fullName, shortName } = baseTableAttrs - -export const buildingTable = pgTable('building', (t) => ({ - id: t.varchar().primaryKey(), - fullName, - shortName, -})) diff --git a/src/db/schema/department.ts b/src/db/schema/department.ts deleted file mode 100644 index c9dd087..0000000 --- a/src/db/schema/department.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { pgTable } from 'drizzle-orm/pg-core' -import { baseTableAttrs, referencialIntegrityOptions } from '../utils.js' -import { facultyTable } from './faculty.js' - -const { id, fullName, shortName } = baseTableAttrs - -export const departmentTable = pgTable('department', (t) => ({ - id, - fullName, - shortName, - facultyId: t - .integer() - .notNull() - .references(() => facultyTable.id, referencialIntegrityOptions), -})) diff --git a/src/db/schema/direction.ts b/src/db/schema/direction.ts deleted file mode 100644 index ba80661..0000000 --- a/src/db/schema/direction.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { pgTable } from 'drizzle-orm/pg-core' -import { baseTableAttrs, referencialIntegrityOptions } from '../utils.js' -import { facultyTable } from './faculty.js' - -const { id, fullName, shortName } = baseTableAttrs - -export const directionTable = pgTable('direction', (t) => ({ - id, - fullName, - shortName, - facultyId: t - .integer() - .notNull() - .references(() => facultyTable.id, referencialIntegrityOptions), -})) diff --git a/src/db/schema/event-to-academic-group.ts b/src/db/schema/event-to-academic-group.ts deleted file mode 100644 index 1d34446..0000000 --- a/src/db/schema/event-to-academic-group.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { pgTable, primaryKey } from 'drizzle-orm/pg-core' -import { eventTable } from './event.js' -import { referencialIntegrityOptions } from '../utils.js' -import { academicGroupTable } from './academic-group.js' - -export const eventToAcademicGroupTable = pgTable( - 'event_to_academic_group', - (t) => ({ - eventId: t - .integer() - .notNull() - .references(() => eventTable.id, referencialIntegrityOptions), - groudId: t - .integer() - .notNull() - .references(() => academicGroupTable.id, referencialIntegrityOptions), - }), - (t) => [primaryKey({ columns: [t.eventId, t.groudId] })], -) diff --git a/src/db/schema/event-to-teacher.ts b/src/db/schema/event-to-teacher.ts deleted file mode 100644 index 444e928..0000000 --- a/src/db/schema/event-to-teacher.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { pgTable, primaryKey } from 'drizzle-orm/pg-core' -import { eventTable } from './event.js' -import { teacherTable } from './teacher.js' -import { referencialIntegrityOptions } from '../utils.js' - -export const eventToTeacherTable = pgTable( - 'event_to_teacher', - (t) => ({ - eventId: t - .integer() - .notNull() - .references(() => eventTable.id, referencialIntegrityOptions), - teacherId: t - .integer() - .notNull() - .references(() => teacherTable.id, referencialIntegrityOptions), - }), - (t) => [primaryKey({ columns: [t.eventId, t.teacherId] })], -) diff --git a/src/db/schema/event-type-enum.ts b/src/db/schema/event-type-enum.ts deleted file mode 100644 index 70f9fdb..0000000 --- a/src/db/schema/event-type-enum.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { pgEnum } from 'drizzle-orm/pg-core' - -export const eventTypeEnum = pgEnum('event_type', [ - 'Лк', - 'Пз', - 'Лб', - 'Конс', - 'Зал', - 'Екз', - 'КП/КР', -]) diff --git a/src/db/schema/event.ts b/src/db/schema/event.ts deleted file mode 100644 index 50243b0..0000000 --- a/src/db/schema/event.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { sql } from 'drizzle-orm' -import { bigint, check, pgTable } from 'drizzle-orm/pg-core' -import { auditoriumTable } from './auditorium.js' -import { eventTypeEnum } from './event-type-enum.js' -import { subjectTable } from './subject.js' -import { referencialIntegrityOptions } from '../utils.js' - -export const eventTable = pgTable( - 'event', - (t) => ({ - id: bigint({ mode: 'number' }).primaryKey().generatedAlwaysAsIdentity(), - startedAt: t.integer(), - endedAt: t.integer(), - numberPair: t.smallint(), - type: eventTypeEnum(), - auditoriumId: t - .integer() - .notNull() - .references(() => auditoriumTable.id, referencialIntegrityOptions), - subjectId: t - .integer() - .notNull() - .references(() => subjectTable.id, referencialIntegrityOptions), - }), - (t) => [check('start_before_end', sql`${t.startedAt} < ${t.endedAt}`)], -) diff --git a/src/db/schema/faculty.ts b/src/db/schema/faculty.ts deleted file mode 100644 index f166595..0000000 --- a/src/db/schema/faculty.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { pgTable } from 'drizzle-orm/pg-core' -import { baseTableAttrs } from '../utils.js' - -const { id, fullName, shortName } = baseTableAttrs - -export const facultyTable = pgTable('faculty', { - id, - fullName, - shortName, -}) diff --git a/src/db/schema/index.ts b/src/db/schema/index.ts deleted file mode 100644 index f43b96c..0000000 --- a/src/db/schema/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -export * from './academic-group.js' -export * from './auditorium-type-to-auditorium.js' -export * from './auditorium-type.js' -export * from './auditorium.js' -export * from './building.js' -export * from './department.js' -export * from './direction.js' -export * from './event-to-academic-group.js' -export * from './event-to-teacher.js' -export * from './event.js' -export * from './faculty.js' -export * from './speciality.js' -export * from './subject-to-teacher.js' -export * from './subject.js' -export * from './teacher.js' diff --git a/src/db/schema/speciality.ts b/src/db/schema/speciality.ts deleted file mode 100644 index 90c9709..0000000 --- a/src/db/schema/speciality.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { pgTable } from 'drizzle-orm/pg-core' -import { baseTableAttrs, referencialIntegrityOptions } from '../utils.js' -import { directionTable } from './direction.js' - -const { id, fullName, shortName } = baseTableAttrs - -export const specialityTable = pgTable('speciality', (t) => ({ - id, - fullName, - shortName, - directionId: t - .integer() - .notNull() - .references(() => directionTable.id, referencialIntegrityOptions), -})) diff --git a/src/db/schema/subject-to-teacher.ts b/src/db/schema/subject-to-teacher.ts deleted file mode 100644 index 81b6421..0000000 --- a/src/db/schema/subject-to-teacher.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { bigint, pgTable } from 'drizzle-orm/pg-core' -import { eventTypeEnum } from './event-type-enum.js' -import { subjectTable } from './subject.js' -import { teacherTable } from './teacher.js' -import { referencialIntegrityOptions } from '../utils.js' - -export const subjectToTeacherTable = pgTable('subject_to_teacher', (t) => ({ - id: bigint({ mode: 'number' }).primaryKey().generatedAlwaysAsIdentity(), - hours: t.smallint(), - type: eventTypeEnum(), - subjectId: t - .integer() - .notNull() - .references(() => subjectTable.id, referencialIntegrityOptions), - teacherId: t - .integer() - .notNull() - .references(() => teacherTable.id, referencialIntegrityOptions), -})) diff --git a/src/db/schema/subject.ts b/src/db/schema/subject.ts deleted file mode 100644 index 3fb0f4c..0000000 --- a/src/db/schema/subject.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { pgTable } from 'drizzle-orm/pg-core' -import { baseTableAttrs } from '../utils.js' - -export const subjectTable = pgTable('subject', (t) => ({ - id: baseTableAttrs.id, - name: t.varchar({ length: 255 }).notNull(), - brief: t.varchar({ length: 100 }).notNull(), -})) diff --git a/src/db/schema/teacher.ts b/src/db/schema/teacher.ts deleted file mode 100644 index 91de5e5..0000000 --- a/src/db/schema/teacher.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { pgTable } from 'drizzle-orm/pg-core' -import { baseTableAttrs, referencialIntegrityOptions } from '../utils.js' -import { departmentTable } from './department.js' - -const { id, fullName, shortName } = baseTableAttrs - -export const teacherTable = pgTable('teacher', (t) => ({ - id, - fullName, - shortName, - departmentId: t - .integer() - .notNull() - .references(() => departmentTable.id, referencialIntegrityOptions), -})) diff --git a/src/db/types.ts b/src/db/types.ts deleted file mode 100644 index 3d66863..0000000 --- a/src/db/types.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type { academicGroupTable } from './schema/academic-group.js' -import type { auditoriumTypeTable } from './schema/auditorium-type.js' -import type { auditoriumTable } from './schema/auditorium.js' -import type { buildingTable } from './schema/building.js' -import type { departmentTable } from './schema/department.js' -import type { directionTable } from './schema/direction.js' -import type { eventTypeEnum } from './schema/event-type-enum.js' -import type { facultyTable } from './schema/faculty.js' -import type { specialityTable } from './schema/speciality.js' -import type { subjectTable } from './schema/subject.js' -import type { teacherTable } from './schema/teacher.js' - -type Auditorium = typeof auditoriumTable.$inferSelect -type AuditoriumType = typeof auditoriumTypeTable.$inferSelect & { - auditoriumId: number -} -type Building = typeof buildingTable.$inferSelect -type Group = typeof academicGroupTable.$inferSelect -type Faculty = typeof facultyTable.$inferSelect -type Department = typeof departmentTable.$inferSelect -type Direction = typeof directionTable.$inferSelect -type Speciality = typeof specialityTable.$inferSelect -type Teacher = typeof teacherTable.$inferSelect -type Subject = typeof subjectTable.$inferSelect - -type TeacherData = Omit -type GroupData = Omit - -type Event = { - id: number - numberPair: number - startTime: number - endTime: number - type: EventType - auditorium: string - subject: Subject - groups: GroupData[] - teachers: TeacherData[] -} - -type EventType = (typeof eventTypeEnum.enumValues)[number] - -type Schedule = Omit & { - startedAt: string - endedAt: string -} - -export type { - Auditorium, - AuditoriumType, - Building, - Department, - Direction, - Event, - EventType, - Faculty, - Group, - GroupData, - Speciality, - Subject, - Teacher, - TeacherData, - Schedule, -} diff --git a/src/db/utils.ts b/src/db/utils.ts deleted file mode 100644 index dca4b52..0000000 --- a/src/db/utils.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { integer, varchar } from 'drizzle-orm/pg-core' - -const referencialIntegrityOptions = { - onDelete: 'cascade', - onUpdate: 'cascade', -} as const - -const baseTableAttrs = { - id: integer().primaryKey().notNull(), - fullName: varchar({ length: 255 }).notNull(), - shortName: varchar({ length: 40 }).notNull(), -} - -export { baseTableAttrs, referencialIntegrityOptions } diff --git a/src/env.ts b/src/env.ts deleted file mode 100644 index b2001a2..0000000 --- a/src/env.ts +++ /dev/null @@ -1,33 +0,0 @@ -import 'dotenv/config.js' -import { z } from 'zod' - -const envSchema = z.object({ - PORT: z.coerce.number().min(1000), - POSTGRES_HOST: z.string(), - POSTGRES_DB: z.string(), - POSTGRES_USER: z.string(), - POSTGRES_PASSWORD: z.string(), - POSTGRES_PORT: z.coerce.number().default(5432), - COOKIE_SECRET: z.string(), - CACHE_HOST: z.string(), - CACHE_USER: z.string(), - CACHE_PASSWORD: z.string(), - CACHE_PORT: z.coerce.number().default(6379), - PROXY_BASE_URL: z.string(), - DISCORD_WEBHOOK_URL: z.url({ - protocol: /^https$/, - hostname: /^discord\.com$/, - }), - ALLOWED_ORIGINS: z - .string() - .transform((val) => val.split(',')) - .default(['https://sh.mindenit.org', 'http://localhost:3000']), - MOODLE_BASE_URL: z.url({ - protocol: /^https?$/, - hostname: /^([a-zA-Z0-9-]+\.)*nure\.ua$/, - }), -}) - -const env = envSchema.parse(process.env) - -export { env } diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index 164ef4e..0000000 --- a/src/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { App } from './app.js' -import { isDbEmpty, isScheduleUpdating } from './core/utils/index.js' -import { cistPostmanJob } from './modules/schedule/jobs/postman.js' - -const bootstrap = async () => { - const port = 8080 as const - - try { - const app = new App() - const server = await app.initialize() - - server.listen({ port, host: '0.0.0.0' }) - - console.log(`Server is running on port ${port}`) - - const [isEmpty, isUpdating] = await Promise.all([ - isDbEmpty(server.diContainer.cradle.db.client), - isScheduleUpdating(server.diContainer.cradle.cache), - ]) - - if (isEmpty || isUpdating) { - await cistPostmanJob(server) - } - } catch (e: unknown) { - console.warn(e) - process.exit(1) - } -} - -void bootstrap() diff --git a/src/infrastructure/commonDiConfig.ts b/src/infrastructure/commonDiConfig.ts deleted file mode 100644 index c9fc6f6..0000000 --- a/src/infrastructure/commonDiConfig.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { - CommonDependencies, - ExternalDependencies, -} from '@/core/types/deps.js' -import { asFunction, type NameAndRegistrationPair } from 'awilix' -import { drizzle } from 'drizzle-orm/postgres-js' -import postgres from 'postgres' -import { getConfig } from './config.js' -import { Redis } from 'ioredis' -import { relations } from '@/db/relations.js' -import { DefaultLogger } from 'drizzle-orm' -import { DrizzleWriter } from '@/core/services/DrizzleWriter.js' - -export const resolveCommonDiConfig = ( - dependencies: ExternalDependencies, -): NameAndRegistrationPair => ({ - logger: asFunction(() => dependencies.app.log).singleton(), - config: asFunction(() => getConfig()).singleton(), - db: asFunction( - (deps: CommonDependencies) => { - const { config } = deps - const { user, password, host, port, database } = config.db - - const queryClient = postgres({ - username: user, - password, - host, - port, - database, - }) - - const logger = new DefaultLogger({ - writer: new DrizzleWriter(deps), - }) - - return { - client: drizzle(queryClient, { - relations, - logger, - casing: 'snake_case', - }), - connection: queryClient, - } - }, - { - dispose: ({ connection }) => { - connection.end() - }, - }, - ).singleton(), - cache: asFunction( - ({ config }: CommonDependencies) => { - const { user, password, port, host } = config.cache - - const cache = new Redis({ - port, - host, - username: user, - password: password, - }) - - return cache - }, - { - dispose: (redis) => { - redis.disconnect() - }, - }, - ).singleton(), -}) diff --git a/src/infrastructure/config.ts b/src/infrastructure/config.ts deleted file mode 100644 index 9940629..0000000 --- a/src/infrastructure/config.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { - Config, - DbConfig, - CacheConfig, - ProxyConfig, - MoodleConfig, -} from '@/core/types/index.js' -import { env } from '@/env.js' - -const getDbConfig = (): DbConfig => ({ - user: env.POSTGRES_USER, - password: env.POSTGRES_PASSWORD, - host: env.POSTGRES_HOST, - port: env.POSTGRES_PORT, - database: env.POSTGRES_DB, -}) - -const getCacheConfig = (): CacheConfig => ({ - host: env.CACHE_HOST, - user: env.CACHE_USER, - password: env.CACHE_PASSWORD, - port: env.CACHE_PORT, -}) - -const getProxyConfig = (): ProxyConfig => ({ - baseUrl: env.PROXY_BASE_URL, -}) - -const getIntegrationConfig = () => ({ - discordWebhookUrl: env.DISCORD_WEBHOOK_URL, -}) - -const getMoodleConfig = (): MoodleConfig => ({ - baseUrl: env.MOODLE_BASE_URL, -}) - -const getConfig = (): Config => ({ - db: getDbConfig(), - cache: getCacheConfig(), - proxy: getProxyConfig(), - integration: getIntegrationConfig(), - moodle: getMoodleConfig(), -}) - -export { getConfig } diff --git a/src/infrastructure/parentDiConfig.ts b/src/infrastructure/parentDiConfig.ts deleted file mode 100644 index 76d806b..0000000 --- a/src/infrastructure/parentDiConfig.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type { - CommonDependencies, - ExternalDependencies, -} from '@/core/types/deps.js' -import type { AwilixContainer, NameAndRegistrationPair } from 'awilix' -import { resolveCommonDiConfig } from './commonDiConfig.js' -import type { AuditoriumsModuleDependencies } from '@/modules/auditoriums/types/index.js' -import { resolveAuditoriumsModule } from '@/modules/auditoriums/index.js' -import type { GroupsModuleDependencies } from '@/modules/groups/types/index.js' -import { resolveGroupsModule } from '@/modules/groups/index.js' -import type { TeachersModuleDependencies } from '@/modules/teachers/types/index.js' -import { resolveTeachersModule } from '@/modules/teachers/index.js' -import type { EventModuleDependencies } from '@/modules/events/types/index.js' -import { resolveEventsModule } from '@/modules/events/index.js' -import type { LinksModuleDependencies } from '@/modules/links/types/index.js' -import { resolveLinksModule } from '@/modules/links/index.js' -import type { MoodleModuleDependencies } from '@/modules/moodle/types/di.js' -import { resolveMoodleModule } from '@/modules/moodle/index.js' - -type Dependencies = CommonDependencies & - AuditoriumsModuleDependencies & - GroupsModuleDependencies & - EventModuleDependencies & - TeachersModuleDependencies & - LinksModuleDependencies & - MoodleModuleDependencies - -type DiConfig = NameAndRegistrationPair - -export const registerDependencies = ( - diContainer: AwilixContainer, - dependencies: ExternalDependencies, -) => { - const diConfig: DiConfig = { - ...resolveCommonDiConfig(dependencies), - ...resolveAuditoriumsModule(), - ...resolveGroupsModule(), - ...resolveTeachersModule(), - ...resolveEventsModule(), - ...resolveLinksModule(), - ...resolveMoodleModule(), - } - - diContainer.register(diConfig) -} - -declare module '@fastify/awilix' { - // eslint-disable-next-line @typescript-eslint/no-empty-object-type - interface Cradle extends Dependencies {} - - // eslint-disable-next-line @typescript-eslint/no-empty-object-type - interface RequestCradle extends Dependencies {} -} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..63e4b92 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,82 @@ +import { INestApplication } from '@nestjs/common' +import { NestFactory, Reflector } from '@nestjs/core' +import { + FastifyAdapter, + NestFastifyApplication, +} from '@nestjs/platform-fastify' +import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger' +import { apiReference } from '@scalar/nestjs-api-reference' +import { + cleanupOpenApiDoc, + ZodSerializerInterceptor, + ZodValidationPipe, +} from 'nestjs-zod' +import { AppModule } from './app.module' +import { GlobalExceptionFilter } from './common/filters/global-exception.filter' +import { ConfigService } from './components/config/config.service' +import { ErrorsInterceptor } from './common/interceptors/error.interceptor' +import { TransformInterceptor } from './common/interceptors/transform.interceptor' +import { Logger } from 'nestjs-pino' + +const useSwagger = (app: INestApplication) => { + const config = new DocumentBuilder() + .setTitle('Mindenit Hub API') + .setDescription('API for Mindenit Hub application') + .setVersion('1.0.0') + .addTag('API') + .addSecurity('access-token', { + type: 'apiKey', + in: 'cookie', + name: 'schedule-client-id', + }) + .addSecurityRequirements('access-token') + .build() + + const document = SwaggerModule.createDocument(app, config) + + SwaggerModule.setup('api', app, cleanupOpenApiDoc(document)) + + app.use( + '/api', + apiReference({ + content: document, + withFastify: true, + theme: 'deepSpace', + metaData: { + title: 'Mindenit Hub API Reference', + description: '', + }, + }), + ) +} + +async function bootstrap() { + const app = await NestFactory.create( + AppModule, + new FastifyAdapter(), + { + bufferLogs: true, + cors: { + credentials: true, + methods: ['GET', 'PUT', 'PATCH', 'POST', 'DELETE', 'OPTIONS'], + maxAge: 86_400, + }, + }, + ) + + useSwagger(app) + + const configService = app.get(ConfigService) + const { port } = configService.get('server') + + app.useLogger(app.get(Logger)) + app.useGlobalFilters(new GlobalExceptionFilter()) + app.useGlobalInterceptors(new ZodSerializerInterceptor(app.get(Reflector))) + app.useGlobalInterceptors(new ErrorsInterceptor()) + app.useGlobalInterceptors(new TransformInterceptor()) + app.useGlobalPipes(new ZodValidationPipe()) + + await app.listen(port) +} + +void bootstrap() diff --git a/src/modules/auditoriums/handlers/index.ts b/src/modules/auditoriums/handlers/index.ts deleted file mode 100644 index 9eaf909..0000000 --- a/src/modules/auditoriums/handlers/index.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { - type GET_SCHEDULE_PARAMS, - type GET_SCHEDULE_QUERY, -} from '@/modules/schedule/schemas/index.js' -import type { FastifyReply, FastifyRequest } from 'fastify' -import type { GET_AUDITORIUM_SCHEDULE_FILTERS } from '../schemas/index.js' - -export const getAuditoriums = async ( - request: FastifyRequest, - reply: FastifyReply, -): Promise => { - const { auditoriumsService } = request.diScope.cradle - - const data = await auditoriumsService.getAuditoriums() - - return reply.status(200).send(data) -} - -export const getAuditoriumGroups = async ( - request: FastifyRequest<{ - Params: GET_SCHEDULE_PARAMS - }>, - reply: FastifyReply, -): Promise => { - const { auditoriumsService } = request.diScope.cradle - const { id } = request.params - - const data = await auditoriumsService.getGroups(id) - - return reply.status(200).send(data) -} - -export const getAuditoriumTeachers = async ( - request: FastifyRequest<{ - Params: GET_SCHEDULE_PARAMS - }>, - reply: FastifyReply, -): Promise => { - const { auditoriumsService } = request.diScope.cradle - const { id } = request.params - - const data = await auditoriumsService.getTeachers(id) - - return reply.status(200).send(data) -} - -export const getAuditoriumSubjects = async ( - request: FastifyRequest<{ - Params: GET_SCHEDULE_PARAMS - }>, - reply: FastifyReply, -): Promise => { - const { auditoriumsService } = request.diScope.cradle - const { id } = request.params - - const data = await auditoriumsService.getSubjects(id) - - return reply.status(200).send(data) -} - -export const getAuditoriumSchedule = async ( - request: FastifyRequest<{ - Params: GET_SCHEDULE_PARAMS - Querystring: GET_SCHEDULE_QUERY - }>, - reply: FastifyReply, -): Promise => { - const { auditoriumsService } = request.diScope.cradle - const { id } = request.params - - const data = await auditoriumsService.getSchedule({ id, ...request.query }) - - return reply.status(200).send(data) -} diff --git a/src/modules/auditoriums/index.ts b/src/modules/auditoriums/index.ts deleted file mode 100644 index 979ee93..0000000 --- a/src/modules/auditoriums/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { asClass } from 'awilix' -import { AuditoriumsParserImpl } from './parsers/AuditoriumsParser.js' -import { AuditoriumProcessorImpl } from './processors/AuditoriumProcessor.js' -import type { AuditoriumsDiConfig } from './types/index.js' -import { AuditoriumsRepositoryImpl } from './repositories/AuditoriumsRepository.js' -import { AuditoriumsServiceImpl } from './services/AuditoriumsService.js' - -export const resolveAuditoriumsModule = (): AuditoriumsDiConfig => ({ - auditoriumsParser: asClass(AuditoriumsParserImpl).singleton(), - auditoriumsProcessor: asClass(AuditoriumProcessorImpl).singleton(), - auditoriumsRepository: asClass(AuditoriumsRepositoryImpl).singleton(), - auditoriumsService: asClass(AuditoriumsServiceImpl).singleton(), -}) diff --git a/src/modules/auditoriums/parsers/AuditoriumsParser.ts b/src/modules/auditoriums/parsers/AuditoriumsParser.ts deleted file mode 100644 index 1acfca8..0000000 --- a/src/modules/auditoriums/parsers/AuditoriumsParser.ts +++ /dev/null @@ -1,92 +0,0 @@ -import type { Auditorium, AuditoriumType, Building } from '@/db/types.js' -import type { Maybe } from '@/core/types/common.js' -import type { CommonDependencies } from '@/core/types/deps.js' -import type { - CistAuditoriumsOutput, - CistAuditoriumsRawJson, -} from '@/core/types/proxy.js' -import { fetchProxy, hashObject } from '@/core/utils/index.js' -import type { CistParser } from '@/core/types/cist.js' - -export class AuditoriumsParserImpl - implements CistParser -{ - private readonly endpoint: string - - constructor({ config }: CommonDependencies) { - const { baseUrl } = config.proxy - - this.endpoint = `${baseUrl}/lists/auditories` - } - - async parse(): Promise> { - try { - const raw = await fetchProxy(this.endpoint) - - const auditoriums: Auditorium[] = [] - const auditoriumTypes: AuditoriumType[] = [] - const buildings: Building[] = [] - - const hashMap = new Map() - - if (!Object.hasOwn(raw, 'university')) { - return null - } - - if (!Object.hasOwn(raw.university, 'buildings')) { - return null - } - - for (const building of raw.university.buildings) { - if (!Object.hasOwn(building, 'auditories')) { - continue - } - - for (const auditorium of building.auditories) { - if (!auditorium.short_name.length) { - continue - } - - const hash = hashObject(auditorium) - - if (hashMap.has(hash)) { - continue - } - - for (const type of auditorium.auditory_types) { - auditoriumTypes.push({ - id: Number.parseInt(type.id), - name: type.short_name, - auditoriumId: Number.parseInt(auditorium.id), - }) - } - - auditoriums.push({ - id: Number.parseInt(auditorium.id), - name: auditorium.short_name, - hasPower: Boolean(auditorium.is_have_power), - floor: - auditorium.floor === '' ? 0 : Number.parseInt(auditorium.floor), - buildingId: building.id, - }) - - hashMap.set(hash, true) - } - - buildings.push({ - id: building.id, - fullName: building.full_name, - shortName: building.short_name, - }) - } - - return { buildings, auditoriums, auditoriumTypes } - } catch (e: unknown) { - const message = e instanceof Error ? e.message : String(e) - - throw new Error( - `[AuditoriumsParser] Failed to fetch or parse auditoriums data: ${message}`, - ) - } - } -} diff --git a/src/modules/auditoriums/processors/AuditoriumProcessor.ts b/src/modules/auditoriums/processors/AuditoriumProcessor.ts deleted file mode 100644 index 64d04bd..0000000 --- a/src/modules/auditoriums/processors/AuditoriumProcessor.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { RedisKeyBuilder } from '@/core/builders/RedisKeyBulder.js' -import type { CistParser, CistProcessor } from '@/core/types/cist.js' -import type { DatabaseClient } from '@/core/types/deps.js' -import type { CistAuditoriumsOutput } from '@/core/types/proxy.js' -import { - auditoriumTable, - auditoriumTypeTable, - auditoriumTypeToAuditoriumTable, - buildingTable, -} from '@/db/schema/index.js' -import type { Auditorium } from '@/db/types.js' -import type { Redis } from 'ioredis' -import type { AuditoriumsInjectableDependencies } from '../types/index.js' - -export class AuditoriumProcessorImpl implements CistProcessor { - private readonly db: DatabaseClient - private readonly cache: Redis - private readonly parser: CistParser - - constructor({ - db, - cache, - auditoriumsParser, - }: AuditoriumsInjectableDependencies) { - this.db = db.client - this.cache = cache - this.parser = auditoriumsParser - } - - async process(): Promise { - try { - const data = await this.parser.parse() - - if (!data) { - return [] - } - - const { buildings, auditoriums, auditoriumTypes } = data - - for (const building of buildings) { - const key = RedisKeyBuilder.buildingKey(building.id) - - const isExists = await this.cache.get(key) - - if (isExists) { - continue - } - - await this.db.insert(buildingTable).values(building) - await this.cache.set(key, 'exists') - } - - for (const auditorium of auditoriums) { - const key = RedisKeyBuilder.auditoriumKey(auditorium.id) - - const isExists = await this.cache.get(key) - - if (isExists) { - continue - } - - await this.db.insert(auditoriumTable).values(auditorium) - await this.cache.set(key, 'exists') - } - - for (const type of auditoriumTypes) { - const key = RedisKeyBuilder.auditoriumTypeKey(type.id) - - const isExists = await this.cache.get(key) - - if (isExists) { - continue - } - - await this.db.transaction(async (tx) => { - await tx.insert(auditoriumTypeTable).values(type) - await tx.insert(auditoriumTypeToAuditoriumTable).values({ - auditoriumId: type.auditoriumId, - auditoriumTypeId: type.id, - }) - }) - - await this.cache.set(key, 'exists') - } - - return data.auditoriums - } catch (e: unknown) { - if (e instanceof Error && e.message.includes('[AuditoriumsParser]')) { - throw new Error(e.message) - } - - const message = `[AuditoriumsProcessor] Failed to process data: ${e instanceof Error ? e.message : 'Unknown error'}` - - throw new Error(message) - } - } -} diff --git a/src/modules/auditoriums/repositories/AuditoriumsRepository.ts b/src/modules/auditoriums/repositories/AuditoriumsRepository.ts deleted file mode 100644 index bbfdead..0000000 --- a/src/modules/auditoriums/repositories/AuditoriumsRepository.ts +++ /dev/null @@ -1,130 +0,0 @@ -import type { DatabaseClient } from '@/core/types/deps.js' -import { auditoriumTable } from '@/db/schema/auditorium.js' -import type { - Auditorium, - Group, - Schedule, - Subject, - Teacher, -} from '@/db/types.js' -import type { GET_SCHEDULE_OPTIONS } from '@/modules/schedule/schemas/index.js' -import { SQL, asc, eq, notLike, sql } from 'drizzle-orm' -import type { - AuditoriumsInjectableDependencies, - AuditoriumsRepository, -} from '../types/index.js' - -import type { Maybe } from '@/core/types/index.js' -import { academicGroupTable } from '@/db/schema/academic-group.js' -import { eventToAcademicGroupTable } from '@/db/schema/event-to-academic-group.js' -import { eventToTeacherTable } from '@/db/schema/event-to-teacher.js' -import { eventTable } from '@/db/schema/event.js' -import { subjectTable } from '@/db/schema/subject.js' -import { teacherTable } from '@/db/schema/teacher.js' -import { - buildScheduleQuery, - getTimeIntervalQuery, -} from '@/modules/schedule/utils/index.js' -import type { GET_AUDITORIUM_SCHEDULE_FILTERS } from '../schemas/index.js' -import { getAuditoriumFiltersQuery } from '../utils/index.js' - -export class AuditoriumsRepositoryImpl implements AuditoriumsRepository { - private readonly db: DatabaseClient - - constructor({ db }: AuditoriumsInjectableDependencies) { - this.db = db.client - } - - async findAll(): Promise { - return this.db - .select() - .from(auditoriumTable) - .where(notLike(auditoriumTable.name, 'DL%')) - .orderBy(asc(auditoriumTable.name)) - } - - async findOne(id: number): Promise> { - const [auditorium] = await this.db - .select() - .from(auditoriumTable) - .where(eq(auditoriumTable.id, id)) - - return auditorium ?? null - } - - async getGroups(auditoriumId: number): Promise[]> { - return this.db - .selectDistinct({ - id: academicGroupTable.id, - name: academicGroupTable.name, - }) - .from(eventTable) - .innerJoin( - eventToAcademicGroupTable, - eq(eventTable.id, eventToAcademicGroupTable.eventId), - ) - .innerJoin( - academicGroupTable, - eq(eventToAcademicGroupTable.groudId, academicGroupTable.id), - ) - .where(eq(eventTable.auditoriumId, auditoriumId)) - .orderBy(asc(academicGroupTable.name)) - } - - async getTeachers( - auditoriumId: number, - ): Promise[]> { - return this.db - .selectDistinct({ - id: teacherTable.id, - shortName: teacherTable.shortName, - fullName: teacherTable.fullName, - }) - .from(eventTable) - .innerJoin( - eventToTeacherTable, - eq(eventTable.id, eventToTeacherTable.eventId), - ) - .innerJoin( - teacherTable, - eq(eventToTeacherTable.teacherId, teacherTable.id), - ) - .where(eq(eventTable.auditoriumId, auditoriumId)) - .orderBy(asc(teacherTable.shortName)) - } - - async getSubjects(auditoriumId: number): Promise { - return this.db - .selectDistinct({ - id: subjectTable.id, - name: subjectTable.name, - brief: subjectTable.brief, - }) - .from(eventTable) - .innerJoin(subjectTable, eq(eventTable.subjectId, subjectTable.id)) - .where(eq(eventTable.auditoriumId, auditoriumId)) - .orderBy(asc(subjectTable.brief)) - } - - async getSchedule( - options: GET_SCHEDULE_OPTIONS, - ): Promise { - const { id } = options - - const whereClause: SQL[] = [sql`e.auditorium_id = ${id}`] - - const timeInterval = getTimeIntervalQuery(options) - - whereClause.push(...timeInterval) - - const filters = getAuditoriumFiltersQuery(options.filters) - - whereClause.push(...filters) - - const query = buildScheduleQuery(whereClause) - - const schedule = await this.db.execute(query) - - return schedule as unknown as Schedule[] - } -} diff --git a/src/modules/auditoriums/routes/index.ts b/src/modules/auditoriums/routes/index.ts deleted file mode 100644 index ee098a3..0000000 --- a/src/modules/auditoriums/routes/index.ts +++ /dev/null @@ -1,108 +0,0 @@ -import type { Routes } from '@/core/types/routes.js' -import { generateSuccessResponseSchema } from '@/core/utils/schemas.js' -import { GROUP_SCHEMA, SUBJECT_SCHEMA } from '@/modules/groups/schemas/index.js' -import { - GET_SCHEDULE_PARAMS_SCHEMA, - SCHEDULE_SCHEMA, -} from '@/modules/schedule/schemas/index.js' -import { getScheduleQuerySchema } from '@/modules/schedule/utils/index.js' -import { TEACHER_SCHEMA } from '@/modules/teachers/schemas/index.js' -import { - getAuditoriumGroups, - getAuditoriumSchedule, - getAuditoriumSubjects, - getAuditoriumTeachers, - getAuditoriums, -} from '../handlers/index.js' -import { - AUDITORIUM_SCHEMA, - GET_AUDITORIUM_SCHEDULE_FILTERS_SCHEMA, -} from '../schemas/index.js' - -export const getAuditoriumsRoutes = (): Routes => ({ - routes: [ - { - method: 'GET', - url: '/auditoriums', - handler: getAuditoriums, - schema: { - summary: 'Get auditoriums', - description: 'Get list of auditoriums', - tags: ['Auditoriums'], - response: { - 200: generateSuccessResponseSchema( - AUDITORIUM_SCHEMA.array(), - ).describe('Successful response'), - }, - }, - }, - { - method: 'GET', - url: '/auditoriums/:id/groups', - handler: getAuditoriumGroups, - schema: { - summary: 'Get auditorium groups', - description: 'Get groups for a specific auditorium', - tags: ['Auditoriums'], - params: GET_SCHEDULE_PARAMS_SCHEMA, - response: { - 200: generateSuccessResponseSchema( - GROUP_SCHEMA.pick({ id: true, name: true }).array(), - ).describe('Successful response'), - }, - }, - }, - { - method: 'GET', - url: '/auditoriums/:id/teachers', - handler: getAuditoriumTeachers, - schema: { - summary: 'Get auditorium teachers', - description: 'Get teachers for a specific auditorium', - tags: ['Auditoriums'], - params: GET_SCHEDULE_PARAMS_SCHEMA, - response: { - 200: generateSuccessResponseSchema( - TEACHER_SCHEMA.omit({ departmentId: true }).array(), - ).describe('Successful response'), - }, - }, - }, - { - method: 'GET', - url: '/auditoriums/:id/subjects', - handler: getAuditoriumSubjects, - schema: { - summary: 'Get auditorium subjects', - description: 'Get subjects for a specific auditorium', - tags: ['Auditoriums'], - params: GET_SCHEDULE_PARAMS_SCHEMA, - response: { - 200: generateSuccessResponseSchema(SUBJECT_SCHEMA.array()).describe( - 'Successful response', - ), - }, - }, - }, - { - method: 'GET', - url: '/auditoriums/:id/schedule', - handler: getAuditoriumSchedule, - schema: { - summary: 'Get auditorium schedule', - description: - 'Get schedule for an auditorium in particular time interval', - tags: ['Auditoriums'], - params: GET_SCHEDULE_PARAMS_SCHEMA, - querystring: getScheduleQuerySchema( - GET_AUDITORIUM_SCHEDULE_FILTERS_SCHEMA, - ), - response: { - 200: generateSuccessResponseSchema(SCHEDULE_SCHEMA.array()).describe( - 'Successful response', - ), - }, - }, - }, - ], -}) diff --git a/src/modules/auditoriums/schemas/index.ts b/src/modules/auditoriums/schemas/index.ts deleted file mode 100644 index a435c3d..0000000 --- a/src/modules/auditoriums/schemas/index.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { - transformEventTypesParam, - transformIdsParam, -} from '@/modules/schedule/utils/query-string.js' -import { z } from 'zod' - -const AUDITORIUM_SCHEMA = z.object({ - id: z.number().int().describe('Auditorium identifier'), - name: z.string().max(255).describe('Name of auditorium'), - floor: z.number().int().describe('Floor where auditorium is located'), - hasPower: z.boolean(), - buildingId: z - .string() - .describe('Identifier of building where auditorium is located'), -}) - -const GET_AUDITORIUM_SCHEDULE_FILTERS_SCHEMA = z - .object({ - lessonTypes: z - .string() - .nullable() - .default(null) - .transform(transformEventTypesParam) - .describe('Comma-separated list of lesson types. Example: "Лк,Пз"'), - teachers: z - .string() - .nullable() - .default(null) - .transform(transformIdsParam) - .describe( - 'Comma-separated list of teacher identifiers. Example: "1,2,3"', - ), - groups: z - .string() - .nullable() - .default(null) - .transform(transformIdsParam) - .describe( - 'Comma-separated list of group identifiers. Example: "101,102"', - ), - subjects: z - .string() - .nullable() - .default(null) - .transform(transformIdsParam) - .describe( - 'Comma-separated list of subject identifiers. Example: "1,2,3"', - ), - }) - .default({ - lessonTypes: [], - teachers: [], - groups: [], - subjects: [], - }) - -type GET_AUDITORIUM_SCHEDULE_FILTERS = z.infer< - typeof GET_AUDITORIUM_SCHEDULE_FILTERS_SCHEMA -> - -export { AUDITORIUM_SCHEMA, GET_AUDITORIUM_SCHEDULE_FILTERS_SCHEMA } -export type { GET_AUDITORIUM_SCHEDULE_FILTERS } diff --git a/src/modules/auditoriums/services/AuditoriumsService.ts b/src/modules/auditoriums/services/AuditoriumsService.ts deleted file mode 100644 index c599aca..0000000 --- a/src/modules/auditoriums/services/AuditoriumsService.ts +++ /dev/null @@ -1,90 +0,0 @@ -import type { BaseResponse } from '@/core/types/common.js' -import type { - AuditoriumsInjectableDependencies, - AuditoriumsRepository, - AuditoriumsService, -} from '../types/index.js' -import type { - Auditorium, - Group, - Schedule, - Subject, - Teacher, -} from '@/db/types.js' -import type { GET_SCHEDULE_OPTIONS } from '@/modules/schedule/schemas/index.js' -import { successResponse } from '@/core/utils/response.js' -import { isDLAuditorium } from '../utils/index.js' -import type { GET_AUDITORIUM_SCHEDULE_FILTERS } from '../schemas/index.js' - -export class AuditoriumsServiceImpl implements AuditoriumsService { - repository: AuditoriumsRepository - - constructor({ auditoriumsRepository }: AuditoriumsInjectableDependencies) { - this.repository = auditoriumsRepository - } - - async getAuditoriums(): Promise> { - const auditoriums = await this.repository.findAll() - const message = 'Auditoriums fetched successfully' - - return successResponse(auditoriums, message) - } - - async getGroups( - auditoriumId: number, - ): Promise[]>> { - const auditorium = await this.repository.findOne(auditoriumId) - const message = `Groups for auditorium with id ${auditoriumId} found successfully` - - if (isDLAuditorium(auditorium)) { - return successResponse([], message) - } - - const groups = await this.repository.getGroups(auditoriumId) - - return successResponse(groups, message) - } - - async getTeachers( - auditoriumId: number, - ): Promise[]>> { - const auditorium = await this.repository.findOne(auditoriumId) - const message = `Teachers for auditorium with id ${auditoriumId} found successfully` - - if (isDLAuditorium(auditorium)) { - return successResponse([], message) - } - - const teachers = await this.repository.getTeachers(auditoriumId) - - return successResponse(teachers, message) - } - - async getSubjects(auditoriumId: number): Promise> { - const auditorium = await this.repository.findOne(auditoriumId) - const message = `Subjects for auditorium with id ${auditoriumId} found successfully` - - if (isDLAuditorium(auditorium)) { - return successResponse([], message) - } - - const subjects = await this.repository.getSubjects(auditoriumId) - - return successResponse(subjects, message) - } - - async getSchedule( - options: GET_SCHEDULE_OPTIONS, - ): Promise> { - const auditorium = await this.repository.findOne(options.id) - const message = `Schedule for auditorium with id ${options.id} found successfully` - - if (isDLAuditorium(auditorium)) { - return successResponse([], message) - } - - const schedule = await this.repository.getSchedule(options) - - return successResponse(schedule, message) - } -} diff --git a/src/modules/auditoriums/types/index.ts b/src/modules/auditoriums/types/index.ts deleted file mode 100644 index 3b2ef3f..0000000 --- a/src/modules/auditoriums/types/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -import type { CistParser, CistProcessor } from '@/core/types/cist.js' -import type { BaseResponse, Maybe } from '@/core/types/common.js' -import type { BaseDiConfig, InjectableDependencies } from '@/core/types/deps.js' -import type { CistAuditoriumsOutput } from '@/core/types/proxy.js' -import type { Schedulable } from '@/core/types/services.js' -import type { - Auditorium, - Group, - Schedule, - Subject, - Teacher, -} from '@/db/types.js' -import type { GET_AUDITORIUM_SCHEDULE_FILTERS } from '../schemas/index.js' - -interface AuditoriumsRepository - extends Schedulable { - findOne: (id: number) => Promise> - findAll: () => Promise - getGroups: (auditoriumId: number) => Promise[]> - getTeachers: ( - auditoriumId: number, - ) => Promise[]> - getSubjects: (auditoriumId: number) => Promise -} - -interface AuditoriumsService - extends Schedulable< - GET_AUDITORIUM_SCHEDULE_FILTERS, - BaseResponse - > { - getAuditoriums: () => Promise> - getGroups: ( - auditoriumId: number, - ) => Promise[]>> - getTeachers: ( - auditoriumId: number, - ) => Promise[]>> - getSubjects: (auditoriumId: number) => Promise> -} - -interface AuditoriumsModuleDependencies { - auditoriumsParser: CistParser - auditoriumsProcessor: CistProcessor - auditoriumsRepository: AuditoriumsRepository - auditoriumsService: AuditoriumsService -} - -type AuditoriumsInjectableDependencies = - InjectableDependencies - -type AuditoriumsDiConfig = BaseDiConfig - -export type { - AuditoriumsDiConfig, - AuditoriumsInjectableDependencies, - AuditoriumsModuleDependencies, - AuditoriumsRepository, - AuditoriumsService, -} diff --git a/src/modules/auditoriums/utils/index.ts b/src/modules/auditoriums/utils/index.ts deleted file mode 100644 index 02109f7..0000000 --- a/src/modules/auditoriums/utils/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { Maybe } from '@/core/types/common.js' -import type { Auditorium } from '@/db/types.js' -import { sql, type SQL } from 'drizzle-orm' -import type { GET_AUDITORIUM_SCHEDULE_FILTERS } from '../schemas/index.js' - -export const getAuditoriumFiltersQuery = ( - filters: GET_AUDITORIUM_SCHEDULE_FILTERS, -): SQL[] => { - const clause: SQL[] = [] - const { lessonTypes, teachers, groups, subjects } = filters - - if (lessonTypes.length) { - clause.push(sql`and`, sql`e.type in (${sql.join(lessonTypes, sql`,`)})`) - } - - if (teachers.length) { - clause.push(sql`and`, sql`t2.id in (${sql.join(teachers, sql`,`)})`) - } - - if (groups.length) { - clause.push(sql`and`, sql`ag2.id in (${sql.join(groups, sql`,`)})`) - } - - if (subjects.length) { - clause.push(sql`and`, sql`s.id in (${sql.join(subjects, sql`,`)})`) - } - - return clause -} - -export const isDLAuditorium = (auditorium: Maybe): boolean => { - return auditorium?.name.startsWith('DL') ?? false -} diff --git a/src/modules/events/index.ts b/src/modules/events/index.ts deleted file mode 100644 index 8f1332b..0000000 --- a/src/modules/events/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { asClass } from 'awilix' -import type { EventsDiConfig } from './types/index.js' -import { EventsParserImpl } from './parsers/EventsParser.js' -import { EventsProcessorImpl } from './processors/EventsProcessor.js' - -export const resolveEventsModule = (): EventsDiConfig => ({ - eventsParser: asClass(EventsParserImpl).singleton(), - eventsProcessor: asClass(EventsProcessorImpl).singleton(), -}) diff --git a/src/modules/events/parsers/EventsParser.ts b/src/modules/events/parsers/EventsParser.ts deleted file mode 100644 index 835a3b0..0000000 --- a/src/modules/events/parsers/EventsParser.ts +++ /dev/null @@ -1,215 +0,0 @@ -import type { ScheduleType } from '@/core/constants/parsers.js' -import type { CommonDependencies, Maybe } from '@/core/types/index.js' -import type { - CistScheduleOutput, - CistScheduleRawJson, - RawSubject, - RawTeacher, - SubjectHour, -} from '@/core/types/proxy.js' -import { fetchProxy } from '@/core/utils/index.js' -import type { - Event, - EventType, - Group, - GroupData, - Subject, - TeacherData, -} from '@/db/types.js' -import type { EventsParser } from '../types/index.js' - -export class EventsParserImpl implements EventsParser { - private readonly endpoint: string - - constructor({ config }: CommonDependencies) { - const { baseUrl } = config.proxy - - this.endpoint = `${baseUrl}/schedule` - } - - async parse( - id: number, - type: ScheduleType, - ): Promise> { - try { - const raw = await fetchProxy( - `${this.endpoint}/${id}?type=${type}`, - ) - - if (Array.isArray(raw) && !raw.length) { - return null - } - - if (!Object.hasOwn(raw, 'events')) { - return null - } - - const events: Omit[] = [] - const subjects: Subject[] = [] - const hours = EventsParserImpl.getSubjectHours(raw.subjects) - - for (const e of raw.events) { - const pair = { - numberPair: e.number_pair ?? 0, - startTime: e.start_time ?? 0, - endTime: e.end_time ?? 0, - type: EventsParserImpl.getType(e.type), - auditorium: e.auditory, - teachers: [] as TeacherData[], - groups: [] as GroupData[], - subject: { - id: 0, - name: '', - brief: '', - }, - } satisfies Omit - - const subject = EventsParserImpl.findSubjectById( - raw.subjects, - e.subject_id, - ) - - if (!subject) { - continue - } - - pair.subject = subject - subjects.push(subject) - - if (!Object.hasOwn(e, 'groups')) { - continue - } - - for (const groupId of e.groups) { - const group = EventsParserImpl.findGroupById(raw.groups, groupId) - - if (!group) { - continue - } - - pair.groups.push(group) - } - - if (!Object.hasOwn(e, 'teachers')) { - continue - } - - for (const teacherId of e.teachers) { - const teacher = EventsParserImpl.findTeacherById( - raw.teachers, - teacherId, - ) - - if (!teacher) { - continue - } - - pair.teachers.push(teacher) - } - - events.push(pair) - } - - return { - events: events.toSorted((a, b) => a.startTime - b.startTime), - subjects, - hours, - } - } catch (e) { - const message = `${e instanceof Error ? e.message : 'Unknown error'}` - - throw new Error( - `[EventsParser] Failed to fetch or parse events data: ${message}`, - ) - } - } - - private static getType(id: number): EventType { - if (id === 10 || id === 12) { - return 'Пз' - } - - if (id >= 20 && id <= 24) { - return 'Лб' - } - - if (id === 30) { - return 'Конс' - } - - if (id >= 40 && id <= 41) { - return 'Зал' - } - - if (id >= 50 && id <= 55) { - return 'Екз' - } - - if (id === 60) { - return 'КП/КР' - } - - return 'Лк' - } - - private static findTeacherById( - teachers: RawTeacher[], - id: number, - ): Maybe { - const raw = teachers.find((t) => t.id === id) - - if (!raw) { - return null - } - - return { - id: raw.id, - fullName: raw.full_name, - shortName: raw.short_name, - } - } - - private static findGroupById(groups: Group[], id: number): Maybe { - const group = groups.find((g) => g.id === id) - - return group ?? null - } - - private static findSubjectById( - subjects: RawSubject[], - id: number, - ): Maybe { - const raw = subjects.find((s) => s.id === id) - - if (!raw) { - return null - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { hours, title, ...rest } = raw - - return { - ...rest, - name: title, - } - } - - private static getSubjectHours(subjects: RawSubject[]): SubjectHour[] { - const hours: SubjectHour[] = [] - - for (const subject of subjects) { - const mappedHours = subject.hours.map((h): SubjectHour => { - return { - hours: h.val, - type: EventsParserImpl.getType(h.type), - teacherId: h.teachers[0] ?? null, - subjectId: subject.id, - } - }) - - hours.push(...mappedHours) - } - - return hours - } -} diff --git a/src/modules/events/processors/EventsProcessor.ts b/src/modules/events/processors/EventsProcessor.ts deleted file mode 100644 index e05ba85..0000000 --- a/src/modules/events/processors/EventsProcessor.ts +++ /dev/null @@ -1,214 +0,0 @@ -import { RedisKeyBuilder } from '@/core/builders/RedisKeyBulder.js' -import type { ScheduleType } from '@/core/constants/parsers.js' -import type { DatabaseClient } from '@/core/types/deps.js' -import { - auditoriumTable, - eventTable, - eventToAcademicGroupTable, - eventToTeacherTable, - subjectTable, - subjectToTeacherTable, -} from '@/db/schema/index.js' -import { eq } from 'drizzle-orm' -import type { FastifyBaseLogger } from 'fastify' -import type { Redis } from 'ioredis' -import type { - EventsInjectableDependencies, - EventsParser, - EventsProcessor, -} from '../types/index.js' - -export class EventsProcessorImpl implements EventsProcessor { - private readonly db: DatabaseClient - private readonly cache: Redis - private readonly parser: EventsParser - private readonly logger: FastifyBaseLogger - - constructor({ - db, - cache, - eventsParser, - logger, - }: EventsInjectableDependencies) { - this.db = db.client - this.cache = cache - this.parser = eventsParser - this.logger = logger - } - - async process(id: number, type: ScheduleType): Promise { - try { - const data = await this.parser.parse(id, type) - - if (!data) { - this.logger.info( - `[Cist Postman]: No events parsed for group with id: ${id}`, - ) - return - } - - const { events, subjects, hours } = data - - for (const subject of subjects) { - const key = RedisKeyBuilder.subjectKey(subject.id) - - const isExist = await this.cache.get(key) - - if (isExist) { - this.logger.info('[Cist Postman]: Skipping subject duplicate') - continue - } - - await this.db.insert(subjectTable).values(subject) - await this.cache.set(key, 'exists') - } - - for (const event of events) { - const key = RedisKeyBuilder.eventKey(event) - - const isExist = await this.cache.exists(key) - - if (isExist) { - this.logger.info('[Cist Postman]: Skipping event duplicate') - - continue - } - - const { startTime, endTime, auditorium, type, numberPair } = event - - const e = await this.db.transaction(async (tx) => { - const [auditoriumId] = await tx - .select({ id: auditoriumTable.id }) - .from(auditoriumTable) - .where(eq(auditoriumTable.name, auditorium)) - - const [e] = await tx - .insert(eventTable) - .values({ - startedAt: startTime, - endedAt: endTime, - auditoriumId: auditoriumId?.id as number, - type, - numberPair, - subjectId: event.subject.id, - }) - .returning() - - for (const teacher of event.teachers) { - const isTeacherExist = await this.cache.get( - RedisKeyBuilder.teacherKey(teacher.id), - ) - - if (!isTeacherExist) { - this.logger.info( - `[Cist Postman]: Skipping event's teacher duplicate`, - ) - continue - } - - const teacherEventKey = RedisKeyBuilder.teacherEventKey( - teacher.id, - e?.id as number, - ) - - const isEventExist = await this.cache.get(teacherEventKey) - - if (!isEventExist) { - await tx.insert(eventToTeacherTable).values({ - eventId: e?.id as number, - teacherId: teacher.id, - }) - - await this.cache.set(teacherEventKey, 'exists') - } - - const teacherSubjectKey = RedisKeyBuilder.teacherSubjectKey( - teacher.id, - event.subject.id, - ) - - const isSubjectExist = await this.cache.get(teacherSubjectKey) - - if (!isSubjectExist) { - const hour = hours.find( - (h) => - h.subjectId === event.subject.id && - h.teacherId === teacher.id, - ) - - if (!hour) { - continue - } - - // @ts-expect-error will be fixed soon - await tx.insert(subjectToTeacherTable).values({ - ...hour, - }) - - await this.cache.set(teacherSubjectKey, 'exists') - } - } - - for (const group of event.groups) { - const eventGroupKey = RedisKeyBuilder.groupEventKey( - group.id, - e?.id as number, - ) - - const isExist = await this.cache.get(eventGroupKey) - - if (isExist) { - this.logger.info( - `[Cist Postman]: Skipping event's group duplicate`, - ) - continue - } - - await tx.insert(eventToAcademicGroupTable).values({ - eventId: e?.id as number, - groudId: group.id, - }) - - await this.cache.set(eventGroupKey, 'exists') - } - - return e! - }) - - await Promise.all([ - this.cache.set(key, e.id), - this.cache.sadd('new-events', key), - ]) - this.logger.info( - `[Cist Postman]: Events processing for group with id ${id} ended`, - ) - } - } catch (e: unknown) { - const message = `[EventsProcessor] Processing for group with id ${id} failed: ${e instanceof Error ? e.message : 'Unknown error'}` - - throw new Error(message) - } - } - - async removeExtraEvents(): Promise { - const eventsToRemove = await this.cache.sinter('old-events', 'new-events') - - for (const eventKey of eventsToRemove) { - const eventId = await this.cache.get(eventKey) - - await Promise.all([ - this.db.delete(eventTable).where(eq(eventTable.id, Number(eventId))), - this.cache.del(eventKey), - ]) - } - - const newEventsExists = await this.cache.exists('new-events') - - if (newEventsExists) { - await Promise.all([ - this.cache.del('old-events'), - this.cache.rename('new-events', 'old-events'), - ]) - } - } -} diff --git a/src/modules/events/types/index.ts b/src/modules/events/types/index.ts deleted file mode 100644 index 034ae60..0000000 --- a/src/modules/events/types/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { ScheduleType } from '@/core/constants/parsers.js' -import type { Maybe } from '@/core/types/common.js' -import type { BaseDiConfig, InjectableDependencies } from '@/core/types/deps.js' -import type { CistScheduleOutput } from '@/core/types/proxy.js' - -interface EventsParser { - parse: (id: number, type: ScheduleType) => Promise> -} - -interface EventsProcessor { - process: (id: number, type: ScheduleType) => Promise - removeExtraEvents: () => Promise -} - -interface EventModuleDependencies { - eventsParser: EventsParser - eventsProcessor: EventsProcessor -} - -type EventsInjectableDependencies = - InjectableDependencies -type EventsDiConfig = BaseDiConfig - -export type { - EventModuleDependencies, - EventsDiConfig, - EventsInjectableDependencies, - EventsParser, - EventsProcessor, -} diff --git a/src/modules/events/utils/index.ts b/src/modules/events/utils/index.ts deleted file mode 100644 index 52e3301..0000000 --- a/src/modules/events/utils/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const arrDifference = (arr1: T[], arr2: T[]): T[] => { - return arr1.filter((item) => !arr2.includes(item)) -} diff --git a/src/modules/groups/handlers/index.ts b/src/modules/groups/handlers/index.ts deleted file mode 100644 index 5dced03..0000000 --- a/src/modules/groups/handlers/index.ts +++ /dev/null @@ -1,69 +0,0 @@ -import type { GET_ENTITY_BY_ID } from '@/core/schemas/index.js' -import { - type GET_SCHEDULE_PARAMS, - type GET_SCHEDULE_QUERY, -} from '@/modules/schedule/schemas/index.js' -import type { FastifyReply, FastifyRequest } from 'fastify' -import type { GET_GROUP_SCHEDULE_FILTERS } from '../schemas/index.js' - -export const getGroups = async ( - request: FastifyRequest, - reply: FastifyReply, -): Promise => { - const { groupsService } = request.diScope.cradle - - const data = await groupsService.getAll() - - return reply.status(200).send(data) -} - -export const getGroupAuditoriums = async ( - request: FastifyRequest<{ Params: GET_ENTITY_BY_ID }>, - reply: FastifyReply, -): Promise => { - const { groupsService } = request.diScope.cradle - const { id } = request.params - - const data = await groupsService.getAuditoriums(id) - - return reply.status(200).send(data) -} - -export const getGroupSchedule = async ( - request: FastifyRequest<{ - Params: GET_SCHEDULE_PARAMS - Querystring: GET_SCHEDULE_QUERY - }>, - reply: FastifyReply, -): Promise => { - const { groupsService } = request.diScope.cradle - const { id } = request.params - - const data = await groupsService.getSchedule({ id, ...request.query }) - - return reply.status(200).send(data) -} - -export const getGroupSubjects = async ( - request: FastifyRequest<{ Params: GET_ENTITY_BY_ID }>, - reply: FastifyReply, -): Promise => { - const { groupsService } = request.diScope.cradle - const { id } = request.params - - const data = await groupsService.getSubjects(id) - - return reply.status(200).send(data) -} - -export const getGroupTeachers = async ( - request: FastifyRequest<{ Params: GET_ENTITY_BY_ID }>, - reply: FastifyReply, -): Promise => { - const { groupsService } = request.diScope.cradle - const { id } = request.params - - const data = await groupsService.getTeachers(id) - - return reply.status(200).send(data) -} diff --git a/src/modules/groups/index.ts b/src/modules/groups/index.ts deleted file mode 100644 index dbf0e11..0000000 --- a/src/modules/groups/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { asClass } from 'awilix' -import { GroupsParserImpl } from './parsers/GroupsParser.js' -import type { GroupsDiConfig } from './types/index.js' -import { GroupsProcessorImpl } from './processors/GroupsProcessor.js' -import { GroupsRepositoryImpl } from './repositories/GroupsRepository.js' -import { GroupsServiceImpl } from './services/GroupsService.js' - -export const resolveGroupsModule = (): GroupsDiConfig => ({ - groupsParser: asClass(GroupsParserImpl).singleton(), - groupsProcessor: asClass(GroupsProcessorImpl).singleton(), - groupsRepository: asClass(GroupsRepositoryImpl).singleton(), - groupsService: asClass(GroupsServiceImpl).singleton(), -}) diff --git a/src/modules/groups/parsers/GroupsParser.ts b/src/modules/groups/parsers/GroupsParser.ts deleted file mode 100644 index 79dac50..0000000 --- a/src/modules/groups/parsers/GroupsParser.ts +++ /dev/null @@ -1,119 +0,0 @@ -import type { CistParser } from '@/core/types/cist.js' -import type { CommonDependencies, Maybe } from '@/core/types/index.js' -import type { CistGroupsOutput, CistGroupsRawJson } from '@/core/types/proxy.js' -import { fetchProxy, hashObject } from '@/core/utils/index.js' -import type { Direction, Faculty, Group, Speciality } from '@/db/types.js' - -export class GroupsParserImpl implements CistParser { - private readonly endpoint: string - private hashSet: Set - private groups: Group[] - - constructor({ config }: CommonDependencies) { - const { baseUrl } = config.proxy - - this.endpoint = `${baseUrl}/lists/groups` - this.hashSet = new Set() - this.groups = [] - } - - async parse(): Promise> { - try { - const raw = await fetchProxy(this.endpoint) - - if (!Object.hasOwn(raw, 'university')) { - return null - } - - const faculties: Faculty[] = [] - const directions: Direction[] = [] - const specialities: Speciality[] = [] - - if (!Object.hasOwn(raw.university, 'faculties')) { - return null - } - - for (const faculty of raw.university.faculties) { - faculties.push({ - id: faculty.id, - fullName: faculty.short_name, - shortName: faculty.full_name, - }) - - if (!Object.hasOwn(faculty, 'directions')) { - continue - } - - for (const direction of faculty.directions) { - directions.push({ - id: direction.id, - fullName: direction.short_name, - shortName: direction.full_name, - facultyId: faculty.id, - }) - - if (!Object.hasOwn(direction, 'specialities')) { - continue - } - - for (const speciality of direction.specialities) { - specialities.push({ - id: speciality.id, - fullName: speciality.full_name, - shortName: speciality.short_name, - directionId: direction.id, - }) - - if (!Object.hasOwn(speciality, 'groups')) { - continue - } - - for (const group of speciality.groups) { - this.addGroup({ - ...group, - specialityId: speciality.id, - directionId: null, - }) - } - } - - if (!Object.hasOwn(direction, 'groups')) { - continue - } - - for (const group of direction.groups) { - this.addGroup({ - ...group, - directionId: direction.id, - specialityId: null, - }) - } - } - } - - return { groups: this.groups, faculties, specialities, directions } - } catch (e) { - const message = e instanceof Error ? e.message : String(e) - - throw new Error( - `[GroupsParser] Failed to fetch or parse groups data: ${message}`, - ) - } - } - - private addGroup(group: Group): void { - if (!group.name?.length) { - return - } - - const hash = hashObject(group) - - if (this.hashSet.has(hash)) { - return - } - - this.groups.push(group) - - this.hashSet.add(hash) - } -} diff --git a/src/modules/groups/processors/GroupsProcessor.ts b/src/modules/groups/processors/GroupsProcessor.ts deleted file mode 100644 index 38ebe8c..0000000 --- a/src/modules/groups/processors/GroupsProcessor.ts +++ /dev/null @@ -1,99 +0,0 @@ -import type { CistParser, CistProcessor } from '@/core/types/cist.js' -import type { DatabaseClient } from '@/core/types/deps.js' -import type { CistGroupsOutput } from '@/core/types/proxy.js' -import type { Group } from '@/db/types.js' -import type { Redis } from 'ioredis' -import type { GroupsInjectableDependencies } from '../types/index.js' -import { RedisKeyBuilder } from '@/core/builders/RedisKeyBulder.js' -import { - academicGroupTable, - directionTable, - facultyTable, - specialityTable, -} from '@/db/schema/index.js' - -export class GroupsProcessorImpl implements CistProcessor { - private readonly db: DatabaseClient - private readonly cache: Redis - private readonly parser: CistParser - - constructor({ db, cache, groupsParser }: GroupsInjectableDependencies) { - this.db = db.client - this.cache = cache - this.parser = groupsParser - } - - async process(): Promise { - try { - const data = await this.parser.parse() - - if (!data) { - return [] - } - - const { groups, faculties, specialities, directions } = data - - for (const faculty of faculties) { - const key = RedisKeyBuilder.facultyKey(faculty.id) - - const isExist = await this.cache.get(key) - - if (isExist) { - continue - } - - await this.db.insert(facultyTable).values(faculty).onConflictDoNothing() - this.cache.set(key, 'exists') - } - - for (const direction of directions) { - const key = RedisKeyBuilder.directionKey(direction.id) - - const isExist = await this.cache.get(key) - - if (isExist) { - continue - } - - await this.db.insert(directionTable).values(direction) - this.cache.set(key, 'exists') - } - - for (const speciality of specialities) { - const key = RedisKeyBuilder.specialityKey(speciality.id) - - const isExist = await this.cache.get(key) - - if (isExist) { - continue - } - - await this.db.insert(specialityTable).values(speciality) - await this.cache.set(key, 'exists') - } - - for (const group of groups) { - const key = RedisKeyBuilder.groupKey(group.id) - - const isExist = await this.cache.get(key) - - if (isExist) { - continue - } - - await this.db.insert(academicGroupTable).values(group) - await this.cache.set(key, 'exists') - } - - return groups - } catch (e: unknown) { - if (e instanceof Error && e.message.includes('[GroupsParser]')) { - throw new Error(e.message) - } - - const message = `[GroupsProcessor] Failed to process data: ${e instanceof Error ? e.message : 'Unknown error'}` - - throw new Error(message) - } - } -} diff --git a/src/modules/groups/repositories/GroupsRepository.ts b/src/modules/groups/repositories/GroupsRepository.ts deleted file mode 100644 index ca13c25..0000000 --- a/src/modules/groups/repositories/GroupsRepository.ts +++ /dev/null @@ -1,126 +0,0 @@ -import type { DatabaseClient } from '@/core/types/deps.js' -import { academicGroupTable } from '@/db/schema/academic-group.js' -import { auditoriumTable } from '@/db/schema/auditorium.js' -import { eventToAcademicGroupTable } from '@/db/schema/event-to-academic-group.js' -import { eventToTeacherTable } from '@/db/schema/event-to-teacher.js' -import { eventTable } from '@/db/schema/event.js' -import { subjectTable } from '@/db/schema/subject.js' -import { teacherTable } from '@/db/schema/teacher.js' -import type { - Auditorium, - Group, - Schedule, - Subject, - Teacher, -} from '@/db/types.js' -import type { GET_SCHEDULE_OPTIONS } from '@/modules/schedule/schemas/index.js' -import { - buildScheduleQuery, - getTimeIntervalQuery, -} from '@/modules/schedule/utils/index.js' -import { SQL, asc, eq, sql } from 'drizzle-orm' -import type { GET_GROUP_SCHEDULE_FILTERS } from '../schemas/index.js' -import type { - GroupsInjectableDependencies, - GroupsRepository, -} from '../types/index.js' -import { getGroupFiltersQuery } from '../utils/index.js' - -export class GroupsRepositoryImpl implements GroupsRepository { - private readonly db: DatabaseClient - - constructor({ db }: GroupsInjectableDependencies) { - this.db = db.client - } - - async findAll(): Promise { - return this.db - .select() - .from(academicGroupTable) - .orderBy(asc(academicGroupTable.name)) - } - - async getAuditoriums( - groupId: number, - ): Promise[]> { - return this.db - .selectDistinct({ - id: auditoriumTable.id, - name: auditoriumTable.name, - }) - .from(eventTable) - .innerJoin( - eventToAcademicGroupTable, - eq(eventTable.id, eventToAcademicGroupTable.eventId), - ) - .innerJoin( - auditoriumTable, - eq(eventTable.auditoriumId, auditoriumTable.id), - ) - .where(eq(eventToAcademicGroupTable.groudId, groupId)) - .orderBy(auditoriumTable.name) - } - - async getSubjects(groupId: number): Promise { - return this.db - .selectDistinct({ - id: subjectTable.id, - name: subjectTable.name, - brief: subjectTable.brief, - }) - .from(eventTable) - .innerJoin( - eventToAcademicGroupTable, - eq(eventTable.id, eventToAcademicGroupTable.eventId), - ) - .innerJoin(subjectTable, eq(eventTable.subjectId, subjectTable.id)) - .where(eq(eventToAcademicGroupTable.groudId, groupId)) - .orderBy(subjectTable.brief) - } - - async getTeachers(groupId: number): Promise[]> { - return this.db - .selectDistinct({ - id: teacherTable.id, - shortName: teacherTable.shortName, - fullName: teacherTable.fullName, - }) - .from(eventTable) - .innerJoin( - eventToAcademicGroupTable, - eq(eventTable.id, eventToAcademicGroupTable.eventId), - ) - .innerJoin( - eventToTeacherTable, - eq(eventTable.id, eventToTeacherTable.eventId), - ) - .innerJoin( - teacherTable, - eq(eventToTeacherTable.teacherId, teacherTable.id), - ) - .where(eq(eventToAcademicGroupTable.groudId, groupId)) - .orderBy(teacherTable.shortName) - } - - async getSchedule( - options: GET_SCHEDULE_OPTIONS, - ): Promise { - const { id } = options - - const whereClause: SQL[] = [sql`ag1.id = ${id}`] - - const timeInterval = getTimeIntervalQuery(options) - - whereClause.push(...timeInterval) - - const filters = getGroupFiltersQuery(options.filters) - - whereClause.push(...filters) - - const query = buildScheduleQuery(whereClause) - - const schedule = await this.db.execute(query) - - return schedule as unknown as Schedule[] - } -} diff --git a/src/modules/groups/routes/index.ts b/src/modules/groups/routes/index.ts deleted file mode 100644 index 9e0dbfb..0000000 --- a/src/modules/groups/routes/index.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { GET_ENTITY_BY_ID_SCHEMA } from '@/core/schemas/index.js' -import type { Routes } from '@/core/types/routes.js' -import { generateSuccessResponseSchema } from '@/core/utils/schemas.js' -import { - GET_SCHEDULE_PARAMS_SCHEMA, - SCHEDULE_SCHEMA, -} from '@/modules/schedule/schemas/index.js' -import { getScheduleQuerySchema } from '@/modules/schedule/utils/index.js' -import { TEACHER_SCHEMA } from '@/modules/teachers/schemas/index.js' -import { - getGroupAuditoriums, - getGroupSchedule, - getGroupSubjects, - getGroupTeachers, - getGroups, -} from '../handlers/index.js' -import { - GET_GROUP_SCHEDULE_FILTERS_SCHEMA, - GROUP_SCHEMA, - SUBJECT_SCHEMA, -} from '../schemas/index.js' -import { AUDITORIUM_SCHEMA } from '@/modules/auditoriums/schemas/index.js' - -export const getGroupsRoutes = (): Routes => ({ - routes: [ - { - method: 'GET', - url: '/groups', - handler: getGroups, - schema: { - summary: 'Get groups', - description: 'Get list of groups', - tags: ['Groups'], - response: { - 200: generateSuccessResponseSchema(GROUP_SCHEMA.array()).describe( - 'Successful response', - ), - }, - }, - }, - { - method: 'GET', - url: '/groups/:id/auditoriums', - handler: getGroupAuditoriums, - schema: { - summary: 'Get group auditoriums', - description: - 'Get list of auditoriums for an appropriate group that are used during this academic year', - tags: ['Groups'], - params: GET_ENTITY_BY_ID_SCHEMA, - response: { - 200: generateSuccessResponseSchema( - AUDITORIUM_SCHEMA.pick({ id: true, name: true }).array(), - ).describe('Successful response'), - }, - }, - }, - { - method: 'GET', - url: '/groups/:id/teachers', - handler: getGroupTeachers, - schema: { - summary: 'Get group teachers', - description: `Get list of teachers for an appropeiate group that teach during this academic year`, - tags: ['Groups'], - params: GET_ENTITY_BY_ID_SCHEMA, - response: { - 200: generateSuccessResponseSchema( - TEACHER_SCHEMA.omit({ departmentId: true }).array(), - ).describe('Successful response'), - }, - }, - }, - { - method: 'GET', - url: '/groups/:id/subjects', - handler: getGroupSubjects, - schema: { - summary: 'Get group subjects', - description: - 'Get list of subjects for an appropriate group that are thought this academic year', - tags: ['Groups'], - params: GET_ENTITY_BY_ID_SCHEMA, - response: { - 200: generateSuccessResponseSchema(SUBJECT_SCHEMA.array()).describe( - 'Successful response', - ), - }, - }, - }, - { - method: 'GET', - url: '/groups/:id/schedule', - handler: getGroupSchedule, - schema: { - summary: 'Get group schedule', - description: 'Get schedule for a group in particular time interval', - tags: ['Groups'], - params: GET_SCHEDULE_PARAMS_SCHEMA, - querystring: getScheduleQuerySchema(GET_GROUP_SCHEDULE_FILTERS_SCHEMA), - response: { - 200: generateSuccessResponseSchema(SCHEDULE_SCHEMA.array()).describe( - 'Successful response', - ), - }, - }, - }, - ], -}) diff --git a/src/modules/groups/schemas/index.ts b/src/modules/groups/schemas/index.ts deleted file mode 100644 index c3fc6a3..0000000 --- a/src/modules/groups/schemas/index.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { - transformEventTypesParam, - transformIdsParam, -} from '@/modules/schedule/utils/query-string.js' -import { z } from 'zod' - -const GROUP_SCHEMA = z.object({ - id: z.number().int().describe('Group identifier'), - name: z.string().describe('Name of group'), - directionId: z - .number() - .int() - .nullable() - .describe('Identifer of direction group belongs to'), - specialityId: z - .number() - .int() - .nullable() - .describe('Identifier of speciality group belongs to'), -}) - -const SUBJECT_SCHEMA = z.object({ - id: z.number().int().describe('Subject identifier'), - brief: z.string().describe('Subject brief name'), - name: z.string().describe('Subject name'), -}) - -const GET_GROUP_SCHEDULE_FILTERS_SCHEMA = z - .object({ - lessonTypes: z - .string() - .nullable() - .default(null) - .transform(transformEventTypesParam) - .describe( - 'Comma-separated list of lesson types to filter by. Example: "Лк,Пз"', - ), - teachers: z - .string() - .nullable() - .default(null) - .transform(transformIdsParam) - .describe( - 'Comma-separated list of teacher IDs to filter by. Example: "1,2,3"', - ), - auditoriums: z - .string() - .nullable() - .default(null) - .transform(transformIdsParam) - .describe( - 'Comma-separated list of auditorium IDs to filter by. Example: "1,2,3"', - ), - subjects: z - .string() - .nullable() - .default(null) - .transform(transformIdsParam) - .describe( - 'Comma-separated list of subject IDs to filter by. Example: "1,2,3"', - ), - }) - .default({ - lessonTypes: [], - teachers: [], - auditoriums: [], - subjects: [], - }) - -type GET_GROUP_SCHEDULE_FILTERS = z.infer< - typeof GET_GROUP_SCHEDULE_FILTERS_SCHEMA -> - -export { GROUP_SCHEMA, SUBJECT_SCHEMA, GET_GROUP_SCHEDULE_FILTERS_SCHEMA } -export type { GET_GROUP_SCHEDULE_FILTERS } diff --git a/src/modules/groups/services/GroupsService.ts b/src/modules/groups/services/GroupsService.ts deleted file mode 100644 index 8aad157..0000000 --- a/src/modules/groups/services/GroupsService.ts +++ /dev/null @@ -1,71 +0,0 @@ -import type { BaseResponse } from '@/core/types/common.js' -import type { - GroupsInjectableDependencies, - GroupsRepository, - GroupsService, -} from '../types/index.js' -import type { - Auditorium, - Group, - Schedule, - Subject, - Teacher, -} from '@/db/types.js' -import type { GET_SCHEDULE_OPTIONS } from '@/modules/schedule/schemas/index.js' -import { successResponse } from '@/core/utils/index.js' -import type { GET_GROUP_SCHEDULE_FILTERS } from '../schemas/index.js' - -export class GroupsServiceImpl implements GroupsService { - private readonly repository: GroupsRepository - - constructor({ groupsRepository }: GroupsInjectableDependencies) { - this.repository = groupsRepository - } - - async getAll(): Promise> { - const groups = await this.repository.findAll() - - return successResponse(groups, 'Groups fetched successfully') - } - - async getAuditoriums( - groupId: number, - ): Promise[]>> { - const auditoriums = await this.repository.getAuditoriums(groupId) - - return successResponse( - auditoriums, - `Auditoriums for group ${groupId} fetched successfully`, - ) - } - - async getSubjects(groupId: number): Promise> { - const subjects = await this.repository.getSubjects(groupId) - - return successResponse( - subjects, - `Subjects for group ${groupId} fetched successfully`, - ) - } - - async getTeachers( - groupId: number, - ): Promise[]>> { - const teachers = await this.repository.getTeachers(groupId) - - return successResponse( - teachers, - `Teachers for group ${groupId} fetched successfully`, - ) - } - - async getSchedule( - options: GET_SCHEDULE_OPTIONS, - ): Promise> { - const schedule = await this.repository.getSchedule(options) - - const message = `Schedule for group with id ${options.id} found successfully` - - return successResponse(schedule, message) - } -} diff --git a/src/modules/groups/types/index.ts b/src/modules/groups/types/index.ts deleted file mode 100644 index d94c297..0000000 --- a/src/modules/groups/types/index.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type { CistParser, CistProcessor } from '@/core/types/cist.js' -import type { BaseResponse } from '@/core/types/common.js' -import type { BaseDiConfig, InjectableDependencies } from '@/core/types/deps.js' -import type { CistGroupsOutput } from '@/core/types/proxy.js' -import type { Schedulable } from '@/core/types/services.js' -import type { - Auditorium, - Group, - Schedule, - Subject, - Teacher, -} from '@/db/types.js' -import type { GET_GROUP_SCHEDULE_FILTERS } from '../schemas/index.js' - -interface GroupsRepository extends Schedulable { - findAll: () => Promise - getAuditoriums: ( - groupId: number, - ) => Promise[]> - getSubjects: (groupId: number) => Promise - getTeachers: (groupId: number) => Promise[]> -} - -interface GroupsService - extends Schedulable> { - getAll: () => Promise> - getAuditoriums: ( - groupId: number, - ) => Promise[]>> - getSubjects: (groupId: number) => Promise> - getTeachers: ( - groupId: number, - ) => Promise[]>> -} - -interface GroupsModuleDependencies { - groupsParser: CistParser - groupsProcessor: CistProcessor - groupsRepository: GroupsRepository - groupsService: GroupsService -} - -type GroupsInjectableDependencies = - InjectableDependencies -type GroupsDiConfig = BaseDiConfig - -export type { - GroupsDiConfig, - GroupsInjectableDependencies, - GroupsModuleDependencies, - GroupsRepository, - GroupsService, -} diff --git a/src/modules/groups/utils/index.ts b/src/modules/groups/utils/index.ts deleted file mode 100644 index 4c9b6fb..0000000 --- a/src/modules/groups/utils/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { sql, type SQL } from 'drizzle-orm' -import type { GET_GROUP_SCHEDULE_FILTERS } from '../schemas/index.js' - -export const getGroupFiltersQuery = ( - filters: GET_GROUP_SCHEDULE_FILTERS, -): SQL[] => { - const clause: SQL[] = [] - const { auditoriums, lessonTypes, teachers, subjects } = filters - - if (auditoriums.length) { - clause.push(sql`and`, sql`a.id in (${sql.join(auditoriums, sql`,`)})`) - } - - if (lessonTypes.length) { - clause.push(sql`and`, sql`e.type in (${sql.join(lessonTypes, sql`,`)})`) - } - - if (teachers.length) { - clause.push(sql`and`, sql`t2.id in (${sql.join(teachers, sql`,`)})`) - } - - if (subjects.length) { - clause.push(sql`and`, sql`s.id in (${sql.join(subjects, sql`,`)})`) - } - - return clause -} diff --git a/src/modules/index.ts b/src/modules/index.ts deleted file mode 100644 index 63b0189..0000000 --- a/src/modules/index.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { - HEALTH_CHECK_KEY, - HEALTH_STATUS, - LAST_UPDATE_KEY, -} from '@/core/constants/index.js' -import type { Routes } from '@/core/types/routes.js' -import { getAuditoriumsRoutes } from './auditoriums/routes/index.js' -import { getGroupsRoutes } from './groups/routes/index.js' -import { getLinksRoutes } from './links/routes/index.js' -import { getTeachersRoutes } from './teachers/routes/index.js' -import { getMoodleRoutes } from './moodle/routes/index.js' - -export const getRoutes = (): Routes => ({ - routes: [ - { - method: 'GET', - url: '/health', - handler: async (request, reply) => { - const { cache } = request.diScope.cradle - - const health = await cache.get(HEALTH_CHECK_KEY) - const lastUpdated = await cache.get(LAST_UPDATE_KEY) - - const data = { - uptime: process.uptime(), - } - - if (!health || !lastUpdated) { - if (!health) { - await cache.set(HEALTH_CHECK_KEY, HEALTH_STATUS.HEALTHY) - } - - if (!lastUpdated) { - await cache.set(LAST_UPDATE_KEY, new Date().toISOString()) - } - - return reply.status(200).send({ - ...data, - message: health ? health : HEALTH_STATUS.HEALTHY, - lastUpdated: lastUpdated ? new Date(lastUpdated) : new Date(), - }) - } - - return reply.status(200).send({ - ...data, - message: health, - lastUpdated: new Date(lastUpdated), - }) - }, - schema: { - tags: ['System Check'], - summary: 'Get system status', - // response: { - // 200: HEALTH_CHECK_SCHEMA, - // }, - }, - }, - ...getAuditoriumsRoutes().routes, - ...getGroupsRoutes().routes, - ...getTeachersRoutes().routes, - ...getLinksRoutes().routes, - ...getMoodleRoutes().routes, - ], -}) diff --git a/src/modules/links/constants/index.ts b/src/modules/links/constants/index.ts deleted file mode 100644 index fb5eb97..0000000 --- a/src/modules/links/constants/index.ts +++ /dev/null @@ -1 +0,0 @@ -export const CLIENT_COOKIE_NAME = 'schedule-client-id' as const diff --git a/src/modules/links/handlers/index.ts b/src/modules/links/handlers/index.ts deleted file mode 100644 index 558aade..0000000 --- a/src/modules/links/handlers/index.ts +++ /dev/null @@ -1,114 +0,0 @@ -import type { FastifyReply, FastifyRequest } from 'fastify' -import { CLIENT_COOKIE_NAME } from '../constants/index.js' -import type { - CREATE_LINK, - GET_LINK_BY_ID, - UPDATE_LINK, -} from '../schemas/index.js' - -export const getUserLinks = async ( - request: FastifyRequest, - reply: FastifyReply, -): Promise => { - const userId = request.cookies[CLIENT_COOKIE_NAME] as string - - const { linksService } = request.diScope.cradle - - const data = await linksService.getUserLinks(userId) - - return reply.status(200).send(data) -} - -export const createLink = async ( - request: FastifyRequest<{ Body: CREATE_LINK }>, - reply: FastifyReply, -): Promise => { - const userId = request.cookies[CLIENT_COOKIE_NAME] as string - - const { linksService } = request.diScope.cradle - - const data = await linksService.createOne(userId, request.body) - - return reply.status(201).send(data) -} - -export const updateLink = async ( - request: FastifyRequest<{ Params: GET_LINK_BY_ID; Body: UPDATE_LINK }>, - reply: FastifyReply, -): Promise => { - const userId = request.cookies[CLIENT_COOKIE_NAME] as string - - const { id } = request.params - const { linksService } = request.diScope.cradle - - const result = await linksService.updateOne(id, userId, request.body) - - if (result.isErr()) { - return reply.status(result.error.error.status).send(result.error) - } - - return reply.status(200).send(result.value) -} - -export const deleteLink = async ( - request: FastifyRequest<{ Params: GET_LINK_BY_ID }>, - reply: FastifyReply, -): Promise => { - const userId = request.cookies[CLIENT_COOKIE_NAME] as string - - const { id } = request.params - const { linksService } = request.diScope.cradle - - const result = await linksService.deleteOne(id, userId) - - if (result.isErr()) { - return reply.status(result.error.error.status).send(result.error) - } - - return reply.status(200).send(result.value) -} - -export const getSharableLink = async ( - request: FastifyRequest<{ Params: GET_LINK_BY_ID }>, - reply: FastifyReply, -): Promise => { - const { id } = request.params - const { sharableLinksService } = request.diScope.cradle - - const result = await sharableLinksService.findOne(id) - - if (result.isErr()) { - return reply.status(result.error.error.status).send(result.error) - } - - return reply.status(200).send(result.value) -} - -export const createSharableLink = async ( - request: FastifyRequest<{ Body: string[] }>, - reply: FastifyReply, -): Promise => { - const userId = request.cookies[CLIENT_COOKIE_NAME] as string - const { sharableLinksService } = request.diScope.cradle - - const data = await sharableLinksService.createOne(userId, request.body) - - return reply.status(201).send(data) -} - -export const acceptSharableLink = async ( - request: FastifyRequest<{ Params: GET_LINK_BY_ID }>, - reply: FastifyReply, -): Promise => { - const userId = request.cookies[CLIENT_COOKIE_NAME] as string - const { id } = request.params - const { sharableLinksService } = request.diScope.cradle - - const result = await sharableLinksService.acceptOne(id, userId) - - if (result.isErr()) { - return reply.status(result.error.error.status).send(result.error) - } - - return reply.status(204).send() -} diff --git a/src/modules/links/index.ts b/src/modules/links/index.ts deleted file mode 100644 index ca09754..0000000 --- a/src/modules/links/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { asClass } from 'awilix' -import type { LinksDiConfig } from './types/index.js' -import { LinksRepositoryImpl } from './repositories/LinksRepository.js' -import { SharableLinksServiceImpl } from './services/SharableLinksService.js' -import { SharableLinkRepositoryImpl } from './repositories/SharableLinksRepository.js' - -export const resolveLinksModule = (): LinksDiConfig => ({ - linksRepository: asClass(LinksRepositoryImpl).singleton(), - linksService: asClass(LinksRepositoryImpl).singleton(), - sharableLinksRepository: asClass(SharableLinkRepositoryImpl).singleton(), - sharableLinksService: asClass(SharableLinksServiceImpl).singleton(), -}) diff --git a/src/modules/links/middlewares/session.ts b/src/modules/links/middlewares/session.ts deleted file mode 100644 index 482e5c5..0000000 --- a/src/modules/links/middlewares/session.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { failureResponse } from '@/core/utils/index.js' -import type { FastifyReply } from 'fastify' -import type { FastifyRequest } from 'fastify/types/request.js' -import { CLIENT_COOKIE_NAME } from '../constants/index.js' - -export const sessionMiddleware = async ( - request: FastifyRequest, - reply: FastifyReply, -): Promise => { - const userId = request.cookies[CLIENT_COOKIE_NAME] - - if (!userId) { - return reply - .status(401) - .send(failureResponse({ status: 401, message: 'Unauthorized' })) - } -} diff --git a/src/modules/links/repositories/LinksRepository.ts b/src/modules/links/repositories/LinksRepository.ts deleted file mode 100644 index bee72ec..0000000 --- a/src/modules/links/repositories/LinksRepository.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { randomUUID } from 'node:crypto' -import { - LINK_SCHEMA, - type CREATE_LINK, - type Link, - type UPDATE_LINK, -} from '../schemas/index.js' -import type { - LinksInjectableDependencies, - LinksRepository, -} from '../types/index.js' -import { Redis } from 'ioredis' -import type { Maybe } from '@/core/types/common.js' -import { scanKeys } from '@/core/utils/redis.js' - -export class LinksRepositoryImpl implements LinksRepository { - private readonly cache: Redis - - constructor({ cache }: LinksInjectableDependencies) { - this.cache = cache - } - - async findOne(id: string, userId: string): Promise> { - const key = LinksRepositoryImpl.getKey(userId, id) - - const [label, url, type, subjectId] = await this.cache.hmget( - key, - 'label', - 'url', - 'type', - 'subjectId', - ) - - const link = { - label, - url, - type, - subjectId: Number(subjectId), - id, - userId, - } - - const { success, data } = LINK_SCHEMA.safeParse(link) - - if (!success) { - return null - } - - return data - } - - async findMany(pattern: string): Promise { - const links: Link[] = [] - const keys = await scanKeys(this.cache, pattern) - - const pipeline = this.cache.pipeline() - - for (const key of keys) { - pipeline.hmget(key, 'id', 'label', 'url', 'type', 'subjectId', 'userId') - } - - const results = await pipeline.exec() - - if (!results) { - return [] - } - - for (const result of results) { - const [error, values] = result - - if (error) { - continue - } - - const [id, label, url, type, subjectId, userId] = values as string[] - - const link = { - id, - label, - url, - type, - subjectId: Number(subjectId), - userId, - } - - const { success, data } = LINK_SCHEMA.safeParse(link) - - if (!success) { - continue - } - - links.push(data) - } - - return links - } - - async createOne(userId: string, data: CREATE_LINK): Promise { - const id = randomUUID() - const key = LinksRepositoryImpl.getKey(userId, id) - - const link = { - id, - userId, - ...data, - } satisfies Link - - await this.cache.hmset(key, link) - - return link - } - - async updateOne( - id: string, - userId: string, - data: UPDATE_LINK, - ): Promise { - const key = LinksRepositoryImpl.getKey(userId, id) - - await this.cache.hmset(key, data) - } - - async deleteOne(id: string, userId: string): Promise { - const key = LinksRepositoryImpl.getKey(userId, id) - - await this.cache.del(key) - } - - private static getKey(userId: string, id: string): string { - return `${userId}:links:${id}` - } -} diff --git a/src/modules/links/repositories/SharableLinksRepository.ts b/src/modules/links/repositories/SharableLinksRepository.ts deleted file mode 100644 index ac095ae..0000000 --- a/src/modules/links/repositories/SharableLinksRepository.ts +++ /dev/null @@ -1,133 +0,0 @@ -import type { Redis } from 'ioredis' -import type { - LinksInjectableDependencies, - SharableLinksRepository, -} from '../types/index.js' -import { randomUUID } from 'node:crypto' -import { HOUR } from '@/core/constants/time.js' -import type { Maybe } from '@/core/types/common.js' -import { LINK_SCHEMA, type Link, type SharableLink } from '../schemas/index.js' - -export class SharableLinkRepositoryImpl implements SharableLinksRepository { - private readonly cache: Redis - - constructor({ cache }: LinksInjectableDependencies) { - this.cache = cache - } - - async findOne(id: string): Promise> { - const key = SharableLinkRepositoryImpl.getKey(id) - const links: Link[] = [] - - const rawLinks = await this.cache.lrange(key, 0, -1) - - if (rawLinks.length === 0) { - return null - } - - for (const key of rawLinks) { - const [label, url, type, subjectId, id, userId] = await this.cache.hmget( - key, - 'label', - 'url', - 'type', - 'subjectId', - 'id', - 'userId', - ) - - const link = { - label, - url, - type, - subjectId: Number(subjectId), - id, - userId, - } - - const { success, data } = LINK_SCHEMA.safeParse(link) - - if (!success) { - continue - } - - links.push(data) - } - - const sharableLink = { - id, - links, - } satisfies SharableLink - - return sharableLink - } - - async createOne(userId: string, links: string[]) { - const id = randomUUID() - const sharableKey = SharableLinkRepositoryImpl.getKey(id) - - for (const link of links) { - const linkKey = `${userId}:links:${link}` - - const linkExists = await this.cache.exists(linkKey) - - if (!linkExists) { - continue - } - - await this.cache.lpush(sharableKey, linkKey) - } - - this.cache.expire(sharableKey, 10 * HOUR) - - return id - } - - async acceptOne(id: string, userId: string): Promise { - const key = SharableLinkRepositoryImpl.getKey(id) - - const rawLinks = await this.cache.lrange(key, 0, -1) - - for (const linkKey of rawLinks) { - const [label, url, type, subjectId] = await this.cache.hmget( - linkKey, - 'label', - 'url', - 'type', - 'subjectId', - ) - - const linkId = randomUUID() - const newLinkKey = `${userId}:links:${linkId}` - - const link = { - id: linkId, - label, - url, - type, - subjectId: Number(subjectId), - userId, - } - - await this.cache.hmset(newLinkKey, link) - } - } - - async isAccepted(id: string, userId: string): Promise { - const exists = await this.cache.exists(`${userId}:sharable-links:${id}`) - - return !!exists - } - - async setAccepted(id: string, userId: string): Promise { - await this.cache.setex( - `${userId}:sharable-links:${id}`, - 'accepted', - 10 * HOUR, - ) - } - - private static getKey(id: string): string { - return `sharable-links:${id}` - } -} diff --git a/src/modules/links/routes/index.ts b/src/modules/links/routes/index.ts deleted file mode 100644 index 7e3c2d2..0000000 --- a/src/modules/links/routes/index.ts +++ /dev/null @@ -1,178 +0,0 @@ -import type { Routes } from '@/core/types/routes.js' -import { - generateFailureResponseSchema, - generateSuccessResponseSchema, -} from '@/core/utils/schemas.js' -import { - acceptSharableLink, - createLink, - createSharableLink, - deleteLink, - getSharableLink, - getUserLinks, - updateLink, -} from '../handlers/index.js' -import { sessionMiddleware } from '../middlewares/session.js' -import { - CREATE_LINK_SCHEMA, - CREATE_SHARABLE_LINK_SCHEMA, - GET_LINK_BY_ID_SCHEMA, - LINK_SCHEMA, - SHARABLE_LINK_SCHEMA, - UPDATE_LINK_SCHEMA, -} from '../schemas/index.js' -import { z } from 'zod' - -export const getLinksRoutes = (): Routes => ({ - routes: [ - { - method: 'GET', - url: '/links', - handler: getUserLinks, - preHandler: [sessionMiddleware], - schema: { - message: 'Get user links', - summary: 'Retrieve all links for the user', - tags: ['Links'], - security: [{ CookieAuth: [] }], - response: { - 200: generateSuccessResponseSchema(LINK_SCHEMA.array()).describe( - 'List of user links', - ), - 401: generateFailureResponseSchema(401).describe( - 'Unauthorized, session cookie is missing', - ), - }, - }, - }, - { - method: 'GET', - url: '/sharable-links/:id', - handler: getSharableLink, - schema: { - summary: 'Get sharable link', - description: 'Retrieve a sharable link by its ID', - tags: ['Sharable Links'], - params: GET_LINK_BY_ID_SCHEMA, - response: { - 200: generateSuccessResponseSchema(SHARABLE_LINK_SCHEMA).describe( - 'Sharable link details', - ), - 404: generateFailureResponseSchema(404).describe( - 'Sharable link not found', - ), - }, - }, - }, - { - method: 'POST', - url: '/links', - handler: createLink, - preHandler: [sessionMiddleware], - schema: { - summary: 'Create a new link', - description: 'Create a new link for a particular subject', - tags: ['Links'], - body: CREATE_LINK_SCHEMA, - security: [{ CookieAuth: [] }], - response: { - 201: generateSuccessResponseSchema(LINK_SCHEMA).describe( - 'Link successfully created', - ), - 401: generateFailureResponseSchema(401).describe( - 'Unauthorized, session cookie is missing', - ), - }, - }, - }, - { - method: 'POST', - url: '/sharable-links', - handler: createSharableLink, - preHandler: [sessionMiddleware], - schema: { - summary: 'Create a sharable link', - description: 'Create a sharable link with multiple links', - tags: ['Sharable Links'], - body: CREATE_SHARABLE_LINK_SCHEMA, - security: [{ CookieAuth: [] }], - response: { - 201: generateSuccessResponseSchema( - z.object({ - id: z.uuid(), - }), - ).describe('Sharable link successfully created'), - 401: generateFailureResponseSchema(401).describe( - 'Unauthorized, session cookie is missing', - ), - }, - }, - }, - { - method: 'PUT', - url: '/links/:id', - handler: updateLink, - preHandler: [sessionMiddleware], - schema: { - summary: 'Update an existing link', - description: 'Update the details of an existing link', - tags: ['Links'], - params: GET_LINK_BY_ID_SCHEMA, - body: UPDATE_LINK_SCHEMA, - security: [{ CookieAuth: [] }], - response: { - 200: generateSuccessResponseSchema(LINK_SCHEMA).describe( - 'Link successfully updated', - ), - 401: generateFailureResponseSchema(401).describe( - 'Unauthorized, session cookie is missing', - ), - 404: generateFailureResponseSchema(404).describe('Link not found'), - }, - }, - }, - { - method: 'PUT', - url: '/sharable-links/:id/accept', - handler: acceptSharableLink, - preHandler: [sessionMiddleware], - schema: { - summary: 'Accept a sharable link', - description: 'Accept a sharable link by its ID', - tags: ['Sharable Links'], - params: GET_LINK_BY_ID_SCHEMA, - security: [{ CookieAuth: [] }], - response: { - 400: generateFailureResponseSchema(400).describe( - 'You have already accepted this sharable link', - ), - 404: generateFailureResponseSchema(404).describe( - 'Sharable link not found', - ), - }, - }, - }, - { - method: 'DELETE', - url: '/links/:id', - handler: deleteLink, - preHandler: [sessionMiddleware], - schema: { - summary: 'Delete a link', - description: 'Delete a link by its ID', - tags: ['Links'], - params: GET_LINK_BY_ID_SCHEMA, - security: [{ CookieAuth: [] }], - response: { - 200: generateSuccessResponseSchema(LINK_SCHEMA).describe( - 'Link successfully updated', - ), - 401: generateFailureResponseSchema(401).describe( - 'Unauthorized, session cookie is missing', - ), - 404: generateFailureResponseSchema(404).describe('Link not found'), - }, - }, - }, - ], -}) diff --git a/src/modules/links/schemas/index.ts b/src/modules/links/schemas/index.ts deleted file mode 100644 index b924d8d..0000000 --- a/src/modules/links/schemas/index.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { eventTypeEnum } from '@/db/schema/event-type-enum.js' -import { z } from 'zod' - -const LINK_SCHEMA = z.object({ - id: z.string().uuid().describe('Unique identifier for the link'), - label: z.string().nonempty().max(64).describe('Label for the link'), - url: z.string().url().describe('URL of the link'), - type: z.enum(eventTypeEnum.enumValues).describe('Type of the link'), - subjectId: z - .number() - .int() - .describe('Identifier of the subject associated with the link'), - userId: z.string().uuid(), -}) - -type Link = z.infer - -const SHARABLE_LINK_SCHEMA = z.object({ - id: z.string().uuid().describe('Unique identifier for the sharable link'), - links: LINK_SCHEMA.array().describe('Array of URLs to be shared'), -}) - -type SharableLink = z.infer - -const CREATE_LINK_SCHEMA = LINK_SCHEMA.omit({ id: true, userId: true }) - -type CREATE_LINK = z.infer - -const GET_LINK_BY_ID_SCHEMA = LINK_SCHEMA.pick({ id: true }) - -type GET_LINK_BY_ID = z.infer - -const UPDATE_LINK_SCHEMA = LINK_SCHEMA.partial().pick({ - label: true, - url: true, -}) - -type UPDATE_LINK = z.infer - -const CREATE_SHARABLE_LINK_SCHEMA = z.object({ - linkIds: z.string().uuid().array().describe('Array of link IDs to be shared'), -}) - -type CREATE_SHARABLE_LINK = z.infer - -export { - CREATE_LINK_SCHEMA, - GET_LINK_BY_ID_SCHEMA, - LINK_SCHEMA, - SHARABLE_LINK_SCHEMA, - UPDATE_LINK_SCHEMA, - CREATE_SHARABLE_LINK_SCHEMA, -} -export type { - CREATE_LINK, - GET_LINK_BY_ID, - Link, - SharableLink, - UPDATE_LINK, - CREATE_SHARABLE_LINK, -} diff --git a/src/modules/links/services/LinksService.ts b/src/modules/links/services/LinksService.ts deleted file mode 100644 index 36c447a..0000000 --- a/src/modules/links/services/LinksService.ts +++ /dev/null @@ -1,84 +0,0 @@ -import type { - BaseResponse, - FailureResponse, - SuccessResponse, -} from '@/core/types/common.js' -import { failureResponse, successResponse } from '@/core/utils/response.js' -import { Result } from 'better-result' -import type { CREATE_LINK, Link, UPDATE_LINK } from '../schemas/index.js' -import type { - LinksInjectableDependencies, - LinksRepository, - LinksService, -} from '../types/index.js' - -export class LinksServiceImpl implements LinksService { - private readonly repository: LinksRepository - - constructor({ linksRepository }: LinksInjectableDependencies) { - this.repository = linksRepository - } - - async getUserLinks(userId: string): Promise> { - const pattern = `${userId}:links:*` - - const links = await this.repository.findMany(pattern) - - return successResponse(links, 'User links retrieved successfully') - } - - async createOne( - userId: string, - data: CREATE_LINK, - ): Promise> { - const link = await this.repository.createOne(userId, data) - - return successResponse(link, 'Link created successfully') - } - - async updateOne( - id: string, - userId: string, - data: UPDATE_LINK, - ): Promise, FailureResponse>> { - const existingLink = await this.repository.findOne(id, userId) - - if (!existingLink) { - return Result.err( - failureResponse({ - status: 404, - message: 'Link not found', - }), - ) - } - - await this.repository.updateOne(id, userId, data) - - const link = { - ...existingLink, - ...data, - } - - return Result.ok(successResponse(link, 'Link updated successfully')) - } - - async deleteOne( - id: string, - userId: string, - ): Promise, FailureResponse>> { - const existingLink = await this.repository.findOne(id, userId) - - if (!existingLink) { - return Result.err( - failureResponse({ - status: 404, - message: 'Link not found', - }), - ) - } - - await this.repository.deleteOne(id, userId) - - return Result.ok(successResponse(existingLink, 'Link deleted successfully')) - } -} diff --git a/src/modules/links/services/SharableLinksService.ts b/src/modules/links/services/SharableLinksService.ts deleted file mode 100644 index 45354ed..0000000 --- a/src/modules/links/services/SharableLinksService.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { FailureResponse, SuccessResponse } from '@/core/types/common.js' -import { Result } from 'better-result' -import type { SharableLink } from '../schemas/index.js' -import type { - LinksInjectableDependencies, - SharableLinksRepository, - SharableLinksService, -} from '../types/index.js' -import { failureResponse, successResponse } from '@/core/utils/response.js' - -export class SharableLinksServiceImpl implements SharableLinksService { - private readonly repository: SharableLinksRepository - - constructor({ sharableLinksRepository }: LinksInjectableDependencies) { - this.repository = sharableLinksRepository - } - - async findOne( - id: string, - ): Promise, FailureResponse>> { - const sharableLink = await this.repository.findOne(id) - - if (!sharableLink) { - return Result.err( - failureResponse({ - status: 404, - message: 'Sharable link not found', - }), - ) - } - - return Result.ok( - successResponse(sharableLink, 'Sharable link found successfully'), - ) - } - - async createOne( - userId: string, - data: string[], - ): Promise> { - const id = await this.repository.createOne(userId, data) - - return successResponse({ id }, 'Sharable link created successfully') - } - - async acceptOne( - id: string, - userId: string, - ): Promise> { - const sharableLink = await this.repository.findOne(id) - - if (!sharableLink) { - return Result.err( - failureResponse({ - status: 404, - message: 'Sharable link not found', - }), - ) - } - - if (await this.repository.isAccepted(id, userId)) { - return Result.err( - failureResponse({ - status: 400, - message: 'You have already accepted this sharable link', - }), - ) - } - - await Promise.all([ - this.repository.setAccepted(id, userId), - this.repository.setAccepted(id, userId), - ]) - - return Result.ok(undefined) - } -} diff --git a/src/modules/links/types/index.ts b/src/modules/links/types/index.ts deleted file mode 100644 index 0938fd7..0000000 --- a/src/modules/links/types/index.ts +++ /dev/null @@ -1,80 +0,0 @@ -import type { - BaseResponse, - FailureResponse, - Maybe, - SuccessResponse, -} from '@/core/types/common.js' -import type { BaseDiConfig, InjectableDependencies } from '@/core/types/deps.js' -import type { FindableById } from '@/core/types/services.js' -import type { Result } from 'better-result' -import type { - CREATE_LINK, - Link, - SharableLink, - UPDATE_LINK, -} from '../schemas/index.js' - -interface LinksRepository extends FindableById { - findMany: (pattern: string) => Promise - createOne: (userId: string, data: CREATE_LINK) => Promise - updateOne: (id: string, userId: string, data: UPDATE_LINK) => Promise - deleteOne: (id: string, userId: string) => Promise -} - -interface LinksService { - getUserLinks: (userId: string) => Promise> - createOne: (userId: string, data: CREATE_LINK) => Promise> - updateOne: ( - id: string, - userId: string, - data: UPDATE_LINK, - ) => Promise, FailureResponse>> - deleteOne: ( - id: string, - userId: string, - ) => Promise, FailureResponse>> -} - -interface SharableLinksRepository { - findOne: (id: string) => Promise> - createOne: (userId: string, data: string[]) => Promise - acceptOne: (id: string, userId: string) => Promise - isAccepted: (id: string, userId: string) => Promise - setAccepted: (id: string, userId: string) => Promise -} - -interface SharableLinksService { - findOne: ( - id: string, - ) => Promise, FailureResponse>> - createOne: ( - userId: string, - data: string[], - ) => Promise> - acceptOne: ( - id: string, - userId: string, - ) => Promise> -} - -interface LinksModuleDependencies { - linksRepository: LinksRepository - linksService: LinksService - sharableLinksRepository: SharableLinksRepository - sharableLinksService: SharableLinksService -} - -type LinksInjectableDependencies = - InjectableDependencies - -type LinksDiConfig = BaseDiConfig - -export type { - LinksInjectableDependencies, - LinksModuleDependencies, - LinksRepository, - LinksService, - SharableLinksRepository, - SharableLinksService, - LinksDiConfig, -} diff --git a/src/modules/moodle/constant/index.ts b/src/modules/moodle/constant/index.ts deleted file mode 100644 index 7057d46..0000000 --- a/src/modules/moodle/constant/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { env } from '@/env.js' - -const MOODLE_TOKEN_COOKIE_NAME = 'moodleToken' as const - -const MOODLE_SEARCH_PARAM = { - WS_TOKEN: 'wstoken', - WS_FUNCTION: 'wsfunction', - MOODLE_WS_REST_FORMAT: 'moodlewsrestformat', - SERVICE: 'service', -} as const - -const MOODLE_WS_FUNCTION = { - GET_SITE_INFO: 'core_webservice_get_site_info', - GET_ASSIGNMENTS: 'mod_assign_get_assignments', - GET_COURSES: 'core_enrol_get_users_courses', - GET_COURSE_GRADES: 'gradereport_user_get_grade_items', - GET_COURSE_CONTENT: 'core_course_get_contents', -} as const - -const MOODLE_COURSE_PAGE_BASE_URL = `${env.MOODLE_BASE_URL}/course/view.php` - -const MOODLE_GRADE_TYPE = { - COURSE: 'course', - MODULE: 'module', - CATEGORY: 'category', -} as const - -export { - MOODLE_SEARCH_PARAM, - MOODLE_WS_FUNCTION, - MOODLE_TOKEN_COOKIE_NAME, - MOODLE_COURSE_PAGE_BASE_URL, - MOODLE_GRADE_TYPE, -} diff --git a/src/modules/moodle/exceptions/error-codes.ts b/src/modules/moodle/exceptions/error-codes.ts deleted file mode 100644 index ee5dcf6..0000000 --- a/src/modules/moodle/exceptions/error-codes.ts +++ /dev/null @@ -1,17 +0,0 @@ -const MOODLE_EXCEPTION_CODE = { - API_ERROR: 'MOODLE_API_ERROR', - NON_JSON_API_RESPONSE_ERROR: 'MOODLE_NON_JSON_API_RESPONSE_ERROR', - LOGIN_FAILED_ERROR: 'MOODLE_LOGIN_FAILED', - INVALID_TOKEN_ERROR: 'MOODLE_INVALID_TOKEN', - RECORD_NOT_FOUND_ERROR: 'MOODLE_RECORD_NOT_FOUND_ERROR', - ACCESS_DENIED_ERROR: 'MOODLE_ACCESS_DENIED_ERROR', - INVALID_PARAM_OR_VALUE_ERROR: 'MOODLE_INVALID_PARAM_OR_VALUE_ERROR', - CONTENT_UNAVAILABLE_ERROR: 'MOODLE_CONTENT_UNAVAILABLE_ERROR', - ACTIVITY_UNAVAILABLE_ERROR: 'MOODLE_ACTIVITY_NOT_FOUND_ERROR', -} as const - -type MoodleExceptionCode = - (typeof MOODLE_EXCEPTION_CODE)[keyof typeof MOODLE_EXCEPTION_CODE] - -export { MOODLE_EXCEPTION_CODE } -export type { MoodleExceptionCode } diff --git a/src/modules/moodle/exceptions/error-messages.ts b/src/modules/moodle/exceptions/error-messages.ts deleted file mode 100644 index 3ccbc60..0000000 --- a/src/modules/moodle/exceptions/error-messages.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { MOODLE_EXCEPTION_CODE } from './error-codes.js' - -const MOODLE_API_EXCEPTION_MESSAGES = { - dml_missing_record_exception: MOODLE_EXCEPTION_CODE.RECORD_NOT_FOUND_ERROR, -} as const - -type MoodleExceptionMessage = keyof typeof MOODLE_API_EXCEPTION_MESSAGES - -export { MOODLE_API_EXCEPTION_MESSAGES } -export type { MoodleExceptionMessage } diff --git a/src/modules/moodle/exceptions/moodle.exceptions.ts b/src/modules/moodle/exceptions/moodle.exceptions.ts deleted file mode 100644 index 4b1e6e0..0000000 --- a/src/modules/moodle/exceptions/moodle.exceptions.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { HttpException } from '@/core/exceptions/http.exception.js' -import type { MoodleExceptionCode } from './error-codes.js' -import { HTTP_STATUS } from '@/core/constants/http.js' - -export class MoodleOperationException extends HttpException { - constructor( - code: MoodleExceptionCode, - message?: string, - status: number = HTTP_STATUS.INTERNAL_SERVER_ERR, - ) { - super(code, message, status) - } -} diff --git a/src/modules/moodle/handlers/index.ts b/src/modules/moodle/handlers/index.ts deleted file mode 100644 index c22a61c..0000000 --- a/src/modules/moodle/handlers/index.ts +++ /dev/null @@ -1,161 +0,0 @@ -import type { FastifyReply, FastifyRequest } from 'fastify' -import type { GetCourse, MoodleLogin } from '../schemas/index.js' -import { setMoodleTokenCookie } from '../utils/index.js' -import { HTTP_STATUS } from '@/core/constants/http.js' -import { successResponse } from '@/core/utils/response.js' - -export const moodleLogin = async ( - request: FastifyRequest<{ Body: MoodleLogin }>, - reply: FastifyReply, -): Promise => { - const { moodleService } = request.diScope.cradle - - const result = await moodleService.login(request.body) - - if (result.isErr()) { - const error = result.error - - return reply.status(error.status).send(error) - } - - const { token } = result.unwrap() - - setMoodleTokenCookie(reply, token) - - return reply - .status(HTTP_STATUS.OK) - .send(successResponse({ token }, 'Login successful')) -} - -export const getSiteInfo = async ( - request: FastifyRequest, - reply: FastifyReply, -): Promise => { - const { moodleService } = request.diScope.cradle - const { token } = request.moodleAuth - - const siteInfo = await moodleService.getSiteInfo(token) - - if (siteInfo.isErr()) { - const error = siteInfo.error - - return reply - .status(error.status ?? HTTP_STATUS.INTERNAL_SERVER_ERR) - .send(error) - } - - return reply - .status(HTTP_STATUS.OK) - .send( - successResponse(siteInfo.unwrap(), 'Site info retrieved successfully'), - ) -} - -export const getCourses = async ( - request: FastifyRequest, - reply: FastifyReply, -): Promise => { - const { moodleService } = request.diScope.cradle - const { token, userId } = request.moodleAuth - - const courses = await moodleService.getUserCourses({ token, userId }) - - if (courses.isErr()) { - const error = courses.error - - return reply - .status(error.status ?? HTTP_STATUS.INTERNAL_SERVER_ERR) - .send(error) - } - - return reply - .status(HTTP_STATUS.OK) - .send( - successResponse(courses.unwrap(), 'User courses retrieved successfully'), - ) -} - -export const getCourseGrades = async ( - request: FastifyRequest<{ Params: GetCourse }>, - reply: FastifyReply, -): Promise => { - const { moodleService } = request.diScope.cradle - const { courseId } = request.params - const { token, userId } = request.moodleAuth - - const grades = await moodleService.getCourseGrades({ - token, - courseId, - userId, - }) - - if (grades.isErr()) { - const error = grades.error - - return reply.status(error.status).send(error) - } - - return reply - .status(HTTP_STATUS.OK) - .send( - successResponse(grades.unwrap(), 'Course grades retrieved successfully'), - ) -} - -export const getCourseAssignments = async ( - request: FastifyRequest<{ Params: GetCourse }>, - reply: FastifyReply, -): Promise => { - const { moodleService } = request.diScope.cradle - const { courseId } = request.params - const { token } = request.moodleAuth - - const assignments = await moodleService.getCourseAssignments({ - token, - courseId, - }) - - if (assignments.isErr()) { - const error = assignments.error - - return reply.status(error.status).send(error) - } - - return reply - .status(HTTP_STATUS.OK) - .send( - successResponse( - assignments.unwrap(), - 'Course assignments retrieved successfully', - ), - ) -} - -export const getCourseContent = async ( - request: FastifyRequest<{ Params: GetCourse }>, - reply: FastifyReply, -): Promise => { - const { moodleService } = request.diScope.cradle - const { courseId } = request.params - const { token } = request.moodleAuth - - const content = await moodleService.getCourseContent({ - token, - courseId, - }) - - if (content.isErr()) { - const error = content.error - - return reply.status(error.status).send(error) - } - - return reply - .status(HTTP_STATUS.OK) - .send( - successResponse( - content.unwrap(), - 'Course content retrieved successfully', - ), - ) -} diff --git a/src/modules/moodle/index.ts b/src/modules/moodle/index.ts deleted file mode 100644 index efe034f..0000000 --- a/src/modules/moodle/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { asClass } from 'awilix' -import type { MoodleDiConfig } from './types/di.js' -import { MoodleServiceImpl } from './services/MoodleService.js' -import { MoodleRepositoryImpl } from './repositories/MoodleRepository.js' - -export const resolveMoodleModule = (): MoodleDiConfig => ({ - moodleService: asClass(MoodleServiceImpl).singleton(), - moodleRepository: asClass(MoodleRepositoryImpl).singleton(), -}) diff --git a/src/modules/moodle/middleware/index.ts b/src/modules/moodle/middleware/index.ts deleted file mode 100644 index e972d51..0000000 --- a/src/modules/moodle/middleware/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { HTTP_STATUS } from '@/core/constants/http.js' -import type { FastifyReply, FastifyRequest } from 'fastify' -import { MOODLE_TOKEN_COOKIE_NAME } from '../constant/index.js' - -export interface MoodleAuthData { - token: string - userId: number -} - -export const moodleAuthMiddleware = async ( - request: FastifyRequest, - reply: FastifyReply, -): Promise => { - const token = request.cookies[MOODLE_TOKEN_COOKIE_NAME] - - if (!token) { - return reply.status(HTTP_STATUS.UNAUTHORIZED).send({ - message: 'Moodle authentication token is missing', - }) - } - - const { moodleService } = request.diScope.cradle - const result = await moodleService.getSiteInfo(token) - - if (result.isErr()) { - const error = result.error - return reply - .status(error.status ?? HTTP_STATUS.UNAUTHORIZED) - .send({ message: error.message }) - } - - const { userId } = result.unwrap() - - request.moodleAuth = { token, userId } -} - -declare module 'fastify' { - interface FastifyRequest { - moodleAuth: MoodleAuthData - } -} diff --git a/src/modules/moodle/repositories/MoodleRepository.ts b/src/modules/moodle/repositories/MoodleRepository.ts deleted file mode 100644 index 3f96a12..0000000 --- a/src/modules/moodle/repositories/MoodleRepository.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { getContentType } from '@/core/utils/index.js' -import { Result } from 'better-result' -import { MOODLE_SEARCH_PARAM } from '../constant/index.js' -import { MOODLE_EXCEPTION_CODE } from '../exceptions/error-codes.js' -import { MoodleOperationException } from '../exceptions/moodle.exceptions.js' -import type { - MoodleInjectableDependencies, - MoodleRepository, -} from '../types/di.js' -import type { BuildMoodleApiUrlArgs } from '../types/index.js' -import { - isMoodleErrorResponse, - isMoodleExceptionResponse, - throwMoodleApiException, -} from '../utils/index.js' - -const JSON_CONTENT_TYPES = ['application/json', 'text/json'] -const JSON_START_CHARS = ['{', '['] - -export class MoodleRepositoryImpl implements MoodleRepository { - private readonly baseUrl: string - - constructor({ config }: MoodleInjectableDependencies) { - const { moodle } = config - - this.baseUrl = moodle.baseUrl - } - - async fetch( - url: URL, - params?: RequestInit, - ): Promise> { - const response = await fetch(url, params) - const contentType = getContentType(response) - - if (!JSON_CONTENT_TYPES.includes(contentType)) { - const text = await response.text() - - if (JSON_START_CHARS.some((char) => text.trim().startsWith(char))) { - const data: T = JSON.parse(text) - if (isMoodleExceptionResponse(data)) { - return throwMoodleApiException(data) - } - return Result.ok(data) - } - return Result.err( - new MoodleOperationException( - MOODLE_EXCEPTION_CODE.NON_JSON_API_RESPONSE_ERROR, - 'Received non-JSON response from Moodle API', - ), - ) - } - - const data = (await response.json()) as T - - if (isMoodleExceptionResponse(data)) { - return throwMoodleApiException(data) - } - - if (isMoodleErrorResponse(data)) { - return throwMoodleApiException(data) - } - - return Result.ok(data) - } - - buildApiUrl({ - path = '/webservice/rest/server.php', - token, - wsFunction, - params = {}, - }: BuildMoodleApiUrlArgs): URL { - const url = new URL(path, this.baseUrl) - - if (token) { - url.searchParams.set(MOODLE_SEARCH_PARAM.WS_TOKEN, token) - } - - if (wsFunction) { - url.searchParams.set(MOODLE_SEARCH_PARAM.WS_FUNCTION, wsFunction) - url.searchParams.set(MOODLE_SEARCH_PARAM.MOODLE_WS_REST_FORMAT, 'json') - } - - for (const [key, value] of Object.entries(params)) { - url.searchParams.set(key, String(value)) - } - - return url - } -} diff --git a/src/modules/moodle/routes/index.ts b/src/modules/moodle/routes/index.ts deleted file mode 100644 index 17eb35a..0000000 --- a/src/modules/moodle/routes/index.ts +++ /dev/null @@ -1,157 +0,0 @@ -import type { Routes } from '@/core/types/routes.js' -import { - generateFailureResponseSchema, - generateSuccessResponseSchema, -} from '@/core/utils/schemas.js' -import { - getCourseAssignments, - getCourseGrades, - getCourses, - getSiteInfo, - moodleLogin, -} from '../handlers/index.js' -import { moodleAuthMiddleware } from '../middleware/index.js' -import { - GET_COURSE, - MOODLE_LOGIN, - MOODLE_LOGIN_RESPONSE, - MOODLE_SITE_INFO_RESPONSE, - MOODLE_COURSE_RESPONSE, - MOODLE_GRADES_RESPONSE, - MOODLE_ASSIGNMENT_RESPONSE, -} from '../schemas/index.js' - -export const getMoodleRoutes = (): Routes => ({ - routes: [ - { - method: 'POST', - url: '/moodle/login', - handler: moodleLogin, - schema: { - tags: ['Moodle'], - summary: 'Login to Moodle', - description: - 'Authenticate with Moodle credentials and receive a session token', - body: MOODLE_LOGIN, - response: { - 200: generateSuccessResponseSchema(MOODLE_LOGIN_RESPONSE).describe( - 'Successfully authenticated', - ), - 500: generateFailureResponseSchema(500).describe( - 'Login failed or invalid credentials', - ), - }, - }, - }, - { - method: 'GET', - url: '/moodle/info', - preHandler: [moodleAuthMiddleware], - handler: getSiteInfo, - schema: { - tags: ['Moodle'], - summary: 'Get site info', - description: - 'Retrieve Moodle site information and current user profile', - security: [{ CookieAuth: [] }], - response: { - 200: generateSuccessResponseSchema( - MOODLE_SITE_INFO_RESPONSE, - ).describe('Site info and user profile'), - 401: generateFailureResponseSchema(401).describe( - 'Moodle authentication token is missing or invalid', - ), - 500: generateFailureResponseSchema(500).describe( - 'Failed to fetch site info from Moodle', - ), - }, - }, - }, - { - method: 'GET', - url: '/moodle/courses', - preHandler: [moodleAuthMiddleware], - handler: getCourses, - schema: { - tags: ['Moodle'], - summary: 'Get user courses', - description: - 'Retrieve all active courses enrolled by the authenticated user', - security: [{ CookieAuth: [] }], - response: { - 200: generateSuccessResponseSchema( - MOODLE_COURSE_RESPONSE.array(), - ).describe('List of enrolled courses'), - 401: generateFailureResponseSchema(401).describe( - 'Moodle authentication token is missing or invalid', - ), - 404: generateFailureResponseSchema(404).describe( - 'No courses found for the user', - ), - 500: generateFailureResponseSchema(500).describe( - 'Failed to fetch courses from Moodle', - ), - }, - }, - }, - { - method: 'GET', - url: '/moodle/courses/:courseId/grades', - preHandler: [moodleAuthMiddleware], - handler: getCourseGrades, - schema: { - tags: ['Moodle'], - summary: 'Get course grades', - description: - 'Retrieve grade items and final grade for a specific course', - security: [{ CookieAuth: [] }], - params: GET_COURSE, - response: { - 200: generateSuccessResponseSchema(MOODLE_GRADES_RESPONSE).describe( - 'Grade items and final grade for the course', - ), - 401: generateFailureResponseSchema(401).describe( - 'Moodle authentication token is missing or invalid', - ), - 404: generateFailureResponseSchema(404).describe( - 'No grade record found for the course and user', - ), - 500: generateFailureResponseSchema(500).describe( - 'Failed to fetch grades from Moodle', - ), - }, - }, - }, - { - method: 'GET', - url: '/moodle/courses/:courseId/assignments', - preHandler: [moodleAuthMiddleware], - handler: getCourseAssignments, - schema: { - tags: ['Moodle'], - summary: 'Get course assignments', - description: 'Retrieve all assignments for a specific course', - security: [{ CookieAuth: [] }], - params: GET_COURSE, - response: { - 200: generateSuccessResponseSchema( - MOODLE_ASSIGNMENT_RESPONSE.array(), - ).describe('List of assignments for the course'), - 401: generateFailureResponseSchema(401).describe( - 'Moodle authentication token is missing or invalid', - ), - 403: generateFailureResponseSchema(403).describe( - 'Access denied to the course assignments', - ), - 404: generateFailureResponseSchema(404).describe('Course not found'), - 500: generateFailureResponseSchema(500).describe( - 'Failed to fetch assignments from Moodle', - ), - 503: generateFailureResponseSchema(503).describe( - 'Course content or activity is currently unavailable', - ), - }, - }, - }, - ], -}) diff --git a/src/modules/moodle/schemas/index.ts b/src/modules/moodle/schemas/index.ts deleted file mode 100644 index 6ae8e51..0000000 --- a/src/modules/moodle/schemas/index.ts +++ /dev/null @@ -1,134 +0,0 @@ -import z from 'zod' - -const GET_COURSE = z.object({ - courseId: z.coerce - .number() - .int() - .positive() - .describe('Unique Moodle course identifier'), -}) - -type GetCourse = z.infer - -const MOODLE_LOGIN = z - .object({ - username: z.string().describe('Moodle account username'), - password: z.string().describe('Moodle account password'), - }) - .strict() - -type MoodleLogin = z.infer - -const MOODLE_LOGIN_RESPONSE = z - .object({ - token: z.string().describe('Moodle session token'), - privatetoken: z - .string() - .nullable() - .describe('Moodle private token for web services'), - }) - .strict() - -type MoodleLoginResponse = z.infer - -const MOODLE_SITE_INFO_RESPONSE = z.object({ - firstName: z.string().describe('User first name'), - lastName: z.string().describe('User last name'), - username: z.string().describe('Moodle username'), - userId: z.number().describe('Unique Moodle user identifier'), -}) - -const MOODLE_COURSE_RESPONSE = z.object({ - id: z.number().describe('Unique course identifier'), - name: z.string().describe('Course display name'), - image: z.string().describe('Course image URL'), - startedAt: z.number().describe('Course start date as Unix timestamp'), - endedAt: z.number().describe('Course end date as Unix timestamp'), - url: z.string().describe('Direct link to the course page'), -}) - -const MOODLE_GRADE_RANGE = z.object({ - min: z.number().describe('Minimum possible grade'), - max: z.number().describe('Maximum possible grade'), -}) - -const MOODLE_FINAL_GRADE = z - .object({ - grade: z.number().nullable().describe('Final numeric grade value'), - letterGrade: z.string().nullable().describe('Final letter grade'), - }) - .nullable() - -const MOODLE_GRADE = z.object({ - id: z.number().describe('Grade item identifier'), - gradedAt: z.number().nullable().describe('Grading date as Unix timestamp'), - grade: z.number().nullable().describe('Numeric grade value'), - letterGrade: z.string().nullable().describe('Letter grade representation'), - range: MOODLE_GRADE_RANGE.describe('Possible grade range'), - feedback: z.string().nullable().describe('Instructor feedback'), - name: z.string().optional().describe('Grade item name'), - module: z - .string() - .optional() - .describe('Source module type (quiz, assignment, etc.)'), - type: z.string().describe('Grade type (module, course, category)'), -}) - -const MOODLE_GRADES_RESPONSE = z.object({ - final: MOODLE_FINAL_GRADE.describe('Overall final grade for the course'), - grades: MOODLE_GRADE.array().describe('List of individual grade items'), -}) - -const MOODLE_ASSIGNMENT_ATTACHMENT = z.object({ - name: z.string().describe('Attachment file name'), - size: z.number().describe('File size in bytes'), - mimeType: z.string().describe('File MIME type'), - url: z.string().describe('Direct download URL'), -}) - -const MOODLE_FILE_SUBMISSION = z - .object({ - maxFiles: z.number().describe('Maximum number of files allowed'), - maxSize: z.number().describe('Maximum total submission size in bytes'), - allowedTypes: z - .string() - .array() - .describe('List of allowed file extensions'), - }) - .nullable() - -const MOODLE_ASSIGNMENT_RESPONSE = z.object({ - id: z.number().describe('Unique assignment identifier'), - name: z.string().describe('Assignment title'), - deadlineAt: z.number().describe('Submission deadline as Unix timestamp'), - hardDeadlineAt: z - .number() - .describe( - 'Hard cutoff date as Unix timestamp, no submissions accepted after', - ), - isSubmitRequired: z - .boolean() - .describe('Whether submission is required for completion'), - grade: z.number().describe('Maximum grade for the assignment'), - reopenMethod: z - .enum(['manual', 'untilpass', 'none']) - .describe('Attempt reopen method'), - intro: z.string().nullable().describe('Assignment description in Markdown'), - attachments: MOODLE_ASSIGNMENT_ATTACHMENT.array().describe( - 'Assignment attachments provided by the teacher', - ), - fileSubmission: MOODLE_FILE_SUBMISSION.describe( - 'File submission configuration, null if file upload is disabled', - ), -}) - -export { - GET_COURSE, - MOODLE_LOGIN, - MOODLE_LOGIN_RESPONSE, - MOODLE_SITE_INFO_RESPONSE, - MOODLE_COURSE_RESPONSE, - MOODLE_GRADES_RESPONSE, - MOODLE_ASSIGNMENT_RESPONSE, -} -export type { GetCourse, MoodleLogin, MoodleLoginResponse } diff --git a/src/modules/moodle/services/MoodleService.ts b/src/modules/moodle/services/MoodleService.ts deleted file mode 100644 index 7ce42ab..0000000 --- a/src/modules/moodle/services/MoodleService.ts +++ /dev/null @@ -1,254 +0,0 @@ -import { HTTP_STATUS } from '@/core/constants/http.js' -import type { HttpExceptionMap } from '@/core/types/common.js' -import { mapHttpException } from '@/core/utils/common.js' -import { Result } from 'better-result' -import { MOODLE_SEARCH_PARAM, MOODLE_WS_FUNCTION } from '../constant/index.js' -import { - MOODLE_EXCEPTION_CODE, - type MoodleExceptionCode, -} from '../exceptions/error-codes.js' -import { MoodleOperationException } from '../exceptions/moodle.exceptions.js' -import type { MoodleLogin, MoodleLoginResponse } from '../schemas/index.js' -import type { - GetAssignmentsArgs, - GetCourseContent, - GetCourseGradesArgs, - GetUserCoursesArgs, - MoodleInjectableDependencies, - MoodleRepository, - MoodleService, -} from '../types/index.js' -import type { - MoodleAssignmentsResponse, - MoodleGradesResponse, - MoodleSiteInfoResponse, - RawMoodleCoursesResponse, - RawMoodleGradesResponse, - RawMoodleSiteInfoResponse, -} from '../types/responses.js' -import { - byCourseNameAsc, - constructMoodleRequestParams, - getDefaultMoodleHeaders, - getMoodleCourseFinalGrade, - hasPrivateToken, - isAssignmentGrade, - isMoodleAuthTokenValid, - mapMoodleAssignment, - mapMoodleCourse, - mapMoodleCourseGrades, - mapMoodleSiteInfo, - moodleWarningToException, -} from '../utils/index.js' - -export class MoodleServiceImpl implements MoodleService { - private readonly repository: MoodleRepository - - constructor({ moodleRepository }: MoodleInjectableDependencies) { - this.repository = moodleRepository - } - - async login( - data: MoodleLogin, - ): Promise> { - const url = this.repository.buildApiUrl({ path: '/login/token.php' }) - - const body = new URLSearchParams() - body.set(MOODLE_SEARCH_PARAM.SERVICE, 'moodle_mobile_app') - for (const [key, value] of Object.entries(data)) { - body.set(key, value) - } - - const result = await this.repository.fetch>(url, { - method: 'POST', - headers: getDefaultMoodleHeaders(), - body, - }) - - if (result.isErr()) { - return Result.err( - new MoodleOperationException( - MOODLE_EXCEPTION_CODE.LOGIN_FAILED_ERROR, - result.error.message, - ), - ) - } - - const response = result.unwrap() - - if (!isMoodleAuthTokenValid(response)) { - return Result.err( - new MoodleOperationException( - MOODLE_EXCEPTION_CODE.INVALID_TOKEN_ERROR, - 'Invalid login response from Moodle', - ), - ) - } - - return Result.ok({ - token: response.token, - privatetoken: hasPrivateToken(response) ? response.privatetoken : null, - }) - } - - async getSiteInfo( - token: string, - ): Promise> { - const url = this.repository.buildApiUrl({ - token, - wsFunction: MOODLE_WS_FUNCTION.GET_SITE_INFO, - }) - - const result = await this.repository.fetch(url) - - return result.map(mapMoodleSiteInfo) - } - - async getUserCourses({ token, ...rest }: GetUserCoursesArgs) { - const params = constructMoodleRequestParams(rest) - - const url = this.repository.buildApiUrl({ - token, - wsFunction: MOODLE_WS_FUNCTION.GET_COURSES, - params, - }) - - const result = await this.repository.fetch(url) - - if (result.isErr()) { - const errorMap: HttpExceptionMap = { - [MOODLE_EXCEPTION_CODE.RECORD_NOT_FOUND_ERROR]: { - message: 'No courses found for the specified user.', - status: HTTP_STATUS.NOT_FOUND, - }, - } - - const obj = mapHttpException(result.error.code, errorMap) - - return Result.err( - new MoodleOperationException( - result.error.code, - obj.message ?? result.error.message, - obj.status, - ), - ) - } - - const courses = result - .unwrap() - .map(mapMoodleCourse) - .toSorted(byCourseNameAsc) - - return Result.ok(courses) - } - - async getCourseGrades({ - token, - ...rest - }: GetCourseGradesArgs): Promise< - Result - > { - const params = constructMoodleRequestParams(rest) - const url = this.repository.buildApiUrl({ - token, - wsFunction: MOODLE_WS_FUNCTION.GET_COURSE_GRADES, - params, - }) - - const result = await this.repository.fetch(url) - - if (result.isErr()) { - const errorMap: HttpExceptionMap = { - [MOODLE_EXCEPTION_CODE.RECORD_NOT_FOUND_ERROR]: { - message: 'No grade record found for the specified course and user.', - status: HTTP_STATUS.NOT_FOUND, - }, - } - - const obj = mapHttpException(result.error.code, errorMap) - - return Result.err( - new MoodleOperationException( - result.error.code, - obj.message ?? result.error.message, - obj.status, - ), - ) - } - - const gradesObj = result.unwrap().usergrades.at(0) - - if (!gradesObj) { - return Result.ok({ final: null, grades: [] }) - } - - const grades = gradesObj.gradeitems - const moduleGrades = grades - .filter(isAssignmentGrade) - .map(mapMoodleCourseGrades) - - return Result.ok({ - final: getMoodleCourseFinalGrade(grades), - grades: moduleGrades, - }) - } - - async getCourseAssignments({ - token, - courseId, - }: GetAssignmentsArgs): Promise> { - const url = this.repository.buildApiUrl({ - token: token, - wsFunction: MOODLE_WS_FUNCTION.GET_ASSIGNMENTS, - }) - - url.searchParams.set(`courseids[]`, courseId.toString()) - - const response = await this.repository.fetch(url) - - if (response.isErr()) { - return Result.err(response.error) - } - - const courses = response.unwrap().courses - - if (!courses.length) { - const warning = response.unwrap().warnings.at(0) - - if (!warning) { - return Result.err( - new MoodleOperationException( - MOODLE_EXCEPTION_CODE.API_ERROR, - 'Failed to fetch course assignments due to an unknown error.', - HTTP_STATUS.INTERNAL_SERVER_ERR, - ), - ) - } - - return Result.err(moodleWarningToException(warning)) - } - - const assignments = courses.at(0)?.assignments - - if (!assignments) { - return Result.ok([]) - } - - return Result.ok(assignments.map(mapMoodleAssignment)) - } - - async getCourseContent({ - token, - ...rest - }: GetCourseContent): Promise> { - const params = constructMoodleRequestParams(rest) - - const url = this.repository.buildApiUrl({ - token, - wsFunction: MOODLE_WS_FUNCTION.GET_COURSE_CONTENT, - params, - }) - - return this.repository.fetch(url) - } -} diff --git a/src/modules/moodle/types/common.ts b/src/modules/moodle/types/common.ts deleted file mode 100644 index a9c1110..0000000 --- a/src/modules/moodle/types/common.ts +++ /dev/null @@ -1,43 +0,0 @@ -type MoodleException = - | { exception: string; message: string } - | { error: string; message: string } - -type MoodleApiParams = Record - -interface BaseMoodleArgs { - token: string -} - -interface BuildMoodleApiUrlArgs { - path?: string - token?: string - wsFunction?: string - params?: MoodleApiParams -} - -interface GetAssignmentsArgs extends BaseMoodleArgs { - courseId: number -} - -interface GetUserCoursesArgs extends BaseMoodleArgs { - userId: number -} - -interface GetCourseGradesArgs extends BaseMoodleArgs { - courseId: number - userId: number -} - -interface GetCourseContent extends BaseMoodleArgs { - courseId: number -} - -export type { - MoodleException, - BaseMoodleArgs, - BuildMoodleApiUrlArgs, - GetAssignmentsArgs, - GetCourseContent, - GetUserCoursesArgs, - GetCourseGradesArgs, -} diff --git a/src/modules/moodle/types/di.ts b/src/modules/moodle/types/di.ts deleted file mode 100644 index 3c89e60..0000000 --- a/src/modules/moodle/types/di.ts +++ /dev/null @@ -1,62 +0,0 @@ -import type { BaseDiConfig, InjectableDependencies } from '@/core/types/deps.js' -import type { Result } from 'better-result' -import type { MoodleOperationException } from '../exceptions/moodle.exceptions.js' -import type { MoodleLogin, MoodleLoginResponse } from '../schemas/index.js' -import type { - BuildMoodleApiUrlArgs, - GetAssignmentsArgs, - GetCourseContent, - GetCourseGradesArgs, - GetUserCoursesArgs, -} from './common.js' -import type { - MoodleGradesResponse, - MoodleSiteInfoResponse, -} from './responses.js' - -interface MoodleRepository { - buildApiUrl: (args: BuildMoodleApiUrlArgs) => URL - fetch: ( - url: URL, - params?: RequestInit, - ) => Promise> -} - -interface MoodleService { - getSiteInfo: ( - token: string, - ) => Promise> - getUserCourses: ( - args: GetUserCoursesArgs, - ) => Promise> - getCourseGrades: ( - args: GetCourseGradesArgs, - ) => Promise> - getCourseAssignments: ( - args: GetAssignmentsArgs, - ) => Promise> - login: ( - data: MoodleLogin, - ) => Promise> - getCourseContent: ( - data: GetCourseContent, - ) => Promise> -} - -interface MoodleModuleDependencies { - moodleService: MoodleService - moodleRepository: MoodleRepository -} - -type MoodleInjectableDependencies = - InjectableDependencies - -type MoodleDiConfig = BaseDiConfig - -export type { - MoodleDiConfig, - MoodleInjectableDependencies, - MoodleModuleDependencies, - MoodleService, - MoodleRepository, -} diff --git a/src/modules/moodle/types/index.ts b/src/modules/moodle/types/index.ts deleted file mode 100644 index 926a224..0000000 --- a/src/modules/moodle/types/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './common.js' -export * from './di.js' diff --git a/src/modules/moodle/types/responses.ts b/src/modules/moodle/types/responses.ts deleted file mode 100644 index cb4ee0d..0000000 --- a/src/modules/moodle/types/responses.ts +++ /dev/null @@ -1,222 +0,0 @@ -import type { Bit, Maybe } from '@/core/types/common.js' - -interface MoodleFunction { - name: string - version: string -} - -interface RawMoodleSiteInfoResponse { - sitename: string - username: string - firstname: string - lastname: string - lang: string - userid: number - siteurl: string - userpictureurl: number - functions: MoodleFunction[] -} - -interface MoodleSiteInfoResponse { - firstName: string - lastName: string - username: string - userId: number -} - -interface RawMoodleCoursesResponse { - id: number - shortname: string - fullname: string - displayname: string - courseimage: string - startdate: number - enddate: number -} - -interface MoodleCoursesResponse { - id: number - name: string - image: string - startedAt: number - endedAt: number - url: string -} - -type RawGradeModule = 'quiz' | 'assign' | 'course' | 'attendance' -type RawGradeType = 'mod' | 'course' | 'category' - -interface BaseRawMoodleGrade { - id: number - graderaw: number - grademin: number - grademax: number - gradedategraded: Maybe - lettergradeformatted: Maybe - feedback: string -} - -type RawMoodleGrade = BaseRawMoodleGrade & - ( - | { - itemname: string - itemtype: Extract - itemmodule: RawGradeModule - } - | { - itemtype: Exclude - } - ) - -interface RawMoodleGradesResponse { - usergrades: { - courseid: number - gradeitems: RawMoodleGrade[] - }[] -} - -type GradeModule = Exclude | 'assignment' -type GradeType = Exclude | 'module' - -type GradeRange = { - min: number - max: number -} - -interface BaseMoodleGrade { - id: number - gradedAt: Maybe - grade: Maybe - letterGrade: Maybe - range: GradeRange - feedback: Maybe -} - -type MoodleGrade = BaseMoodleGrade & - ( - | { name: string; module: GradeModule; type: Extract } - | { type: Exclude } - ) - -type MoodleFinalGrade = Pick - -interface MoodleGradesResponse { - final: Maybe - grades: MoodleGrade[] -} - -type AttemptReopenMethod = 'manual' | 'untilpass' | 'none' - -interface RawAssignmentAttachment { - filename: string - filesize: number - mimetype: string - fileurl: string -} - -type MoodleAssigmentInputFormat = 0 | 1 | 2 | 3 - -type MoodlePlugin = 'file' | 'comment' -interface RawMoodleAssignmentConfig { - plugin: MoodlePlugin - subtype: string - name: string - value: string -} - -interface RawMoodleAssignment { - id: number - name: string - duedate: number - cutoffdate: number - grade: number - gradepenalty: number - completionsubmit: Bit - maxattempts: number - configs: RawMoodleAssignmentConfig[] - attemptreopenmethod: AttemptReopenMethod - intro: string - introformat: MoodleAssigmentInputFormat - introattachments: RawAssignmentAttachment[] -} - -type MoodleWarningItem = - | 'course' - | 'module' - | 'user' - | 'category' - | 'section' - | 'assignment' - | 'quiz' - | 'forum' - | 'group' - -type MoodleWarningCode = '1' | '2' | '3' | '4' | '8' - -interface MoodleWarning { - item: MoodleWarningItem - itemid: number - warningcode: MoodleWarningCode - message: string -} - -interface MoodleAssignmentsResponse { - courses: { - id: number - fullname: string - shortname: string - timemodified: number - assignments: RawMoodleAssignment[] - }[] - warnings: MoodleWarning[] -} - -interface MoodleAssignmentAttachment { - name: string - size: number - mimeType: string - url: string -} - -type MoodleAssignmentFileSubmission = { - maxFiles: number - maxSize: number - allowedTypes: string[] -} - -interface MoodleAssignment { - id: number - name: string - deadlineAt: number - hardDeadlineAt: number - isSubmitRequired: boolean - grade: number - reopenMethod: AttemptReopenMethod - intro: Maybe - attachments: MoodleAssignmentAttachment[] - fileSubmission: Maybe -} - -export type { - MoodleSiteInfoResponse, - RawMoodleSiteInfoResponse, - MoodleCoursesResponse, - RawMoodleCoursesResponse, - RawMoodleGradesResponse, - RawGradeType, - RawGradeModule, - RawMoodleAssignment, - GradeModule, - GradeType, - MoodleGrade, - MoodleGradesResponse, - RawMoodleGrade, - MoodleFinalGrade, - MoodleAssignmentsResponse, - MoodleWarning, - MoodleWarningCode, - MoodleWarningItem, - MoodleAssignment, - MoodleAssignmentFileSubmission, - MoodleAssignmentAttachment, -} diff --git a/src/modules/moodle/utils/index.ts b/src/modules/moodle/utils/index.ts deleted file mode 100644 index 84b0ed2..0000000 --- a/src/modules/moodle/utils/index.ts +++ /dev/null @@ -1,355 +0,0 @@ -import { DAY } from '@/core/constants/time.js' -import { setCookie } from '@/core/utils/cookie.js' -import { Result } from 'better-result' -import type { FastifyReply } from 'fastify' -import { - MOODLE_COURSE_PAGE_BASE_URL, - MOODLE_GRADE_TYPE, - MOODLE_TOKEN_COOKIE_NAME, -} from '../constant/index.js' -import { - MOODLE_EXCEPTION_CODE, - type MoodleExceptionCode, -} from '../exceptions/error-codes.js' -import { - MOODLE_API_EXCEPTION_MESSAGES, - type MoodleExceptionMessage, -} from '../exceptions/error-messages.js' -import { MoodleOperationException } from '../exceptions/moodle.exceptions.js' -import type { MoodleException } from '../types/common.js' -import type { - GradeModule, - GradeType, - MoodleAssignment, - MoodleAssignmentAttachment, - MoodleAssignmentFileSubmission, - MoodleCoursesResponse, - MoodleFinalGrade, - MoodleGrade, - MoodleSiteInfoResponse, - MoodleWarning, - MoodleWarningCode, - RawGradeModule, - RawGradeType, - RawMoodleAssignment, - RawMoodleCoursesResponse, - RawMoodleGrade, - RawMoodleSiteInfoResponse, -} from '../types/responses.js' -import type { Maybe } from '@/core/types/common.js' -import { HTTP_STATUS, type HttpStatus } from '@/core/constants/http.js' -import { NodeHtmlMarkdown } from 'node-html-markdown' - -const getDefaultMoodleHeaders = () => { - const headers = new Headers() - headers.set('Content-Type', 'application/x-www-form-urlencoded') - return headers -} - -const isMoodleExceptionResponse = ( - data: unknown, -): data is { exception: string; message: string } => { - return !!data && typeof data === 'object' && Object.hasOwn(data, 'exception') -} - -const isMoodleErrorResponse = ( - data: unknown, -): data is { error: string; message: string } => { - return ( - !!data && - typeof data === 'object' && - Object.hasOwn(data, 'error') && - !Object.hasOwn(data, 'token') - ) -} - -const extractMoodleExceptionMessage = (data: MoodleException): string => { - if ('exception' in data && data.exception) { - return data.exception - } - if ('error' in data && data.error) { - return data.error - } - return data.message ?? 'Moodle API unknown error' -} - -const getMoodleExceptionCode = ( - message: MoodleExceptionMessage | string, -): MoodleExceptionCode => { - return message in MOODLE_API_EXCEPTION_MESSAGES - ? MOODLE_API_EXCEPTION_MESSAGES[message as MoodleExceptionMessage] - : MOODLE_EXCEPTION_CODE.API_ERROR -} - -const throwMoodleApiException = (data: MoodleException) => { - const message = extractMoodleExceptionMessage(data) - const code = getMoodleExceptionCode(message) - - return Result.err(new MoodleOperationException(code, message)) -} - -const isMoodleAuthTokenValid = (data: unknown): data is { token: string } => { - return ( - !!data && - typeof data === 'object' && - Object.hasOwn(data, 'token') && - typeof (data as { token: unknown }).token === 'string' - ) -} - -const hasPrivateToken = (data: unknown): data is { privatetoken: string } => { - return ( - !!data && - typeof data === 'object' && - Object.hasOwn(data, 'privatetoken') && - typeof (data as { privatetoken: unknown }).privatetoken === 'string' - ) -} - -const setMoodleTokenCookie = (reply: FastifyReply, token: string): void => { - const expiresAt = new Date(Date.now() + 7 * DAY) - - setCookie({ - name: MOODLE_TOKEN_COOKIE_NAME, - value: token, - expiresAt: expiresAt, - })(reply) -} - -const mapMoodleSiteInfo = ( - data: RawMoodleSiteInfoResponse, -): MoodleSiteInfoResponse => ({ - firstName: data.firstname, - lastName: data.lastname, - username: data.username, - userId: data.userid, -}) - -const ensureCourseIsActive = (data: RawMoodleCoursesResponse): boolean => { - return data.enddate * 1000 > Date.now() -} - -const sanitizeCourseName = (name: string): string => { - return name.charAt(0).match(/\d/) ? name.slice(1).trim() : name.trim() -} - -const removeOptionalCourseSign = (name: string): string => { - return name.replace('*', '').trim() -} - -const mapMoodleCourse = ( - data: RawMoodleCoursesResponse, -): MoodleCoursesResponse => { - const url = new URL(`${MOODLE_COURSE_PAGE_BASE_URL}/course/view.php`) - - url.searchParams.set('id', data.id.toString()) - - return { - id: data.id, - name: sanitizeCourseName(data.fullname), - startedAt: data.startdate, - endedAt: data.enddate, - image: data.courseimage, - url: url.toString(), - } -} - -const byCourseNameAsc = ( - a: MoodleCoursesResponse, - b: MoodleCoursesResponse, -): number => { - const nameA = removeOptionalCourseSign(a.name) - const nameB = removeOptionalCourseSign(b.name) - - return nameA.localeCompare(nameB) -} - -const constructMoodleRequestParams = ( - params: Record, -): Record, V> => { - return Object.entries(params).reduce( - (acc, [key, value]) => { - acc[key.toLowerCase() as Lowercase] = value as V - - return acc - }, - {} as Record, V>, - ) -} - -const mapGradeModule = (module: RawGradeModule): GradeModule => { - return module === 'assign' ? 'assignment' : module -} - -const mapGradeType = (type: RawGradeType): GradeType => { - return type === 'mod' ? 'module' : type -} - -const isAssignmentGrade = (grade: RawMoodleGrade): boolean => { - return !( - [MOODLE_GRADE_TYPE.COURSE, MOODLE_GRADE_TYPE.CATEGORY] as string[] - ).includes(grade.itemtype) -} - -const mapMoodleCourseGrades = (grade: RawMoodleGrade): MoodleGrade => { - const baseGrade = { - id: grade.id, - gradedAt: grade.gradedategraded, - grade: grade.graderaw, - letterGrade: !grade.graderaw ? null : grade.lettergradeformatted, - range: { - min: grade.grademin, - max: grade.grademax, - }, - feedback: !grade.feedback.trim() ? null : grade.feedback, - } - - if (grade.itemtype === 'mod') { - return { - name: grade.itemname, - module: mapGradeModule(grade.itemmodule), - type: 'module' as const, - ...baseGrade, - } - } - - return { - type: mapGradeType(grade.itemtype) as Exclude, - ...baseGrade, - } -} - -const getMoodleCourseFinalGrade = ( - grades: RawMoodleGrade[], -): Maybe => { - const grade = grades.find((g) => g.itemtype === MOODLE_GRADE_TYPE.COURSE) - - if (!grade) { - return null - } - - return { - letterGrade: grade.lettergradeformatted, - grade: grade.graderaw, - } -} - -const mapMoodleWarningToErrorCode = ( - warning: MoodleWarning, -): MoodleExceptionCode => { - const warningCodeMap: Record = { - '1': MOODLE_EXCEPTION_CODE.RECORD_NOT_FOUND_ERROR, - '2': MOODLE_EXCEPTION_CODE.ACCESS_DENIED_ERROR, - '3': MOODLE_EXCEPTION_CODE.INVALID_PARAM_OR_VALUE_ERROR, - '4': MOODLE_EXCEPTION_CODE.CONTENT_UNAVAILABLE_ERROR, - '8': MOODLE_EXCEPTION_CODE.ACTIVITY_UNAVAILABLE_ERROR, - } - - return warningCodeMap[warning.warningcode] -} - -const mapMoodleWarningToStatusCode = (warning: MoodleWarning): HttpStatus => { - const statusCodeMap: Record = { - '1': HTTP_STATUS.NOT_FOUND, - '2': HTTP_STATUS.FORBIDDEN, - '3': HTTP_STATUS.BAD_REQUEST, - '4': HTTP_STATUS.SERVICE_UNAVAILABLE, - '8': HTTP_STATUS.SERVICE_UNAVAILABLE, - } - - return statusCodeMap[warning.warningcode] ?? HTTP_STATUS.INTERNAL_SERVER_ERR -} - -const moodleWarningToException = ( - warning: MoodleWarning, -): MoodleOperationException => { - const code = mapMoodleWarningToErrorCode(warning) - const status = mapMoodleWarningToStatusCode(warning) - - return new MoodleOperationException(code, warning.message, status) -} - -const mapAssignmentFileSubmission = ( - from: RawMoodleAssignment, -): Maybe => { - const fileConfigs = from.configs.filter((c) => c.plugin === 'file') - - const isFileSubmissionEnabled = fileConfigs.find( - (c) => c.name === 'enabled' && Boolean(c.value), - ) - - if (!isFileSubmissionEnabled) { - return null - } - - const allowedFileTypesConfig = fileConfigs.find( - (c) => c.name === 'filetypeslist', - ) - const allowedFileTypes = allowedFileTypesConfig - ? allowedFileTypesConfig.value === '' - ? [] - : allowedFileTypesConfig.value.split(',') - : [] - - return { - maxFiles: Number( - fileConfigs.find((c) => c.name === 'maxfilesubmissions')?.value, - ), - maxSize: Number( - fileConfigs.find((c) => c.name === 'maxsubmissionsizebytes')?.value, - ), - allowedTypes: allowedFileTypes, - } -} - -const mapAssignmentAttachments = ( - from: RawMoodleAssignment, -): MoodleAssignmentAttachment[] => { - return from.introattachments.map((attachment) => ({ - name: attachment.filename, - url: attachment.fileurl, - size: attachment.filesize, - mimeType: attachment.mimetype, - })) -} - -const mapAssignmentIntro = (from: RawMoodleAssignment): string => { - if (from.introformat === 1) { - return NodeHtmlMarkdown.translate(from.intro) - } - - return from.intro -} - -const mapMoodleAssignment = (from: RawMoodleAssignment): MoodleAssignment => ({ - id: from.id, - name: from.name, - deadlineAt: from.duedate, - hardDeadlineAt: from.cutoffdate, - isSubmitRequired: Boolean(from.completionsubmit), - grade: from.grade, - reopenMethod: from.attemptreopenmethod, - intro: from.intro.trim() ? mapAssignmentIntro(from) : null, - fileSubmission: mapAssignmentFileSubmission(from), - attachments: mapAssignmentAttachments(from), -}) - -export { - byCourseNameAsc, - constructMoodleRequestParams, - ensureCourseIsActive, - getDefaultMoodleHeaders, - hasPrivateToken, - isAssignmentGrade, - isMoodleAuthTokenValid, - isMoodleErrorResponse, - isMoodleExceptionResponse, - mapMoodleCourse, - mapMoodleCourseGrades, - mapMoodleSiteInfo, - setMoodleTokenCookie, - throwMoodleApiException, - getMoodleCourseFinalGrade, - moodleWarningToException, - mapMoodleAssignment, -} diff --git a/src/modules/schedule/jobs/postman.ts b/src/modules/schedule/jobs/postman.ts deleted file mode 100644 index 5bedb2f..0000000 --- a/src/modules/schedule/jobs/postman.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { - HEALTH_CHECK_KEY, - HEALTH_STATUS, - IS_UPDATE_IN_PROGRESS_KEY, - LAST_UPDATE_KEY, - SCHEDULE_TYPE, - UPDATE_STATUS, -} from '@/core/constants/index.js' -import type { AppInstance } from '@/core/types/common.js' -import { delay } from '@/core/utils/index.js' -import { pingDiscordWebhook } from '../utils/discord.js' - -const CIST_DELAY_MS = 8_000 - -export const cistPostmanJob = async (app: AppInstance): Promise => { - const { - auditoriumsProcessor, - groupsProcessor, - teachersProcessor, - eventsProcessor, - logger, - cache, - config, - } = app.diContainer.cradle - - try { - await Promise.all([ - cache.set(HEALTH_CHECK_KEY, HEALTH_STATUS.UPDATING), - cache.set(IS_UPDATE_IN_PROGRESS_KEY, UPDATE_STATUS.IN_PROGRESS), - ]) - - logger.info('[Cist Postman]: Start CIST Postman') - - const [auditoriums, groups, teachers] = await Promise.all([ - auditoriumsProcessor.process(), - groupsProcessor.process(), - teachersProcessor.process(), - ]) - - if (!auditoriums || !groups || !teachers) { - return - } - - logger.info('[Cist Postman]: Start filling events') - - const totalGroups = groups.length - - for (let i = 0; i < groups.length; i++) { - logger.info( - `[Cist Postman]: Processing group ${i + 1}/${totalGroups} with id ${groups[i]!.id}`, - ) - - const group = groups[i]! - - await eventsProcessor.process(group.id, SCHEDULE_TYPE.GROUP) - await delay(CIST_DELAY_MS) - } - - await Promise.all([ - eventsProcessor.removeExtraEvents(), - cache.set(HEALTH_CHECK_KEY, HEALTH_STATUS.HEALTHY), - cache.set(IS_UPDATE_IN_PROGRESS_KEY, UPDATE_STATUS.FINISHED), - ]) - - logger.info('[Cist Postman] Job completed sucessfully') - } catch (e: unknown) { - await cache.set(HEALTH_CHECK_KEY, HEALTH_STATUS.FAILED) - - logger.error('[Cist Postman] Job failed') - logger.error(e) - - const errMessage = `:warning: **CIST Postman** job failed!\n\`\`\`${e instanceof Error ? e.message : 'Unknown error'}\`\`\`` - - await pingDiscordWebhook(config.integration.discordWebhookUrl, errMessage) - } finally { - await cache.set(LAST_UPDATE_KEY, new Date().toISOString()) - } -} diff --git a/src/modules/schedule/schemas/index.ts b/src/modules/schedule/schemas/index.ts deleted file mode 100644 index affc713..0000000 --- a/src/modules/schedule/schemas/index.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { eventTypeEnum } from '@/db/schema/event-type-enum.js' -import { GROUP_SCHEMA } from '@/modules/groups/schemas/index.js' -import { TEACHER_SCHEMA } from '@/modules/teachers/schemas/index.js' -import { z } from 'zod' -import { - transformEventTypesParam, - transformIdsParam, -} from '../utils/query-string.js' - -const SCHEDULE_SCHEMA = z.object({ - id: z.number().int().describe('Identifier of double period'), - startedAt: z - .number() - .describe('Unix timestamp when double period is starting'), - endedAt: z.number().describe('Unix timestamp when double period is ending'), - type: z.enum(eventTypeEnum.enumValues).describe('Type of an event'), - auditorium: z - .object({ - id: z.number().describe('Auditorium identifier'), - name: z - .string() - .describe('Name of an auditorium where double period is held'), - }) - .describe('Auditorium where double period is held'), - numberPair: z.number().int().min(1).describe('Number of pair'), - subject: z - .object({ - id: z.number().int().describe('Subject identifier'), - title: z.string().describe('Title of subject'), - brief: z.string().describe('Brief of subject'), - }) - .describe('Subject from which there will be a double period'), - groups: GROUP_SCHEMA.omit({ directionId: true, specialityId: true }) - .array() - .describe('List of groups which attend the class'), - teachers: TEACHER_SCHEMA.omit({ departmentId: true }) - .array() - .describe('List of teachers who teach the class'), - pairIndex: z - .number() - .int() - .min(1) - .describe('Index of the pair for the subject'), - pairsCount: z - .number() - .int() - .min(1) - .describe('Total number of pairs for the subject'), -}) - -const GET_SCHEDULE_PARAMS_SCHEMA = z.object({ - id: z.coerce.number().int().describe('Identifier of an entity'), -}) - -type GET_SCHEDULE_PARAMS = z.infer - -const GET_SCHEDULE_FILTERS_SCHEMA = z.object({ - lessonTypes: z - .string() - .nullable() - .default(null) - .transform(transformEventTypesParam), - teachers: z.string().nullable().default(null).transform(transformIdsParam), - auditoriums: z.string().nullable().default(null).transform(transformIdsParam), - subjects: z.string().nullable().default(null).transform(transformIdsParam), -}) - -type GET_SCHEDULE_FILTERS = z.infer - -const GET_SCHEDULE_TIME_INTERVAL_SCHEMA = z.object({ - startedAt: z.coerce - .number() - .min(0) - .refine((ts) => ts < 1e10, { - message: 'Should be a Unix timestamp in seconds', - }) - .nullable() - .default(null) - .describe('Start time of the schedule range'), - endedAt: z.coerce - .number() - .min(0) - .refine((ts) => ts < 1e10, { - message: 'Should be a Unix timestamp in seconds', - }) - .nullable() - .default(null) - .describe('End time of the schedule range'), -}) - -type GET_SCHEDULE_TIME_INTERVAL = z.infer< - typeof GET_SCHEDULE_TIME_INTERVAL_SCHEMA -> - -type GET_SCHEDULE_QUERY = GET_SCHEDULE_TIME_INTERVAL & { - filters: T -} - -type GET_SCHEDULE_OPTIONS = GET_SCHEDULE_PARAMS & - GET_SCHEDULE_QUERY - -export { - GET_SCHEDULE_FILTERS_SCHEMA, - GET_SCHEDULE_PARAMS_SCHEMA, - GET_SCHEDULE_TIME_INTERVAL_SCHEMA, - SCHEDULE_SCHEMA, -} -export type { - GET_SCHEDULE_FILTERS, - GET_SCHEDULE_OPTIONS, - GET_SCHEDULE_PARAMS, - GET_SCHEDULE_QUERY, - GET_SCHEDULE_TIME_INTERVAL, -} diff --git a/src/modules/schedule/utils/discord.ts b/src/modules/schedule/utils/discord.ts deleted file mode 100644 index 547d3b6..0000000 --- a/src/modules/schedule/utils/discord.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const pingDiscordWebhook = async ( - webhookUrl: string, - message: string, -): Promise => { - await fetch(webhookUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - content: message, - }), - }) -} diff --git a/src/modules/schedule/utils/index.ts b/src/modules/schedule/utils/index.ts deleted file mode 100644 index 3454536..0000000 --- a/src/modules/schedule/utils/index.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { sql, type SQL } from 'drizzle-orm' -import { - GET_SCHEDULE_TIME_INTERVAL_SCHEMA, - type GET_SCHEDULE_FILTERS, - type GET_SCHEDULE_TIME_INTERVAL, -} from '../schemas/index.js' -import type { ZodSchema } from 'zod' - -export const getTimeIntervalQuery = ({ - startedAt, - endedAt, -}: GET_SCHEDULE_TIME_INTERVAL): SQL[] => { - const clause: SQL[] = [] - - if (startedAt) { - clause.push(sql`and`, sql`e.started_at >= ${startedAt}`) - } - - if (endedAt) { - clause.push(sql`and`, sql`e.ended_at <= ${endedAt}`) - } - - return clause -} - -export const getFiltersQuery = (filters: GET_SCHEDULE_FILTERS): SQL[] => { - const clause: SQL[] = [] - const { auditoriums, lessonTypes, teachers, subjects } = filters - - if (auditoriums.length) { - clause.push(sql`and`, sql`a.id not in (${sql.join(auditoriums, sql`,`)} )`) - } - - if (lessonTypes.length) { - clause.push(sql`and`, sql`e.type not in (${sql.join(lessonTypes, sql`,`)})`) - } - - if (teachers.length) { - clause.push(sql`and`, sql`t2.id not in (${sql.join(teachers, sql`,`)})`) - } - - if (subjects.length) { - clause.push(sql`and`, sql`s.id not in (${sql.join(subjects, sql`,`)})`) - } - - return clause -} - -export const getScheduleQuerySchema = (filtersSchema: ZodSchema) => { - return GET_SCHEDULE_TIME_INTERVAL_SCHEMA.extend({ - filters: filtersSchema, - }) -} - -export const buildScheduleQuery = (whereClause: SQL[]): SQL => { - return sql` - select - e.id::int as id, - e.number_pair as "numberPair", - e.type as type, - json_build_object('id', a.id, 'name', a.name) as auditorium, - e.started_at as "startedAt", - e.ended_at as "endedAt", - jsonb_build_object('id', s.id, 'title', s.name, 'brief', s.brief) as subject, - array_agg(distinct jsonb_build_object('id', ag2.id, 'name', ag2.name)) as groups, - coalesce( - json_agg( - distinct jsonb_build_object( - 'id', t2.id, - 'shortName', t2.short_name, - 'fullName', t2.full_name - ) - ) filter (where t2.id is not null), - '[]'::json - ) as teachers, - row_number() over ( - partition by s.id, e.type, t1.id, ag1.id - order by e.started_at - )::int as "pairIndex", - count(*) over (partition by s.id, e.type, t1.id, ag1.id)::int as "pairsCount" - from - event e - join auditorium a on a.id = e.auditorium_id - join subject s on s.id = e.subject_id - join event_to_academic_group etag1 on etag1.event_id = e.id - join academic_group ag1 on ag1.id = etag1.groud_id - join event_to_academic_group etag2 on etag2.event_id = e.id - join academic_group ag2 on ag2.id = etag2.groud_id - left join event_to_teacher ett1 on ett1.event_id = e.id - left join teacher t1 on t1.id = ett1.teacher_id - left join event_to_teacher ett2 on ett2.event_id = e.id - left join teacher t2 on t2.id = ett2.teacher_id - where ${sql.join(whereClause, sql.raw(' '))} - group by - e.id, a.name, s.id, a.id, t1.id, ag1.id - order by - e.started_at; - ` -} diff --git a/src/modules/schedule/utils/query-string.ts b/src/modules/schedule/utils/query-string.ts deleted file mode 100644 index f5147d7..0000000 --- a/src/modules/schedule/utils/query-string.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { Maybe } from '@/core/types/index.js' -import { eventTypeEnum } from '@/db/schema/event-type-enum.js' - -export const queryParamToArray = (s: Maybe): string[] => { - return !s ? [] : s.includes(',') ? s.split(',') : [s] -} - -export const transformEventTypesParam = (s: Maybe): string[] => { - return queryParamToArray(s).filter((item) => { - // @ts-expect-error will be fixed soon - return eventTypeEnum.enumValues.includes(item) - }) -} - -export const transformIdsParam = (s: Maybe): number[] => { - return queryParamToArray(s).map(Number).filter(Number.isInteger) -} diff --git a/src/modules/teachers/handlers/index.ts b/src/modules/teachers/handlers/index.ts deleted file mode 100644 index f2b8795..0000000 --- a/src/modules/teachers/handlers/index.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { - type GET_SCHEDULE_PARAMS, - type GET_SCHEDULE_QUERY, -} from '@/modules/schedule/schemas/index.js' -import type { FastifyReply, FastifyRequest } from 'fastify' -import type { GET_TEACHER_SCHEDULE_FILTERS } from '../schemas/index.js' - -export const getTeachers = async ( - request: FastifyRequest, - reply: FastifyReply, -): Promise => { - const { teachersService } = request.diScope.cradle - - const data = await teachersService.getAll() - - return reply.status(200).send(data) -} - -export const getTeacherAuditoriums = async ( - request: FastifyRequest<{ - Params: GET_SCHEDULE_PARAMS - }>, - reply: FastifyReply, -): Promise => { - const { teachersService } = request.diScope.cradle - const { id } = request.params - - const data = await teachersService.getAuditoriums(id) - - return reply.status(200).send(data) -} - -export const getTeacherGroups = async ( - request: FastifyRequest<{ - Params: GET_SCHEDULE_PARAMS - }>, - reply: FastifyReply, -): Promise => { - const { teachersService } = request.diScope.cradle - const { id } = request.params - - const data = await teachersService.getGroups(id) - - return reply.status(200).send(data) -} - -export const getTeacherSubjects = async ( - request: FastifyRequest<{ - Params: GET_SCHEDULE_PARAMS - }>, - reply: FastifyReply, -): Promise => { - const { teachersService } = request.diScope.cradle - const { id } = request.params - - const data = await teachersService.getSubjects(id) - - return reply.status(200).send(data) -} - -export const getTeacherSchedule = async ( - request: FastifyRequest<{ - Params: GET_SCHEDULE_PARAMS - Querystring: GET_SCHEDULE_QUERY - }>, - reply: FastifyReply, -): Promise => { - const { teachersService } = request.diScope.cradle - const { id } = request.params - - const data = await teachersService.getSchedule({ id, ...request.query }) - - return reply.status(200).send(data) -} diff --git a/src/modules/teachers/index.ts b/src/modules/teachers/index.ts deleted file mode 100644 index 1092bb6..0000000 --- a/src/modules/teachers/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { asClass } from 'awilix' -import { TeachersParserImpl } from './parsers/TeachersParser.js' -import { TeachersProcessorImpl } from './processors/TeachersProcessor.js' -import type { TeachersDiConfig } from './types/index.js' -import { TeachersRepositoryImpl } from './repositories/TeachersRepository.js' -import { TeachersServiceImpl } from './services/TeachersService.js' - -export const resolveTeachersModule = (): TeachersDiConfig => ({ - teachersParser: asClass(TeachersParserImpl).singleton(), - teachersProcessor: asClass(TeachersProcessorImpl).singleton(), - teachersRepository: asClass(TeachersRepositoryImpl).singleton(), - teachersService: asClass(TeachersServiceImpl).singleton(), -}) diff --git a/src/modules/teachers/parsers/TeachersParser.ts b/src/modules/teachers/parsers/TeachersParser.ts deleted file mode 100644 index c6568f6..0000000 --- a/src/modules/teachers/parsers/TeachersParser.ts +++ /dev/null @@ -1,113 +0,0 @@ -import type { Department, Faculty, Teacher } from '@/db/types.js' -import type { Maybe } from '@/core/types/common.js' -import type { CommonDependencies } from '@/core/types/deps.js' -import type { - CistTeachersOutput, - CistTeachersRawJson, - RawDepartment, - RawTeacher, -} from '@/core/types/proxy.js' -import { fetchProxy } from '@/core/utils/proxy.js' -import type { CistParser } from '@/core/types/cist.js' - -export class TeachersParserImpl implements CistParser { - private readonly endpoint: string - private hashSet: Set - private teachers: Teacher[] - - constructor({ config }: CommonDependencies) { - const { baseUrl } = config.proxy - - this.endpoint = `${baseUrl}/lists/teachers` - this.hashSet = new Set() - this.teachers = [] - } - - async parse(): Promise> { - try { - const raw = await fetchProxy(this.endpoint) - - const faculties: Faculty[] = [] - const departments: Department[] = [] - - if (!Object.hasOwn(raw, 'university')) { - return null - } - - if (!Object.hasOwn(raw.university, 'faculties')) { - return null - } - - for (const faculty of raw.university.faculties) { - faculties.push({ - id: faculty.id, - fullName: faculty.full_name, - shortName: faculty.short_name, - }) - - if (!Object.hasOwn(faculty, 'departments')) { - continue - } - - for (const department of faculty.departments) { - departments.push({ - id: department.id, - fullName: department.full_name, - shortName: department.short_name, - facultyId: faculty.id, - }) - - this.processDepartment(department) - - if (Object.hasOwn(department, 'departments')) { - for (const subDepartment of department.departments) { - departments.push({ - id: subDepartment.id, - fullName: subDepartment.full_name, - shortName: subDepartment.short_name, - facultyId: faculty.id, - }) - - this.processDepartment(subDepartment) - } - } - } - } - - return { teachers: this.teachers, faculties, departments } - } catch (e) { - const message = e instanceof Error ? e.message : String(e) - - throw new Error( - `[TeachersParser] Failed to fetch or parse teachers data: ${message}`, - ) - } - } - - private processDepartment(department: RawDepartment) { - if (Object.hasOwn(department, 'teachers')) { - for (const teacher of department.teachers) { - this.addTeacher(teacher, department.id) - } - } - } - - private addTeacher(teacher: RawTeacher, departmentId: number) { - if (!teacher.full_name.length || !teacher.short_name.length) { - return - } - - if (this.hashSet.has(teacher.id)) { - return - } - - this.teachers.push({ - id: teacher.id, - shortName: teacher.short_name, - fullName: teacher.full_name, - departmentId, - }) - - this.hashSet.add(teacher.id) - } -} diff --git a/src/modules/teachers/processors/TeachersProcessor.ts b/src/modules/teachers/processors/TeachersProcessor.ts deleted file mode 100644 index d015ad9..0000000 --- a/src/modules/teachers/processors/TeachersProcessor.ts +++ /dev/null @@ -1,85 +0,0 @@ -import type { CistParser, CistProcessor } from '@/core/types/cist.js' -import type { DatabaseClient } from '@/core/types/deps.js' -import type { CistTeachersOutput } from '@/core/types/proxy.js' -import type { Teacher } from '@/db/types.js' -import type { Redis } from 'ioredis' -import type { TeachersInjectableDependencies } from '../types/index.js' -import { - departmentTable, - facultyTable, - teacherTable, -} from '@/db/schema/index.js' -import { RedisKeyBuilder } from '@/core/builders/RedisKeyBulder.js' - -export class TeachersProcessorImpl implements CistProcessor { - private readonly db: DatabaseClient - private readonly cache: Redis - private readonly parser: CistParser - - constructor({ db, cache, teachersParser }: TeachersInjectableDependencies) { - this.db = db.client - this.cache = cache - this.parser = teachersParser - } - - async process(): Promise { - try { - const data = await this.parser.parse() - - if (!data) { - return [] - } - - const { teachers, faculties, departments } = data - - for (const faculty of faculties) { - const key = RedisKeyBuilder.facultyKey(faculty.id) - - const isExist = await this.cache.get(key) - - if (isExist) { - continue - } - - await this.db.insert(facultyTable).values(faculty) - await this.cache.set(key, 'exists') - } - - for (const department of departments) { - const key = RedisKeyBuilder.departmentKey(department.id) - - const isExist = await this.cache.get(key) - - if (isExist) { - continue - } - - await this.db.insert(departmentTable).values(department) - this.cache.set(key, 'exists') - } - - for (const teacher of teachers) { - const key = RedisKeyBuilder.teacherKey(teacher.id) - - const isExist = await this.cache.get(key) - - if (isExist) { - continue - } - - await this.db.insert(teacherTable).values(teacher) - this.cache.set(key, 'exists') - } - - return teachers - } catch (e: unknown) { - if (e instanceof Error && e.message.includes('[TeachersParser]')) { - throw new Error(e.message) - } - - const message = `[TeachersProcessor] Failed to process data: ${e instanceof Error ? e.message : 'Unknown error'}` - - throw new Error(message) - } - } -} diff --git a/src/modules/teachers/repositories/TeachersRepository.ts b/src/modules/teachers/repositories/TeachersRepository.ts deleted file mode 100644 index 2a50c65..0000000 --- a/src/modules/teachers/repositories/TeachersRepository.ts +++ /dev/null @@ -1,121 +0,0 @@ -import type { DatabaseClient } from '@/core/types/deps.js' -import { - academicGroupTable, - auditoriumTable, - eventTable, - eventToAcademicGroupTable, - eventToTeacherTable, - subjectTable, -} from '@/db/schema/index.js' -import { teacherTable } from '@/db/schema/teacher.js' -import type { Group, Schedule, Subject, Teacher } from '@/db/types.js' -import type { GET_SCHEDULE_OPTIONS } from '@/modules/schedule/schemas/index.js' -import { - buildScheduleQuery, - getTimeIntervalQuery, -} from '@/modules/schedule/utils/index.js' -import { SQL, asc, eq, sql } from 'drizzle-orm' -import type { GET_TEACHER_SCHEDULE_FILTERS } from '../schemas/index.js' -import type { - TeachersInjectableDependencies, - TeachersRepository, -} from '../types/index.js' -import { getTeacherFiltersQuery } from '../utils/index.js' - -export class TeachersRepositoryImpl implements TeachersRepository { - private readonly db: DatabaseClient - - constructor({ db }: TeachersInjectableDependencies) { - this.db = db.client - } - - async findAll(): Promise { - return this.db - .select() - .from(teacherTable) - .orderBy(asc(teacherTable.shortName)) - } - - async getAuditoriums( - teacherId: number, - ): Promise[]> { - return this.db - .selectDistinct({ - id: auditoriumTable.id, - name: auditoriumTable.name, - }) - .from(eventTable) - .innerJoin( - eventToTeacherTable, - eq(eventTable.id, eventToTeacherTable.eventId), - ) - .innerJoin( - auditoriumTable, - eq(auditoriumTable.id, eventTable.auditoriumId), - ) - .where(eq(eventToTeacherTable.teacherId, teacherId)) - .orderBy(auditoriumTable.name) - } - - async getGroups(teacherId: number): Promise[]> { - return this.db - .selectDistinct({ - id: academicGroupTable.id, - name: academicGroupTable.name, - }) - .from(eventTable) - .innerJoin( - eventToTeacherTable, - eq(eventTable.id, eventToTeacherTable.eventId), - ) - .innerJoin( - eventToAcademicGroupTable, - eq(eventTable.id, eventToAcademicGroupTable.eventId), - ) - .innerJoin( - academicGroupTable, - eq(eventToAcademicGroupTable.groudId, academicGroupTable.id), - ) - .where(eq(eventToTeacherTable.teacherId, teacherId)) - .orderBy(academicGroupTable.name) - } - - async getSubjects(teacherId: number): Promise { - return this.db - .selectDistinct({ - id: subjectTable.id, - name: subjectTable.name, - brief: subjectTable.brief, - }) - .from(eventTable) - .innerJoin( - eventToTeacherTable, - eq(eventTable.id, eventToTeacherTable.eventId), - ) - .innerJoin(subjectTable, eq(eventTable.subjectId, subjectTable.id)) - .where(eq(eventToTeacherTable.teacherId, teacherId)) - .orderBy(subjectTable.brief) - } - - async getSchedule( - options: GET_SCHEDULE_OPTIONS, - ): Promise { - const { id } = options - - const whereClause: SQL[] = [sql`ett1.teacher_id = ${id}`] - - const timeInterval = getTimeIntervalQuery(options) - - whereClause.push(...timeInterval) - - const filters = getTeacherFiltersQuery(options.filters) - - whereClause.push(...filters) - - const query = buildScheduleQuery(whereClause) - - const schedule = await this.db.execute(query) - - return schedule as unknown as Schedule[] - } -} diff --git a/src/modules/teachers/routes/index.ts b/src/modules/teachers/routes/index.ts deleted file mode 100644 index 77046ee..0000000 --- a/src/modules/teachers/routes/index.ts +++ /dev/null @@ -1,107 +0,0 @@ -import type { Routes } from '@/core/types/routes.js' -import { generateSuccessResponseSchema } from '@/core/utils/schemas.js' -import { AUDITORIUM_SCHEMA } from '@/modules/auditoriums/schemas/index.js' -import { GROUP_SCHEMA, SUBJECT_SCHEMA } from '@/modules/groups/schemas/index.js' -import { - GET_SCHEDULE_PARAMS_SCHEMA, - SCHEDULE_SCHEMA, -} from '@/modules/schedule/schemas/index.js' -import { getScheduleQuerySchema } from '@/modules/schedule/utils/index.js' -import { - getTeacherAuditoriums, - getTeacherGroups, - getTeacherSchedule, - getTeacherSubjects, - getTeachers, -} from '../handlers/index.js' -import { - GET_TEACHER_SCHEDULE_FILTERS_SCHEMA, - TEACHER_SCHEMA, -} from '../schemas/index.js' - -export const getTeachersRoutes = (): Routes => ({ - routes: [ - { - method: 'GET', - url: '/teachers', - handler: getTeachers, - schema: { - summary: 'Get teachers', - description: 'Get list of teachers', - tags: ['Teachers'], - response: { - 200: generateSuccessResponseSchema(TEACHER_SCHEMA.array()).describe( - 'Successful response', - ), - }, - }, - }, - { - method: 'GET', - url: '/teachers/:id/auditoriums', - handler: getTeacherAuditoriums, - schema: { - summary: 'Get teacher auditoriums', - description: 'Get auditoriums for a specific teacher', - tags: ['Teachers'], - params: GET_SCHEDULE_PARAMS_SCHEMA, - response: { - 200: generateSuccessResponseSchema( - AUDITORIUM_SCHEMA.pick({ id: true, name: true }).array(), - ).describe('Successful response'), - }, - }, - }, - { - method: 'GET', - url: '/teachers/:id/groups', - handler: getTeacherGroups, - schema: { - summary: 'Get teacher groups', - description: 'Get groups for a specific teacher', - tags: ['Teachers'], - params: GET_SCHEDULE_PARAMS_SCHEMA, - response: { - 200: generateSuccessResponseSchema( - GROUP_SCHEMA.pick({ id: true, name: true }).array(), - ).describe('Successful response'), - }, - }, - }, - { - method: 'GET', - url: '/teachers/:id/subjects', - handler: getTeacherSubjects, - schema: { - summary: 'Get teacher subjects', - description: 'Get subjects for a specific teacher', - tags: ['Teachers'], - params: GET_SCHEDULE_PARAMS_SCHEMA, - response: { - 200: generateSuccessResponseSchema(SUBJECT_SCHEMA.array()).describe( - 'Successful response', - ), - }, - }, - }, - { - method: 'GET', - url: '/teachers/:id/schedule', - handler: getTeacherSchedule, - schema: { - summary: 'Get teacher schedule', - description: 'Get schedule for teacher in particular time interval', - tags: ['Teachers'], - params: GET_SCHEDULE_PARAMS_SCHEMA, - querystring: getScheduleQuerySchema( - GET_TEACHER_SCHEDULE_FILTERS_SCHEMA, - ), - response: { - 200: generateSuccessResponseSchema(SCHEDULE_SCHEMA.array()).describe( - 'Successful response', - ), - }, - }, - }, - ], -}) diff --git a/src/modules/teachers/schemas/index.ts b/src/modules/teachers/schemas/index.ts deleted file mode 100644 index d85de96..0000000 --- a/src/modules/teachers/schemas/index.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { - transformEventTypesParam, - transformIdsParam, -} from '@/modules/schedule/utils/query-string.js' -import { z } from 'zod' - -const TEACHER_SCHEMA = z.object({ - id: z.number().int().describe('Teacher identifier'), - fullName: z - .string() - .describe('Last name, first name, and patronymic of teacher'), - shortName: z.string().describe('Last name and initials of teacher'), - departmentId: z - .number() - .int() - .describe('Identifier of department teacher belongs to'), -}) - -const GET_TEACHER_SCHEDULE_FILTERS_SCHEMA = z - .object({ - lessonTypes: z - .string() - .nullable() - .default(null) - .transform(transformEventTypesParam) - .describe('Comma-separated list of lesson types. Example: "Лк,Пз"'), - groups: z - .string() - .nullable() - .default(null) - .transform(transformIdsParam) - .describe('Comma-separated list of group identifiers. Example: "1,2,3"'), - auditoriums: z - .string() - .nullable() - .default(null) - .transform(transformIdsParam) - .describe( - 'Comma-separated list of auditorium identifiers. Example: "101,102"', - ), - subjects: z - .string() - .nullable() - .default(null) - .transform(transformIdsParam) - .describe( - 'Comma-separated list of subject identifiers. Example: "1,2,3"', - ), - }) - .default({ - lessonTypes: [], - groups: [], - auditoriums: [], - subjects: [], - }) - -type GET_TEACHER_SCHEDULE_FILTERS = z.infer< - typeof GET_TEACHER_SCHEDULE_FILTERS_SCHEMA -> - -export { TEACHER_SCHEMA, GET_TEACHER_SCHEDULE_FILTERS_SCHEMA } -export type { GET_TEACHER_SCHEDULE_FILTERS } diff --git a/src/modules/teachers/services/TeachersService.ts b/src/modules/teachers/services/TeachersService.ts deleted file mode 100644 index d58098c..0000000 --- a/src/modules/teachers/services/TeachersService.ts +++ /dev/null @@ -1,68 +0,0 @@ -import type { BaseResponse } from '@/core/types/common.js' -import type { - TeachersInjectableDependencies, - TeachersRepository, - TeachersService, -} from '../types/index.js' -import type { - Auditorium, - Group, - Schedule, - Subject, - Teacher, -} from '@/db/types.js' -import type { GET_SCHEDULE_OPTIONS } from '@/modules/schedule/schemas/index.js' -import { successResponse } from '@/core/utils/response.js' -import type { GET_TEACHER_SCHEDULE_FILTERS } from '../schemas/index.js' - -export class TeachersServiceImpl implements TeachersService { - private readonly repository: TeachersRepository - - constructor({ teachersRepository }: TeachersInjectableDependencies) { - this.repository = teachersRepository - } - - async getAll(): Promise> { - const teachers = await this.repository.findAll() - - return successResponse(teachers, 'Teachers successfuly fetched') - } - - async getAuditoriums( - teacherId: number, - ): Promise[]>> { - const auditoriums = await this.repository.getAuditoriums(teacherId) - - const message = `Auditoriums for teacher with id ${teacherId} found successfully` - - return successResponse(auditoriums, message) - } - - async getGroups( - teacherId: number, - ): Promise[]>> { - const groups = await this.repository.getGroups(teacherId) - - const message = `Groups for teacher with id ${teacherId} found successfully` - - return successResponse(groups, message) - } - - async getSubjects(teacherId: number): Promise> { - const subjects = await this.repository.getSubjects(teacherId) - - const message = `Subjects for teacher with id ${teacherId} found successfully` - - return successResponse(subjects, message) - } - - async getSchedule( - options: GET_SCHEDULE_OPTIONS, - ): Promise> { - const schedule = await this.repository.getSchedule(options) - - const message = `Schedule for teacher with id ${options.id} found successfully` - - return successResponse(schedule, message) - } -} diff --git a/src/modules/teachers/types/index.ts b/src/modules/teachers/types/index.ts deleted file mode 100644 index 0c490a4..0000000 --- a/src/modules/teachers/types/index.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { CistParser, CistProcessor } from '@/core/types/cist.js' -import type { BaseResponse } from '@/core/types/common.js' -import type { BaseDiConfig, InjectableDependencies } from '@/core/types/deps.js' -import type { CistTeachersOutput } from '@/core/types/proxy.js' -import type { Schedulable } from '@/core/types/services.js' -import type { - Auditorium, - Group, - Schedule, - Subject, - Teacher, -} from '@/db/types.js' -import type { GET_TEACHER_SCHEDULE_FILTERS } from '../schemas/index.js' - -interface TeachersRepository extends Schedulable { - findAll: () => Promise - getSubjects: (teacherId: number) => Promise - getGroups: (teacherId: number) => Promise[]> - getAuditoriums: ( - teacherId: number, - ) => Promise[]> -} - -interface TeachersService - extends Schedulable> { - getAll: () => Promise> - getAuditoriums: ( - teacherId: number, - ) => Promise[]>> - getGroups: ( - teacherId: number, - ) => Promise[]>> - getSubjects: (teacherId: number) => Promise> -} - -interface TeachersModuleDependencies { - teachersParser: CistParser - teachersProcessor: CistProcessor - teachersRepository: TeachersRepository - teachersService: TeachersService -} - -type TeachersInjectableDependencies = - InjectableDependencies - -type TeachersDiConfig = BaseDiConfig - -export type { - TeachersDiConfig, - TeachersInjectableDependencies, - TeachersModuleDependencies, - TeachersRepository, - TeachersService, -} diff --git a/src/modules/teachers/utils/index.ts b/src/modules/teachers/utils/index.ts deleted file mode 100644 index 6baf728..0000000 --- a/src/modules/teachers/utils/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { sql, type SQL } from 'drizzle-orm' -import type { GET_TEACHER_SCHEDULE_FILTERS } from '../schemas/index.js' - -export const getTeacherFiltersQuery = ( - filters: GET_TEACHER_SCHEDULE_FILTERS, -): SQL[] => { - const clause: SQL[] = [] - const { auditoriums, lessonTypes, groups, subjects } = filters - - if (auditoriums.length) { - clause.push(sql`and`, sql`a.id in (${sql.join(auditoriums, sql`,`)})`) - } - - if (lessonTypes.length) { - clause.push(sql`and`, sql`e.type in (${sql.join(lessonTypes, sql`,`)})`) - } - - if (groups.length) { - clause.push(sql`and`, sql`ag1.id in (${sql.join(groups, sql`,`)})`) - } - - if (subjects.length) { - clause.push(sql`and`, sql`s.id in (${sql.join(subjects, sql`,`)})`) - } - - return clause -} diff --git a/test/app.e2e-spec.ts b/test/app.e2e-spec.ts new file mode 100644 index 0000000..9fb2f7a --- /dev/null +++ b/test/app.e2e-spec.ts @@ -0,0 +1,25 @@ +import { Test, TestingModule } from '@nestjs/testing' +import { INestApplication } from '@nestjs/common' +import request from 'supertest' +import { App } from 'supertest/types' +import { AppModule } from '../src/app.module' + +describe('AppController (e2e)', () => { + let app: INestApplication + + beforeEach(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + imports: [AppModule], + }).compile() + + app = moduleFixture.createNestApplication() + await app.init() + }) + + it('/ (GET)', () => { + return request(app.getHttpServer()) + .get('/') + .expect(200) + .expect('Hello World!') + }) +}) diff --git a/test/jest-e2e.json b/test/jest-e2e.json new file mode 100644 index 0000000..f43e8a6 --- /dev/null +++ b/test/jest-e2e.json @@ -0,0 +1,9 @@ +{ + "moduleFileExtensions": ["js", "json", "ts"], + "rootDir": ".", + "testEnvironment": "node", + "testRegex": ".e2e-spec.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + } +} diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 0000000..54e3f6e --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist", "**/*spec.ts", "legacy"] +} diff --git a/tsconfig.json b/tsconfig.json index c0fcb21..192e324 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,26 +1,26 @@ { "compilerOptions": { + "module": "nodenext", + "moduleResolution": "nodenext", + "resolvePackageJsonExports": true, "esModuleInterop": true, - "skipLibCheck": true, - "target": "es2022", - "allowJs": true, - "resolveJsonModule": true, - "moduleDetection": "force", "isolatedModules": true, - "verbatimModuleSyntax": true, - "strict": true, - "noUncheckedIndexedAccess": true, - "noImplicitOverride": true, - "module": "NodeNext", - "outDir": "dist", - "rootDir": "src", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "ES2023", "sourceMap": true, - "baseUrl": ".", - "paths": { - "@/*": ["./src/*"] - }, - "lib": ["ESNext.Array", "ESNext"] + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": true, + "forceConsistentCasingInFileNames": true, + "noImplicitAny": false, + "strictBindCallApply": false, + "noFallthroughCasesInSwitch": false }, - "include": ["src"], - "exclude": ["opensrc"] + "exclude": ["legacy"] } diff --git a/vitest.config.e2e.ts b/vitest.config.e2e.ts new file mode 100644 index 0000000..b570a1f --- /dev/null +++ b/vitest.config.e2e.ts @@ -0,0 +1,21 @@ +import swc from 'unplugin-swc' +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + include: ['**/*.e2e-spec.ts'], + globals: true, + alias: { + src: './src', + test: './test', + }, + root: './', + }, + resolve: { + alias: { + src: './src', + test: './test', + }, + }, + plugins: [swc.vite()], +}) diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..ba26f78 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,20 @@ +import swc from 'unplugin-swc' +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + globals: true, + alias: { + src: './src', + test: './test', + }, + root: './', + }, + resolve: { + alias: { + src: './src', + test: './test', + }, + }, + plugins: [swc.vite()], +})