diff --git a/.github/workflows/build-and-push.yml b/.github/workflows/build-and-push.yml index 32a83c4..092cdf1 100644 --- a/.github/workflows/build-and-push.yml +++ b/.github/workflows/build-and-push.yml @@ -30,18 +30,20 @@ jobs: strategy: matrix: image: - - name: 'Main Image' + - name: 'Core Latest' tags: | remnawave/node:latest remnawave/node:${{github.ref_name}} ghcr.io/remnawave/node:latest ghcr.io/remnawave/node:${{github.ref_name}} build_args: '' - - name: 'SNI Image' + - name: 'Core v25.6.8' tags: | - remnawave/node:sni-latest - remnawave/node:sni-${{github.ref_name}} - build_args: 'UPSTREAM_REPO=kastov' + remnawave/node:xray-v25.6.8-latest + remnawave/node:xray-v25.6.8-${{github.ref_name}} + ghcr.io/remnawave/node:xray-v25.6.8-latest + ghcr.io/remnawave/node:xray-v25.6.8-${{github.ref_name}} + build_args: 'XRAY_CORE_VERSION=v25.6.8' steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index e89ab44..20f97f9 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -29,18 +29,10 @@ jobs: strategy: matrix: image: - - name: 'Main Image' + - name: 'Dev Image' tag: 'remnawave/node:dev' dockerfile: 'Dockerfile' build_args: '' - - name: 'SNI Image' - tag: 'remnawave/node:sni-dev' - dockerfile: 'Dockerfile' - build_args: 'UPSTREAM_REPO=kastov' - - name: 'Bun Image' - tag: 'remnawave/node:bun-dev' - dockerfile: 'Dockerfile.Bun' - build_args: '' steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.old.eslintrc.js b/.old.eslintrc.js deleted file mode 100644 index 909091e..0000000 --- a/.old.eslintrc.js +++ /dev/null @@ -1,85 +0,0 @@ -module.exports = { - parser: '@typescript-eslint/parser', - parserOptions: { - project: 'tsconfig.json', - tsconfigRootDir: __dirname, - sourceType: 'commonjs', - }, - plugins: ['@typescript-eslint/eslint-plugin', 'eslint-plugin-paths'], - extends: [ - 'plugin:@typescript-eslint/recommended', - 'plugin:perfectionist/recommended-natural-legacy', - 'plugin:prettier/recommended', - ], - root: true, - env: { - node: true, - jest: true, - }, - ignorePatterns: ['.eslintrc.js', 'prisma/**'], - rules: { - 'perfectionist/sort-imports': [ - 'error', - { - type: 'line-length', - order: 'desc', - ignoreCase: true, - specialCharacters: 'keep', - internalPattern: ['^~/.+'], - tsconfigRootDir: '.', - partitionByComment: false, - partitionByNewLine: false, - newlinesBetween: 'always', - maxLineLength: undefined, - groups: [ - 'type', - ['builtin', 'external'], - 'internal-type', - 'internal', - ['parent-type', 'sibling-type', 'index-type'], - ['parent', 'sibling', 'index'], - 'object', - 'unknown', - ], - customGroups: { type: {}, value: {} }, - environment: 'node', - }, - ], - 'perfectionist/sort-objects': ['off'], - 'perfectionist/sort-objects-types': ['off'], - 'perfectionist/sort-classes': ['off'], - 'perfectionist/sort-switch-case': ['off'], - 'paths/alias': 'error', - '@typescript-eslint/interface-name-prefix': 'off', - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-namespace': 'off', - 'linebreak-style': 0, - 'no-console': 'warn', - 'prettier/prettier': [ - 'error', - { - bracketSpacing: true, - tabWidth: 4, - printWidth: 100, - singleQuote: true, - trailingComma: 'all', - overrides: [ - { - files: ['*.js', '*.jsx', '*.ts', '*.tsx'], - options: { - parser: 'typescript', - }, - }, - { - files: ['*.md', '*.json', '*.yaml', '*.yml'], - options: { - tabWidth: 2, - }, - }, - ], - }, - ], - }, -}; diff --git a/Dockerfile b/Dockerfile index 544c9da..817f5d4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,6 +16,13 @@ RUN mkdir -p /var/log/supervisor WORKDIR /opt/app COPY --from=build /opt/app/dist ./dist +RUN echo '#!/bin/bash' > /usr/local/bin/xlogs \ + && echo 'tail -n +1 -f /var/log/supervisor/xray.out.log' >> /usr/local/bin/xlogs \ + && chmod +x /usr/local/bin/xlogs + +RUN echo '#!/bin/bash' > /usr/local/bin/xerrors \ + && echo 'tail -n +1 -f /var/log/supervisor/xray.err.log' >> /usr/local/bin/xerrors \ + && chmod +x /usr/local/bin/xerrors RUN apk add --no-cache \ curl \ diff --git a/Dockerfile.Bun b/bun.Dockerfile similarity index 100% rename from Dockerfile.Bun rename to bun.Dockerfile diff --git a/Dockerfile.dev b/dev.Dockerfile similarity index 100% rename from Dockerfile.dev rename to dev.Dockerfile diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index cbba487..d8df348 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -2,7 +2,7 @@ services: remnawave-node-dev: build: context: . - dockerfile: Dockerfile.dev + dockerfile: dev.Dockerfile container_name: remnawave-node-dev hostname: remnawave-node-dev networks: diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 38b3657..11b5c95 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,8 +1,13 @@ #!/bin/sh -echo "Starting entrypoint script..." +echo "[Entrypoint] Starting entrypoint script..." supervisord -c /etc/supervisord.conf & -echo "Supervisord started" +echo "[Entrypoint] Supervisord started successfully" sleep 1 -echo "Executing: $@" +echo "[Entrypoint] Getting Xray version..." +XRAY_CORE_VERSION=$(/usr/local/bin/xray version | head -n 1) +export XRAY_CORE_VERSION +echo "[Entrypoint] Xray version: $XRAY_CORE_VERSION" + +echo "[Entrypoint] Executing command: $@" exec "$@" \ No newline at end of file diff --git a/libs/contract/constants/headers/headers.contants.ts b/libs/contract/constants/headers/headers.contants.ts index 5401533..f3dc62f 100644 --- a/libs/contract/constants/headers/headers.contants.ts +++ b/libs/contract/constants/headers/headers.contants.ts @@ -1 +1,2 @@ export const X_HASH_PAYLOAD = 'X-Hash-Payload'; +export const X_FORCE_RESTART = 'X-Force-Restart'; diff --git a/libs/contract/package.json b/libs/contract/package.json index 96a5713..60a99e8 100644 --- a/libs/contract/package.json +++ b/libs/contract/package.json @@ -1,6 +1,6 @@ { "name": "@remnawave/node-contract", - "version": "0.5.8", + "version": "0.5.9", "description": "A node-contract library for Remnawave Panel", "main": "build/index.js", "types": "build/index.d.ts", diff --git a/package-lock.json b/package-lock.json index d5d1322..7938fd5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@remnawave/node", - "version": "2.1.3", + "version": "2.1.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@remnawave/node", - "version": "2.1.3", + "version": "2.1.4", "license": "AGPL-3.0-only", "dependencies": { - "@cjs-exporter/execa": "9.5.2", + "@henrygd/semaphore": "^0.0.2", "@nestjs/common": "11.1.6", "@nestjs/config": "4.0.2", "@nestjs/core": "11.1.6", @@ -25,53 +25,48 @@ "helmet": "^8.1.0", "husky": "9.1.7", "morgan": "^1.10.1", - "nanoid": "^5.1.5", "nest-winston": "^1.10.2", "nestjs-zod": "4.3.1", - "node-object-hash": "^3.1.1", "node-supervisord": "^1.0.6-rc.2", "object-hash": "^3.0.0", + "p-map": "^7.0.3", "p-retry": "^6.2.1", "passport": "0.7.0", "passport-jwt": "4.0.1", - "pkg-types": "^2.1.0", + "pkg-types": "^2.3.0", "pretty-bytes": "^6.1.1", "reflect-metadata": "0.2.2", "rxjs": "7.8.2", - "selfsigned": "^2.4.1", - "semver": "^7.7.1", - "systeminformation": "^5.25.11", + "semver": "^7.7.2", + "systeminformation": "^5.27.7", "table": "^6.9.0", "winston": "^3.17.0", - "zod": "^3.24.2" + "zod": "3.25.76" }, "devDependencies": { "@nestjs/cli": "11.0.10", "@nestjs/schematics": "11.0.7", "@types/compression": "^1.8.1", "@types/express": "^5.0.3", - "@types/js-yaml": "^4.0.9", - "@types/jsonwebtoken": "^9.0.10", - "@types/mjml": "^4.7.4", "@types/morgan": "^1.9.10", - "@types/node": "^22.13.14", - "@types/nunjucks": "^3.2.6", + "@types/node": "^22.17.2", "@types/object-hash": "^3.0.6", "@types/passport-jwt": "^4.0.1", "@types/semver": "^7.7.0", - "@typescript-eslint/eslint-plugin": "8.28.0", - "@typescript-eslint/parser": "8.28.0", - "eslint": "9.23.0", - "eslint-config-prettier": "^10.1.1", + "@typescript-eslint/eslint-plugin": "8.40.0", + "@typescript-eslint/parser": "8.40.0", + "eslint": "9.33.0", + "eslint-config-prettier": "^10.1.8", "eslint-plugin-paths": "^1.1.0", - "eslint-plugin-perfectionist": "^4.10.1", - "eslint-plugin-prettier": "^5.2.5", - "prettier": "^3.5.3", + "eslint-plugin-perfectionist": "^4.15.0", + "eslint-plugin-prettier": "^5.5.4", + "knip": "^5.62.0", + "prettier": "^3.6.2", "source-map-support": "^0.5.21", "ts-loader": "9.5.2", "ts-node": "10.9.2", "tsconfig-paths": "^4.2.0", - "typescript": "~5.8.2" + "typescript": "^5.9.2" } }, "node_modules/@angular-devkit/core": { @@ -225,15 +220,6 @@ "integrity": "sha512-tFQoXHJdkEOSwj5tRIZSPNUuXK3RaR7T1nUrPgbYX1pUbvqqaaZAsfo+NXBPsz5rZMSKVFrgK1WL8Q/MSLvprg==", "license": "(Apache-2.0 AND BSD-3-Clause)" }, - "node_modules/@cjs-exporter/execa": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/@cjs-exporter/execa/-/execa-9.5.2.tgz", - "integrity": "sha512-DyC+vBKD1GUjLr9/t7gKQlXsX+8fah9EX9xdA/RKJywDi9yqZvAWJFKx95tDYp0vzAmkrkwI84BNUkUsHO1YJA==", - "license": "MIT", - "dependencies": { - "execa": "9.5.2" - } - }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -269,10 +255,44 @@ "kuler": "^2.0.0" } }, + "node_modules/@emnapi/core": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz", + "integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.4", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", + "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz", + "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, "license": "MIT", "dependencies": { @@ -299,9 +319,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", - "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -314,9 +334,9 @@ } }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -338,9 +358,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.0.tgz", - "integrity": "sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -348,9 +368,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", - "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -402,9 +422,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -433,13 +453,16 @@ } }, "node_modules/@eslint/js": { - "version": "9.23.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz", - "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==", + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.33.0.tgz", + "integrity": "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==", "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { @@ -453,13 +476,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", - "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.12.0", + "@eslint/core": "^0.15.2", "levn": "^0.4.1" }, "engines": { @@ -497,6 +520,12 @@ "node": ">=6" } }, + "node_modules/@henrygd/semaphore": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@henrygd/semaphore/-/semaphore-0.0.2.tgz", + "integrity": "sha512-N3W7MKwTRmAxOjeG0NAT18oe2Xn3KdjkpMR6crbkF1UDamMGPjyigqEsefiv+qTaxibtc1a+zXCVzb9YXANVqw==", + "license": "MIT" + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -639,15 +668,15 @@ } }, "node_modules/@inquirer/editor": { - "version": "4.2.15", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.15.tgz", - "integrity": "sha512-wst31XT8DnGOSS4nNJDIklGKnf+8shuauVrWzgKegWUe28zfCftcWZ2vktGdzJgcylWSS2SrDnYUb6alZcwnCQ==", + "version": "4.2.17", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.17.tgz", + "integrity": "sha512-r6bQLsyPSzbWrZZ9ufoWL+CztkSatnJ6uSxqd6N+o41EZC51sQeWOzI6s5jLb+xxTWxl7PlUppqm8/sow241gg==", "dev": true, "license": "MIT", "dependencies": { "@inquirer/core": "^10.1.15", - "@inquirer/type": "^3.0.8", - "external-editor": "^3.1.0" + "@inquirer/external-editor": "^1.0.1", + "@inquirer/type": "^3.0.8" }, "engines": { "node": ">=18" @@ -684,6 +713,28 @@ } } }, + "node_modules/@inquirer/external-editor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.1.tgz", + "integrity": "sha512-Oau4yL24d2B5IL4ma4UpbQigkVhzPDXLoqy1ggK4gnHg/stmkffJE4oOXHXF3uz0UEpywG68KcyXsyYpA1Re/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^2.1.0", + "iconv-lite": "^0.6.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, "node_modules/@inquirer/figures": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.13.tgz", @@ -1098,6 +1149,19 @@ "node": ">=8" } }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.3.tgz", + "integrity": "sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.5", + "@emnapi/runtime": "^1.4.5", + "@tybys/wasm-util": "^0.10.0" + } + }, "node_modules/@nest-zod/z": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@nest-zod/z/-/z-2.0.0.tgz", @@ -1170,6 +1234,20 @@ } } }, + "node_modules/@nestjs/cli/node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@nestjs/common": { "version": "11.1.6", "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.6.tgz", @@ -1381,17 +1459,286 @@ "npm": ">=5.10.0" } }, + "node_modules/@oxc-resolver/binding-android-arm-eabi": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.6.1.tgz", + "integrity": "sha512-Ma/kg29QJX1Jzelv0Q/j2iFuUad1WnjgPjpThvjqPjpOyLjCUaiFCCnshhmWjyS51Ki1Iol3fjf1qAzObf8GIA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@oxc-resolver/binding-android-arm64": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.6.1.tgz", + "integrity": "sha512-xjL/FKKc5p8JkFWiH7pJWSzsewif3fRf1rw2qiRxRvq1uIa6l7Zoa14Zq2TNWEsqDjdeOrlJtfWiPNRnevK0oQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@oxc-resolver/binding-darwin-arm64": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.6.1.tgz", + "integrity": "sha512-u0yrJ3NHE0zyCjiYpIyz4Vmov21MA0yFKbhHgixDU/G6R6nvC8ZpuSFql3+7C8ttAK9p8WpqOGweepfcilH5Bw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxc-resolver/binding-darwin-x64": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.6.1.tgz", + "integrity": "sha512-2lox165h1EhzxcC8edUy0znXC/hnAbUPaMpYKVlzLpB2AoYmgU4/pmofFApj+axm2FXpNamjcppld8EoHo06rw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxc-resolver/binding-freebsd-x64": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.6.1.tgz", + "integrity": "sha512-F45MhEQ7QbHfsvZtVNuA/9obu3il7QhpXYmCMfxn7Zt9nfAOw4pQ8hlS5DroHVp3rW35u9F7x0sixk/QEAi3qQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm-gnueabihf": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.6.1.tgz", + "integrity": "sha512-r+3+MTTl0tD4NoWbfTIItAxJvuyIU7V0fwPDXrv7Uj64vZ3OYaiyV+lVaeU89Bk/FUUQxeUpWBwdKNKHjyRNQw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm-musleabihf": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.6.1.tgz", + "integrity": "sha512-TBTZ63otsWZ72Z8ZNK2JVS0HW1w9zgOixJTFDNrYPUUW1pXGa28KAjQ1yGawj242WLAdu3lwdNIWtkxeO2BLxQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm64-gnu": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.6.1.tgz", + "integrity": "sha512-SjwhNynjSG2yMdyA0f7wz7Yvo3ppejO+ET7n2oiI7ApCXrwxMzeRWjBzQt+oVWr2HzVOfaEcDS9rMtnR83ulig==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm64-musl": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.6.1.tgz", + "integrity": "sha512-f4EMidK6rosInBzPMnJ0Ri4RttFCvvLNUNDFUBtELW/MFkBwPTDlvbsmW0u0Mk/ruBQ2WmRfOZ6tT62kWMcX2Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-ppc64-gnu": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.6.1.tgz", + "integrity": "sha512-1umENVKeUsrWnf5IlF/6SM7DCv8G6CoKI2LnYR6qhZuLYDPS4PBZ0Jow3UDV9Rtbv5KRPcA3/uXjI88ntWIcOQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-riscv64-gnu": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.6.1.tgz", + "integrity": "sha512-Hjyp1FRdJhsEpIxsZq5VcDuFc8abC0Bgy8DWEa31trCKoTz7JqA7x3E2dkFbrAKsEFmZZ0NvuG5Ip3oIRARhow==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-riscv64-musl": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.6.1.tgz", + "integrity": "sha512-ODJOJng6f3QxpAXhLel3kyWs8rPsJeo9XIZHzA7p//e+5kLMDU7bTVk4eZnUHuxsqsB8MEvPCicJkKCEuur5Ag==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-s390x-gnu": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.6.1.tgz", + "integrity": "sha512-hCzRiLhqe1ZOpHTsTGKp7gnMJRORlbCthawBueer2u22RVAka74pV/+4pP1tqM07mSlQn7VATuWaDw9gCl+cVg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-x64-gnu": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.6.1.tgz", + "integrity": "sha512-JansPD8ftOzMYIC3NfXJ68tt63LEcIAx44Blx6BAd7eY880KX7A0KN3hluCrelCz5aQkPaD95g8HBiJmKaEi2w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-x64-musl": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.6.1.tgz", + "integrity": "sha512-R78ES1rd4z2x5NrFPtSWb/ViR1B8wdl+QN2X8DdtoYcqZE/4tvWtn9ZTCXMEzUp23tchJ2wUB+p6hXoonkyLpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-wasm32-wasi": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.6.1.tgz", + "integrity": "sha512-qAR3tYIf3afkij/XYunZtlz3OH2Y4ni10etmCFIJB5VRGsqJyI6Hl+2dXHHGJNwbwjXjSEH/KWJBpVroF3TxBw==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.0.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-resolver/binding-win32-arm64-msvc": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.6.1.tgz", + "integrity": "sha512-QqygWygIuemGkaBA48POOTeinbVvlamqh6ucm8arGDGz/mB5O00gXWxed12/uVrYEjeqbMkla/CuL3fjL3EKvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@oxc-resolver/binding-win32-ia32-msvc": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-11.6.1.tgz", + "integrity": "sha512-N2+kkWwt/bk0JTCxhPuK8t8JMp3nd0n2OhwOkU8KO4a7roAJEa4K1SZVjMv5CqUIr5sx2CxtXRBoFDiORX5oBg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@oxc-resolver/binding-win32-x64-msvc": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.6.1.tgz", + "integrity": "sha512-DfMg3cU9bJUbN62Prbp4fGCtLgexuwyEaQGtZAp8xmi1Ii26uflOGx0FJkFTF6lVMSFoIRFvIL8gsw5/ZdHrMw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@pkgr/core": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.0.tgz", - "integrity": "sha512-vsJDAkYR6qCPu+ioGScGiMYR7LvZYIXh/dlQeviqoTWNCVfKTLYD/LkNWH4Mxsv2a5vpIRc77FN5DnmK1eBggQ==", + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", "dev": true, "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/pkgr" } }, "node_modules/@protobufjs/aspromise": { @@ -1513,24 +1860,6 @@ "node": ">= 10" } }, - "node_modules/@sec-ant/readable-stream": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", - "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", - "license": "MIT" - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", - "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@tokenizer/inflate": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", @@ -1583,6 +1912,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", + "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/body-parser": { "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", @@ -1676,13 +2016,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/js-yaml": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1708,23 +2041,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/mjml": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/@types/mjml/-/mjml-4.7.4.tgz", - "integrity": "sha512-vyi1vzWgMzFMwZY7GSZYX0GU0dmtC8vLHwpgk+NWmwbwRSrlieVyJ9sn5elodwUfklJM7yGl0zQeet1brKTWaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mjml-core": "*" - } - }, - "node_modules/@types/mjml-core": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/@types/mjml-core/-/mjml-core-4.15.1.tgz", - "integrity": "sha512-qu8dUksU8yXX18qMTFINkM4uoz7WQYC5F14lcWeSNmWbulaGG0KG19yeZwpx75b9RJXr8WI/FRHH0LyQTU9JbA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/morgan": { "version": "1.9.10", "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.10.tgz", @@ -1743,30 +2059,14 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.13.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.14.tgz", - "integrity": "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==", + "version": "22.17.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.17.2.tgz", + "integrity": "sha512-gL6z5N9Jm9mhY+U2KXZpteb+09zyffliRkZyZOHODGATyC5B1Jt/7TzuuiLkFsSUMLbS1OLmlj/E+/3KF4Q/4w==", "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", - "license": "MIT", - "dependencies": { - "@types/node": "*" + "undici-types": "~6.21.0" } }, - "node_modules/@types/nunjucks": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@types/nunjucks/-/nunjucks-3.2.6.tgz", - "integrity": "sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/object-hash": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/@types/object-hash/-/object-hash-3.0.6.tgz", @@ -1863,21 +2163,21 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.28.0.tgz", - "integrity": "sha512-lvFK3TCGAHsItNdWZ/1FkvpzCxTHUVuFrdnOGLMa0GGCFIbCgQWVk3CzCGdA7kM3qGVc+dfW9tr0Z/sHnGDFyg==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz", + "integrity": "sha512-w/EboPlBwnmOBtRbiOvzjD+wdiZdgFeo17lkltrtn7X37vagKKWJABvyfsJXTlHe6XBzugmYgd4A4nW+k8Mixw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.28.0", - "@typescript-eslint/type-utils": "8.28.0", - "@typescript-eslint/utils": "8.28.0", - "@typescript-eslint/visitor-keys": "8.28.0", + "@typescript-eslint/scope-manager": "8.40.0", + "@typescript-eslint/type-utils": "8.40.0", + "@typescript-eslint/utils": "8.40.0", + "@typescript-eslint/visitor-keys": "8.40.0", "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1887,22 +2187,32 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "@typescript-eslint/parser": "^8.40.0", "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.28.0.tgz", - "integrity": "sha512-LPcw1yHD3ToaDEoljFEfQ9j2xShY367h7FZ1sq5NJT9I3yj4LHer1Xd1yRSOdYy9BpsrxU7R+eoDokChYM53lQ==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.40.0.tgz", + "integrity": "sha512-jCNyAuXx8dr5KJMkecGmZ8KI61KBUhkCob+SD+C+I5+Y1FWI2Y3QmY4/cxMCC5WAsZqoEtEETVhUiUMIGCf6Bw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.28.0", - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/typescript-estree": "8.28.0", - "@typescript-eslint/visitor-keys": "8.28.0", + "@typescript-eslint/scope-manager": "8.40.0", + "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/typescript-estree": "8.40.0", + "@typescript-eslint/visitor-keys": "8.40.0", "debug": "^4.3.4" }, "engines": { @@ -1914,18 +2224,40 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.40.0.tgz", + "integrity": "sha512-/A89vz7Wf5DEXsGVvcGdYKbVM9F7DyFXj52lNYUDS1L9yJfqjW/fIp5PgMuEJL/KeqVTe2QSbXAGUZljDUpArw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.40.0", + "@typescript-eslint/types": "^8.40.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.28.0.tgz", - "integrity": "sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.40.0.tgz", + "integrity": "sha512-y9ObStCcdCiZKzwqsE8CcpyuVMwRouJbbSrNuThDpv16dFAj429IkM6LNb1dZ2m7hK5fHyzNcErZf7CEeKXR4w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/visitor-keys": "8.28.0" + "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/visitor-keys": "8.40.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1935,17 +2267,35 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.40.0.tgz", + "integrity": "sha512-jtMytmUaG9d/9kqSl/W3E3xaWESo4hFDxAIHGVW/WKKtQhesnRIJSAJO6XckluuJ6KDB5woD1EiqknriCtAmcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.28.0.tgz", - "integrity": "sha512-oRoXu2v0Rsy/VoOGhtWrOKDiIehvI+YNrDk5Oqj40Mwm0Yt01FC/Q7nFqg088d3yAsR1ZcZFVfPCTTFCe/KPwg==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.40.0.tgz", + "integrity": "sha512-eE60cK4KzAc6ZrzlJnflXdrMqOBaugeukWICO2rB0KNvwdIMaEaYiywwHMzA1qFpTxrLhN9Lp4E/00EgWcD3Ow==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.28.0", - "@typescript-eslint/utils": "8.28.0", + "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/typescript-estree": "8.40.0", + "@typescript-eslint/utils": "8.40.0", "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1956,13 +2306,13 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.28.0.tgz", - "integrity": "sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.40.0.tgz", + "integrity": "sha512-ETdbFlgbAmXHyFPwqUIYrfc12ArvpBhEVgGAxVYSwli26dn8Ko+lIo4Su9vI9ykTZdJn+vJprs/0eZU0YMAEQg==", "dev": true, "license": "MIT", "engines": { @@ -1974,20 +2324,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.28.0.tgz", - "integrity": "sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.40.0.tgz", + "integrity": "sha512-k1z9+GJReVVOkc1WfVKs1vBrR5MIKKbdAjDTPvIK3L8De6KbFfPFt6BKpdkdk7rZS2GtC/m6yI5MYX+UsuvVYQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/visitor-keys": "8.28.0", + "@typescript-eslint/project-service": "8.40.0", + "@typescript-eslint/tsconfig-utils": "8.40.0", + "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/visitor-keys": "8.40.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1997,20 +2349,20 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/utils": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.28.0.tgz", - "integrity": "sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.40.0.tgz", + "integrity": "sha512-Cgzi2MXSZyAUOY+BFwGs17s7ad/7L+gKt6Y8rAVVWS+7o6wrjeFN4nVfTpbE25MNcxyJ+iYUXflbs2xR9h4UBg==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.28.0", - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/typescript-estree": "8.28.0" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.40.0", + "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/typescript-estree": "8.40.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2021,18 +2373,18 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.28.0.tgz", - "integrity": "sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.40.0.tgz", + "integrity": "sha512-8CZ47QwalyRjsypfwnbI3hKy5gJDPmrkLjkgMxhi0+DZZ2QNx2naS6/hWoVYUHU7LU2zleF68V9miaVZvhFfTA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.28.0", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/types": "8.40.0", + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2043,9 +2395,9 @@ } }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2534,22 +2886,10 @@ "node": ">=18" } }, - "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2737,9 +3077,9 @@ } }, "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.0.tgz", + "integrity": "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==", "dev": true, "license": "MIT" }, @@ -3029,9 +3369,9 @@ } }, "node_modules/confbox": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.1.tgz", - "integrity": "sha512-hkT3yDPFbs95mNCy1+7qNKC6Pro+/ibzYxtM2iqEigpf0sVw+bg4Zh9/snjsBcf990vfIsg5+1U7VyiyBb3etg==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", "license": "MIT" }, "node_modules/consola": { @@ -3140,6 +3480,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -3402,20 +3743,20 @@ } }, "node_modules/eslint": { - "version": "9.23.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz", - "integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==", + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.33.0.tgz", + "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.2", - "@eslint/config-helpers": "^0.2.0", - "@eslint/core": "^0.12.0", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.23.0", - "@eslint/plugin-kit": "^0.2.7", + "@eslint/js": "9.33.0", + "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -3426,9 +3767,9 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -3463,14 +3804,17 @@ } }, "node_modules/eslint-config-prettier": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz", - "integrity": "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==", + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, "peerDependencies": { "eslint": ">=7.0.0" } @@ -3486,14 +3830,14 @@ } }, "node_modules/eslint-plugin-perfectionist": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.10.1.tgz", - "integrity": "sha512-GXwFfL47RfBLZRGQdrvGZw9Ali2T2GPW8p4Gyj2fyWQ9396R/HgJMf0m9kn7D6WXRwrINfTDGLS+QYIeok9qEg==", + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.15.0.tgz", + "integrity": "sha512-pC7PgoXyDnEXe14xvRUhBII8A3zRgggKqJFx2a82fjrItDs1BSI7zdZnQtM2yQvcyod6/ujmzb7ejKPx8lZTnw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "^8.26.0", - "@typescript-eslint/utils": "^8.26.0", + "@typescript-eslint/types": "^8.34.1", + "@typescript-eslint/utils": "^8.34.1", "natural-orderby": "^5.0.0" }, "engines": { @@ -3504,14 +3848,14 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.5.tgz", - "integrity": "sha512-IKKP8R87pJyMl7WWamLgPkloB16dagPIdd2FjBDbyRYPKo93wS/NbCOPh6gH+ieNLC+XZrhJt/kWj0PS/DFdmg==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz", + "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==", "dev": true, "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.10.2" + "synckit": "^0.11.7" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -3535,9 +3879,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -3582,9 +3926,9 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -3593,9 +3937,9 @@ } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3639,15 +3983,15 @@ } }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3657,9 +4001,9 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3748,32 +4092,6 @@ "node": ">=0.8.x" } }, - "node_modules/execa": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.2.tgz", - "integrity": "sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==", - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^4.0.0", - "cross-spawn": "^7.0.3", - "figures": "^6.1.0", - "get-stream": "^9.0.0", - "human-signals": "^8.0.0", - "is-plain-obj": "^4.1.0", - "is-stream": "^4.0.1", - "npm-run-path": "^6.0.0", - "pretty-ms": "^9.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^4.0.0", - "yoctocolors": "^2.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.5.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, "node_modules/express": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", @@ -3829,26 +4147,11 @@ } }, "node_modules/exsolve": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.4.tgz", - "integrity": "sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", "license": "MIT" }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "license": "MIT", - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3925,6 +4228,16 @@ "reusify": "^1.0.4" } }, + "node_modules/fd-package-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fd-package-json/-/fd-package-json-2.0.0.tgz", + "integrity": "sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "walk-up-path": "^4.0.0" + } + }, "node_modules/fecha": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", @@ -3937,21 +4250,6 @@ "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", "license": "MIT" }, - "node_modules/figures": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", - "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", - "license": "MIT", - "dependencies": { - "is-unicode-supported": "^2.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -4118,12 +4416,28 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "ISC", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/formatly": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/formatly/-/formatly-0.2.4.tgz", + "integrity": "sha512-lIN7GpcvX/l/i24r/L9bnJ0I8Qn01qijWpQpDDvTLL29nKqSaJJu4h20+7VJ6m2CAhQ2/En/GbxDiHCzq/0MyA==", + "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "fd-package-json": "^2.0.0" + }, + "bin": { + "formatly": "bin/index.mjs" }, "engines": { - "node": "*" + "node": ">=18.3.0" } }, "node_modules/forwarded": { @@ -4208,22 +4522,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-stream": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", - "license": "MIT", - "dependencies": { - "@sec-ant/readable-stream": "^0.4.1", - "is-stream": "^4.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/glob": { "version": "11.0.3", "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", @@ -4392,15 +4690,6 @@ "node": ">= 0.8" } }, - "node_modules/human-signals": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.0.tgz", - "integrity": "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, "node_modules/husky": { "version": "9.1.7", "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", @@ -4417,13 +4706,12 @@ } }, "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" @@ -4572,52 +4860,17 @@ "node": ">=0.12.0" } }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-promise": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, - "node_modules/is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, "license": "ISC" }, "node_modules/iterare": { @@ -4676,6 +4929,16 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4809,6 +5072,66 @@ "json-buffer": "3.0.1" } }, + "node_modules/knip": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/knip/-/knip-5.62.0.tgz", + "integrity": "sha512-hfTUVzmrMNMT1khlZfAYmBABeehwWUUrizLQoLamoRhSFkygsGIXWx31kaWKBgEaIVL77T3Uz7IxGvSw+CvQ6A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/webpro" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/knip" + }, + { + "type": "polar", + "url": "https://polar.sh/webpro-nl" + } + ], + "license": "ISC", + "dependencies": { + "@nodelib/fs.walk": "^1.2.3", + "fast-glob": "^3.3.3", + "formatly": "^0.2.4", + "jiti": "^2.4.2", + "js-yaml": "^4.1.0", + "minimist": "^1.2.8", + "oxc-resolver": "^11.1.0", + "picocolors": "^1.1.1", + "picomatch": "^4.0.1", + "smol-toml": "^1.3.4", + "strip-json-comments": "5.0.2", + "zod": "^3.22.4", + "zod-validation-error": "^3.0.3" + }, + "bin": { + "knip": "bin/knip.js", + "knip-bun": "bin/knip-bun.js" + }, + "engines": { + "node": ">=18.18.0" + }, + "peerDependencies": { + "@types/node": ">=18", + "typescript": ">=5.0.4" + } + }, + "node_modules/knip/node_modules/strip-json-comments": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.2.tgz", + "integrity": "sha512-4X2FR3UwhNUE9G49aIsJW5hRRR3GXGTBTZRMfv568O60ojM8HcWjV/VxAxCDW3SUND33O6ZY66ZuRcdkj73q2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -5310,22 +5633,20 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/nanoid": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz", - "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/napi-postinstall": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz", + "integrity": "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==", + "dev": true, "license": "MIT", "bin": { - "nanoid": "bin/nanoid.js" + "napi-postinstall": "lib/cli.js" }, "engines": { - "node": "^18 || >=20" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" } }, "node_modules/natural-compare": { @@ -5441,25 +5762,6 @@ "lodash": "^4.17.21" } }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-object-hash": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-object-hash/-/node-object-hash-3.1.1.tgz", - "integrity": "sha512-A32kRGjXtwQ+uSa3GrXiCl8HVFY0Jy6IiKFO7UjagAKSaOOrruxB2Qf/w7TP5QtNfB3uOiHTu3cjhp8k/C0PCg==", - "license": "MIT", - "engines": { - "node": ">=16", - "pnpm": ">=8" - } - }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -5480,34 +5782,6 @@ "node": ">= 18" } }, - "node_modules/npm-run-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", - "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5648,14 +5922,39 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "node_modules/oxc-resolver": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/oxc-resolver/-/oxc-resolver-11.6.1.tgz", + "integrity": "sha512-WQgmxevT4cM5MZ9ioQnEwJiHpPzbvntV5nInGAKo9NQZzegcOonHvcVcnkYqld7bTG35UFHEKeF7VwwsmA3cZg==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxc-resolver/binding-android-arm-eabi": "11.6.1", + "@oxc-resolver/binding-android-arm64": "11.6.1", + "@oxc-resolver/binding-darwin-arm64": "11.6.1", + "@oxc-resolver/binding-darwin-x64": "11.6.1", + "@oxc-resolver/binding-freebsd-x64": "11.6.1", + "@oxc-resolver/binding-linux-arm-gnueabihf": "11.6.1", + "@oxc-resolver/binding-linux-arm-musleabihf": "11.6.1", + "@oxc-resolver/binding-linux-arm64-gnu": "11.6.1", + "@oxc-resolver/binding-linux-arm64-musl": "11.6.1", + "@oxc-resolver/binding-linux-ppc64-gnu": "11.6.1", + "@oxc-resolver/binding-linux-riscv64-gnu": "11.6.1", + "@oxc-resolver/binding-linux-riscv64-musl": "11.6.1", + "@oxc-resolver/binding-linux-s390x-gnu": "11.6.1", + "@oxc-resolver/binding-linux-x64-gnu": "11.6.1", + "@oxc-resolver/binding-linux-x64-musl": "11.6.1", + "@oxc-resolver/binding-wasm32-wasi": "11.6.1", + "@oxc-resolver/binding-win32-arm64-msvc": "11.6.1", + "@oxc-resolver/binding-win32-ia32-msvc": "11.6.1", + "@oxc-resolver/binding-win32-x64-msvc": "11.6.1" } }, "node_modules/p-limit": { @@ -5690,6 +5989,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-map": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-retry": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", @@ -5746,18 +6057,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-ms": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", - "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -5817,6 +6116,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5890,13 +6190,13 @@ } }, "node_modules/pkg-types": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz", - "integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", "license": "MIT", "dependencies": { - "confbox": "^0.2.1", - "exsolve": "^1.0.1", + "confbox": "^0.2.2", + "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, @@ -5921,9 +6221,9 @@ } }, "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", "bin": { @@ -5961,21 +6261,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pretty-ms": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz", - "integrity": "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==", - "license": "MIT", - "dependencies": { - "parse-ms": "^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/protobufjs": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", @@ -6093,18 +6378,6 @@ "node": ">= 0.8" } }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -6351,23 +6624,10 @@ "dev": true, "license": "MIT" }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "license": "MIT", - "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -6445,6 +6705,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -6457,6 +6718,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6538,6 +6800,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, "license": "ISC", "engines": { "node": ">=14" @@ -6578,6 +6841,19 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/smol-toml": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.4.2.tgz", + "integrity": "sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, "node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", @@ -6716,18 +6992,6 @@ "node": ">=4" } }, - "node_modules/strip-final-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", - "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -6781,26 +7045,25 @@ } }, "node_modules/synckit": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.10.3.tgz", - "integrity": "sha512-R1urvuyiTaWfeCggqEvpDJwAlDVdsT9NM+IP//Tk2x7qHCkSvBk/fwFgw/TLAHzZlrAnnazMcRw0ZD8HlYFTEQ==", + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.2.0", - "tslib": "^2.8.1" + "@pkgr/core": "^0.2.9" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/synckit" } }, "node_modules/systeminformation": { - "version": "5.25.11", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.25.11.tgz", - "integrity": "sha512-jI01fn/t47rrLTQB0FTlMCC+5dYx8o0RRF+R4BPiUNsvg5OdY0s9DKMFmJGrx5SwMZQ4cag0Gl6v8oycso9b/g==", + "version": "5.27.7", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.7.tgz", + "integrity": "sha512-saaqOoVEEFaux4v0K8Q7caiauRwjXC4XbD2eH60dxHXbpKxQ8kH9Rf7Jh+nryKpOUSEFxtCdBlSUx0/lO6rwRg==", "license": "MIT", "os": [ "darwin", @@ -6978,19 +7241,6 @@ "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", "license": "MIT" }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7229,9 +7479,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true, "license": "Apache-2.0", "bin": { @@ -7267,23 +7517,11 @@ } }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "license": "MIT" }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -7394,6 +7632,16 @@ "node": ">= 0.8" } }, + "node_modules/walk-up-path": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-4.0.0.tgz", + "integrity": "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/watchpack": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", @@ -7566,6 +7814,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -7775,18 +8024,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yoctocolors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", - "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/yoctocolors-cjs": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", @@ -7801,13 +8038,26 @@ } }, "node_modules/zod": { - "version": "3.24.2", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", - "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } + }, + "node_modules/zod-validation-error": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.5.3.tgz", + "integrity": "sha512-OT5Y8lbUadqVZCsnyFaTQ4/O2mys4tj7PqhdbBCp7McPwvIEKfPtdA6QfPeFQK2/Rz5LgwmAXRJTugBNBi0btw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } } } } diff --git a/package.json b/package.json index 9a99b2d..0bf6422 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@remnawave/node", - "version": "2.1.3", + "version": "2.1.4", "description": "Remnawave Node", "private": false, "type": "commonjs", @@ -25,10 +25,11 @@ "prepare": "husky", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\"", "lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", - "lint:fix:imports": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix --rule 'perfectionist/sort-imports: error'" + "lint:fix:imports": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix --rule 'perfectionist/sort-imports: error'", + "knip": "knip" }, "dependencies": { - "@cjs-exporter/execa": "9.5.2", + "@henrygd/semaphore": "^0.0.2", "@nestjs/common": "11.1.6", "@nestjs/config": "4.0.2", "@nestjs/core": "11.1.6", @@ -44,52 +45,47 @@ "helmet": "^8.1.0", "husky": "9.1.7", "morgan": "^1.10.1", - "nanoid": "^5.1.5", "nest-winston": "^1.10.2", "nestjs-zod": "4.3.1", - "node-object-hash": "^3.1.1", "node-supervisord": "^1.0.6-rc.2", "object-hash": "^3.0.0", + "p-map": "^7.0.3", "p-retry": "^6.2.1", "passport": "0.7.0", "passport-jwt": "4.0.1", - "pkg-types": "^2.1.0", + "pkg-types": "^2.3.0", "pretty-bytes": "^6.1.1", "reflect-metadata": "0.2.2", "rxjs": "7.8.2", - "selfsigned": "^2.4.1", - "semver": "^7.7.1", - "systeminformation": "^5.25.11", + "semver": "^7.7.2", + "systeminformation": "^5.27.7", "table": "^6.9.0", "winston": "^3.17.0", - "zod": "^3.24.2" + "zod": "3.25.76" }, "devDependencies": { "@nestjs/cli": "11.0.10", "@nestjs/schematics": "11.0.7", "@types/compression": "^1.8.1", "@types/express": "^5.0.3", - "@types/js-yaml": "^4.0.9", - "@types/jsonwebtoken": "^9.0.10", - "@types/mjml": "^4.7.4", "@types/morgan": "^1.9.10", - "@types/node": "^22.13.14", - "@types/nunjucks": "^3.2.6", + "@types/node": "^22.17.2", "@types/object-hash": "^3.0.6", "@types/passport-jwt": "^4.0.1", "@types/semver": "^7.7.0", - "@typescript-eslint/eslint-plugin": "8.28.0", - "@typescript-eslint/parser": "8.28.0", - "eslint": "9.23.0", - "eslint-config-prettier": "^10.1.1", + "@typescript-eslint/eslint-plugin": "8.40.0", + "@typescript-eslint/parser": "8.40.0", + "eslint": "9.33.0", + "eslint-config-prettier": "^10.1.8", "eslint-plugin-paths": "^1.1.0", - "eslint-plugin-perfectionist": "^4.10.1", - "eslint-plugin-prettier": "^5.2.5", - "prettier": "^3.5.3", + "eslint-plugin-perfectionist": "^4.15.0", + "eslint-plugin-prettier": "^5.5.4", + "knip": "^5.62.0", + "prettier": "^3.6.2", "source-map-support": "^0.5.21", "ts-loader": "9.5.2", "ts-node": "10.9.2", "tsconfig-paths": "^4.2.0", - "typescript": "~5.8.2" + "typescript": "^5.9.2" } } diff --git a/src/common/decorators/get-x-force-restart/get-x-force-restart.ts b/src/common/decorators/get-x-force-restart/get-x-force-restart.ts new file mode 100644 index 0000000..3114776 --- /dev/null +++ b/src/common/decorators/get-x-force-restart/get-x-force-restart.ts @@ -0,0 +1,17 @@ +import { createParamDecorator, ExecutionContext } from '@nestjs/common'; + +import { X_FORCE_RESTART } from '@libs/contracts/constants'; + +export const XForceRestart = createParamDecorator((_, ctx: ExecutionContext): boolean => { + const request = ctx.switchToHttp().getRequest(); + + const forceRestart: string | undefined = request.headers[X_FORCE_RESTART.toLowerCase()]; + + if (forceRestart) { + if (forceRestart === 'true' || forceRestart === '1') { + return true; + } + } + + return false; +}); diff --git a/src/common/exception/httpException.filter.ts b/src/common/exception/http-exception.filter.ts similarity index 100% rename from src/common/exception/httpException.filter.ts rename to src/common/exception/http-exception.filter.ts diff --git a/src/common/exception/index.ts b/src/common/exception/index.ts new file mode 100644 index 0000000..d1cbc3a --- /dev/null +++ b/src/common/exception/index.ts @@ -0,0 +1,3 @@ +export * from './http-exception.filter'; +export * from './http-exeception-with-error-code.type'; +export * from './not-found-exception.filter'; diff --git a/src/common/guards/jwt-guards/index.ts b/src/common/guards/jwt-guards/index.ts index e69de29..ad9e5e5 100644 --- a/src/common/guards/jwt-guards/index.ts +++ b/src/common/guards/jwt-guards/index.ts @@ -0,0 +1 @@ +export * from './def-jwt-guard'; diff --git a/src/common/helpers/index.ts b/src/common/helpers/index.ts new file mode 100644 index 0000000..396fec2 --- /dev/null +++ b/src/common/helpers/index.ts @@ -0,0 +1,3 @@ +export * from './can-parse-json'; +export * from './error-handler-with-null.helper'; +export * from './error-handler.helper'; diff --git a/src/common/types/converter.interface.ts b/src/common/types/converter.interface.ts deleted file mode 100644 index 942d7d5..0000000 --- a/src/common/types/converter.interface.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface IConverter { - fromEntitiesToPrismaModels(entities: T[]): U[]; - fromEntityToPrismaModel(entity: T): U; - fromPrismaModelsToEntities(prismaModels: U[]): T[]; - fromPrismaModelToEntity(prismaModel: U): T; -} diff --git a/src/common/types/crud-port.ts b/src/common/types/crud-port.ts deleted file mode 100644 index 4a345fa..0000000 --- a/src/common/types/crud-port.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface ICrud { - create: (entity: ENTITY) => Promise; - deleteByUUID: (uuid: string) => Promise; - findByCriteria: (entity: Partial) => Promise; - findByUUID: (uuid: string) => Promise; - update: (entity: ENTITY) => Promise; -} diff --git a/src/common/utils/get-start-message.ts b/src/common/utils/get-start-message.ts index 5df2dc4..60a3e29 100644 --- a/src/common/utils/get-start-message.ts +++ b/src/common/utils/get-start-message.ts @@ -14,7 +14,7 @@ export async function getStartMessage( const xrayService = app.get(XrayService); - const xrayInfo = await xrayService.getXrayInfo(); + const xrayInfo = xrayService.getXrayInfo(); return table( [ diff --git a/src/common/utils/validate-env-config.ts b/src/common/utils/validate-env-config.ts index e514eb7..f479867 100644 --- a/src/common/utils/validate-env-config.ts +++ b/src/common/utils/validate-env-config.ts @@ -1,9 +1,27 @@ -import { z } from 'zod'; +import { z, ZodError } from 'zod'; export function validateEnvConfig(schema: z.ZodType, config: Record): T { try { return schema.parse(config); } catch (e) { - throw new Error(`.env configuration validation error: ${e}`); + if (e instanceof ZodError) { + const formattedErrors = e.errors + .map((err) => `❌ ${err.path.join('.')}: ${err.message}`) + .join('\n'); + + const errorMessage = ` +🔧 Environment Configuration Errors: +${formattedErrors} + +Please fix your .env file and restart the application.`; + + const error = new Error(errorMessage); + error.stack = ''; + throw error; + } + + const error = new Error(`.env configuration validation error: ${e}`); + error.stack = ''; + throw error; } } diff --git a/src/main.ts b/src/main.ts index bcf15d4..bca53b8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -10,11 +10,11 @@ import morgan from 'morgan'; import { ConfigService } from '@nestjs/config'; import { NestFactory } from '@nestjs/core'; -import { NotFoundExceptionFilter } from '@common/exception/not-found-exception.filter'; -import { customLogFilter } from '@common/utils/filter-logs/filter-logs'; import { parseNodePayload } from '@common/utils/decode-node-payload'; import { getStartMessage } from '@common/utils/get-start-message'; import { isDevelopment } from '@common/utils/is-development'; +import { NotFoundExceptionFilter } from '@common/exception'; +import { customLogFilter } from '@common/utils/filter-logs'; import { XRAY_INTERNAL_API_PORT, XRAY_INTERNAL_FULL_PATH } from '@libs/contracts/constants'; import { REST_API, ROOT } from '@libs/contracts/api'; diff --git a/src/modules/handler/handler.controller.ts b/src/modules/handler/handler.controller.ts index e37d327..d6e176a 100644 --- a/src/modules/handler/handler.controller.ts +++ b/src/modules/handler/handler.controller.ts @@ -1,8 +1,8 @@ import { Body, Controller, Post, UseFilters, UseGuards } from '@nestjs/common'; -import { HttpExceptionFilter } from '@common/exception/httpException.filter'; -import { JwtDefaultGuard } from '@common/guards/jwt-guards/def-jwt-guard'; -import { errorHandler } from '@common/helpers/error-handler.helper'; +import { JwtDefaultGuard } from '@common/guards/jwt-guards'; +import { HttpExceptionFilter } from '@common/exception'; +import { errorHandler } from '@common/helpers'; import { HANDLER_CONTROLLER, HANDLER_ROUTES } from '@libs/contracts/api/controllers/handler'; import { diff --git a/src/modules/handler/handler.service.ts b/src/modules/handler/handler.service.ts index f516923..ba83712 100644 --- a/src/modules/handler/handler.service.ts +++ b/src/modules/handler/handler.service.ts @@ -1,7 +1,9 @@ import { Injectable, Logger } from '@nestjs/common'; -import { RemoveUserResponseModel as RemoveUserResponseModelFromSdk } from '@remnawave/xtls-sdk/build/src/handler/models/remove-user'; -import { AddUserResponseModel as AddUserResponseModelFromSdk } from '@remnawave/xtls-sdk/build/src/handler/models/add-user'; +import { + RemoveUserResponseModel as RemoveUserResponseModelFromSdk, + AddUserResponseModel as AddUserResponseModelFromSdk, +} from '@remnawave/xtls-sdk/build/src/handler/models'; import { ISdkResponse } from '@remnawave/xtls-sdk/build/src/common/types'; import { InjectXtls } from '@remnawave/xtls-sdk-nestjs'; import { XtlsApi } from '@remnawave/xtls-sdk'; @@ -9,12 +11,14 @@ import { XtlsApi } from '@remnawave/xtls-sdk'; import { ICommandResponse } from '@common/types/command-response.type'; import { ERRORS } from '@libs/contracts/constants/errors'; -import { AddUserResponseModel, RemoveUserResponseModel } from './models'; +import { + GetInboundUsersCountResponseModel, + GetInboundUsersResponseModel, + AddUserResponseModel, + RemoveUserResponseModel, +} from './models'; +import { IRemoveUserRequest, TAddUserRequest } from './interfaces'; import { InternalService } from '../internal/internal.service'; -import { GetInboundUsersCountResponseModel } from './models'; -import { GetInboundUsersResponseModel } from './models'; -import { IRemoveUserRequest } from './interfaces'; -import { TAddUserRequest } from './interfaces'; @Injectable() export class HandlerService { @@ -40,9 +44,9 @@ export class HandlerService { await this.xtlsApi.handler.removeUser(tag, requestData[0].username); if (hashData.prevVlessUuid) { - this.internalService.removeUserFromInbound(tag, hashData.prevVlessUuid); + await this.internalService.removeUserFromInbound(tag, hashData.prevVlessUuid); } else { - this.internalService.removeUserFromInbound(tag, hashData.vlessUuid); + await this.internalService.removeUserFromInbound(tag, hashData.vlessUuid); } } @@ -60,7 +64,10 @@ export class HandlerService { level: item.level, }); if (tempRes.isOk) { - this.internalService.addUserToInbound(item.tag, hashData.vlessUuid); + await this.internalService.addUserToInbound( + item.tag, + hashData.vlessUuid, + ); } response.push(tempRes); break; @@ -73,7 +80,10 @@ export class HandlerService { level: item.level, }); if (tempRes.isOk) { - this.internalService.addUserToInbound(item.tag, hashData.vlessUuid); + await this.internalService.addUserToInbound( + item.tag, + hashData.vlessUuid, + ); } response.push(tempRes); break; @@ -87,7 +97,10 @@ export class HandlerService { level: item.level, }); if (tempRes.isOk) { - this.internalService.addUserToInbound(item.tag, hashData.vlessUuid); + await this.internalService.addUserToInbound( + item.tag, + hashData.vlessUuid, + ); } response.push(tempRes); break; @@ -135,7 +148,7 @@ export class HandlerService { const tempRes = await this.xtlsApi.handler.removeUser(tag, username); - this.internalService.removeUserFromInbound(tag, hashData.vlessUuid); + await this.internalService.removeUserFromInbound(tag, hashData.vlessUuid); response.push(tempRes); } diff --git a/src/modules/internal/internal.controller.ts b/src/modules/internal/internal.controller.ts index 9047d62..631bcc8 100644 --- a/src/modules/internal/internal.controller.ts +++ b/src/modules/internal/internal.controller.ts @@ -1,8 +1,8 @@ import { Controller, Get, UseFilters, UseGuards } from '@nestjs/common'; -import { PortGuard } from '@common/guards/request-port-guard/request-port.guard'; -import { HttpExceptionFilter } from '@common/exception/httpException.filter'; -import { OnPort } from '@common/decorators/port/port.decorator'; +import { PortGuard } from '@common/guards/request-port-guard'; +import { HttpExceptionFilter } from '@common/exception'; +import { OnPort } from '@common/decorators/port'; import { XRAY_INTERNAL_API_CONTROLLER, XRAY_INTERNAL_API_PATH, diff --git a/src/modules/internal/internal.service.ts b/src/modules/internal/internal.service.ts index bf7ff33..3b9a5e0 100644 --- a/src/modules/internal/internal.service.ts +++ b/src/modules/internal/internal.service.ts @@ -1,4 +1,6 @@ +import { getSemaphore } from '@henrygd/semaphore'; import ems from 'enhanced-ms'; +import pMap from 'p-map'; import { Injectable, Logger } from '@nestjs/common'; @@ -9,6 +11,8 @@ import { IHashPayload } from '@libs/contracts/constants'; @Injectable() export class InternalService { private readonly logger = new Logger(InternalService.name); + private readonly mutex = getSemaphore(); + private xrayConfig: null | Record = null; private emptyConfigHash: null | string = null; private inboundsHashMap: Map = new Map(); @@ -25,14 +29,13 @@ export class InternalService { } public setXrayConfig(config: Record): void { - this.logger.debug('Setting new xray config'); this.xrayConfig = config; } - public extractUsersFromConfig( + public async extractUsersFromConfig( hashPayload: IHashPayload, newConfig: Record, - ): void { + ): Promise { this.cleanup(); this.emptyConfigHash = hashPayload.emptyConfig; @@ -44,33 +47,39 @@ export class InternalService { const start = performance.now(); if (newConfig.inbounds && Array.isArray(newConfig.inbounds)) { - for (const inbound of newConfig.inbounds) { - const inboundTag: string = inbound.tag; + const validTags = new Set(hashPayload.inbounds.map((item) => item.tag)); - if (!inboundTag || !hashPayload.inbounds.find((item) => item.tag === inboundTag)) { - continue; - } + await pMap( + newConfig.inbounds, + async (inbound) => { + const inboundTag: string = inbound.tag; - const usersSet = new HashedSet(); + if (!inboundTag || !validTags.has(inboundTag)) { + return; + } - if ( - inbound.settings && - inbound.settings.clients && - Array.isArray(inbound.settings.clients) - ) { - for (const client of inbound.settings.clients) { - if (client.id) { - usersSet.add(client.id); + const usersSet = new HashedSet(); + + if ( + inbound.settings && + inbound.settings.clients && + Array.isArray(inbound.settings.clients) + ) { + for (const client of inbound.settings.clients) { + if (client.id) { + usersSet.add(client.id); + } } } - } - this.inboundsHashMap.set(inboundTag, usersSet); - } + this.inboundsHashMap.set(inboundTag, usersSet); + }, + { concurrency: 20 }, + ); for (const [inboundTag, usersSet] of this.inboundsHashMap) { this.xtlsConfigInbounds.add(inboundTag); - this.logger.log(`Inbound ${inboundTag} contains ${usersSet.size} user(s)`); + this.logger.log(`${inboundTag} has ${usersSet.size} users`); } } @@ -90,12 +99,12 @@ export class InternalService { } if (incomingHashPayload.emptyConfig !== this.emptyConfigHash) { - this.logger.log('Detected changes in Xray Core base configuration'); + this.logger.warn('Detected changes in Xray Core base configuration'); return true; } if (incomingHashPayload.inbounds.length !== this.inboundsHashMap.size) { - this.logger.log('Number of Xray Core inbounds has changed'); + this.logger.warn('Number of Xray Core inbounds has changed'); return true; } @@ -105,14 +114,14 @@ export class InternalService { ); if (!incomingInbound) { - this.logger.log( + this.logger.warn( `Inbound ${inboundTag} no longer exists in Xray Core configuration`, ); return true; } if (usersSet.hash64String !== incomingInbound.hash) { - this.logger.log( + this.logger.warn( `User configuration changed for inbound ${inboundTag} (${usersSet.hash64String} → ${incomingInbound.hash})`, ); return true; @@ -134,36 +143,52 @@ export class InternalService { } } - public addUserToInbound(inboundTag: string, user: string): void { - const usersSet = this.inboundsHashMap.get(inboundTag); + public async addUserToInbound(inboundTag: string, user: string): Promise { + await this.mutex.acquire(); - if (!usersSet) { - this.logger.warn( - `Inbound ${inboundTag} not found in inboundsHashMap, creating new one`, - ); + try { + const usersSet = this.inboundsHashMap.get(inboundTag); - this.inboundsHashMap.set(inboundTag, new HashedSet([user])); + if (!usersSet) { + this.logger.warn( + `Inbound ${inboundTag} not found in inboundsHashMap, creating new one`, + ); - return; - } + this.inboundsHashMap.set(inboundTag, new HashedSet([user])); + + return; + } - usersSet.add(user); + usersSet.add(user); + } catch (error) { + this.logger.error(`Failed to add user to inbound ${inboundTag}: ${error}`); + } finally { + this.mutex.release(); + } } - public removeUserFromInbound(inboundTag: string, user: string): void { - const usersSet = this.inboundsHashMap.get(inboundTag); + public async removeUserFromInbound(inboundTag: string, user: string): Promise { + await this.mutex.acquire(); - if (!usersSet) { - return; - } + try { + const usersSet = this.inboundsHashMap.get(inboundTag); - usersSet.delete(user); + if (!usersSet) { + return; + } + + usersSet.delete(user); - if (usersSet.size === 0) { - this.xtlsConfigInbounds.delete(inboundTag); - this.inboundsHashMap.delete(inboundTag); + if (usersSet.size === 0) { + this.xtlsConfigInbounds.delete(inboundTag); + this.inboundsHashMap.delete(inboundTag); - this.logger.warn(`Inbound ${inboundTag} has no users, clearing inboundsHashMap.`); + this.logger.warn(`Inbound ${inboundTag} has no users, clearing inboundsHashMap.`); + } + } catch (error) { + this.logger.error(`Failed to remove user from inbound ${inboundTag}: ${error}`); + } finally { + this.mutex.release(); } } diff --git a/src/modules/stats/stats.controller.ts b/src/modules/stats/stats.controller.ts index 9ac33cd..74a2c07 100644 --- a/src/modules/stats/stats.controller.ts +++ b/src/modules/stats/stats.controller.ts @@ -1,8 +1,8 @@ import { Body, Controller, Get, Post, UseFilters, UseGuards } from '@nestjs/common'; -import { HttpExceptionFilter } from '@common/exception/httpException.filter'; -import { JwtDefaultGuard } from '@common/guards/jwt-guards/def-jwt-guard'; -import { errorHandler } from '@common/helpers/error-handler.helper'; +import { JwtDefaultGuard } from '@common/guards/jwt-guards'; +import { HttpExceptionFilter } from '@common/exception'; +import { errorHandler } from '@common/helpers'; import { STATS_CONTROLLER, STATS_ROUTES } from '@libs/contracts/api/controllers/stats'; import { diff --git a/src/modules/vision/vision.controller.ts b/src/modules/vision/vision.controller.ts index 9368426..749fa08 100644 --- a/src/modules/vision/vision.controller.ts +++ b/src/modules/vision/vision.controller.ts @@ -1,9 +1,9 @@ import { Body, Controller, Post, UseFilters, UseGuards } from '@nestjs/common'; -import { PortGuard } from '@common/guards/request-port-guard/request-port.guard'; -import { HttpExceptionFilter } from '@common/exception/httpException.filter'; -import { errorHandler } from '@common/helpers/error-handler.helper'; import { OnPort } from '@common/decorators/port/port.decorator'; +import { PortGuard } from '@common/guards/request-port-guard'; +import { HttpExceptionFilter } from '@common/exception'; +import { errorHandler } from '@common/helpers'; import { VISION_CONTROLLER, VISION_ROUTES } from '@libs/contracts/api/controllers/vision'; import { XRAY_INTERNAL_API_PORT } from '@libs/contracts/constants'; diff --git a/src/modules/xray-core/xray.controller.ts b/src/modules/xray-core/xray.controller.ts index f4aa218..8c3a1d0 100644 --- a/src/modules/xray-core/xray.controller.ts +++ b/src/modules/xray-core/xray.controller.ts @@ -1,10 +1,11 @@ import { Body, Controller, Get, Ip, Logger, Post, UseFilters, UseGuards } from '@nestjs/common'; +import { XForceRestart } from '@common/decorators/get-x-force-restart/get-x-force-restart'; import { HashPayload } from '@common/decorators/get-hash-payload/get-hash-payload'; -import { HttpExceptionFilter } from '@common/exception/httpException.filter'; -import { JwtDefaultGuard } from '@common/guards/jwt-guards/def-jwt-guard'; +import { HttpExceptionFilter } from '@common/exception/http-exception.filter'; import { errorHandler } from '@common/helpers/error-handler.helper'; -import { XRAY_CONTROLLER, XRAY_ROUTES } from '@libs/contracts/api/controllers/xray'; +import { JwtDefaultGuard } from '@common/guards/jwt-guards'; +import { XRAY_CONTROLLER, XRAY_ROUTES } from '@libs/contracts/api'; import { IHashPayload } from '@libs/contracts/constants'; import { @@ -29,8 +30,9 @@ export class XrayController { @Body() body: StartXrayRequestDto, @Ip() ip: string, @HashPayload() hashPayload: IHashPayload | null, + @XForceRestart() forceRestart: boolean, ): Promise { - const response = await this.xrayService.startXray(body, ip, hashPayload); + const response = await this.xrayService.startXray(body, ip, hashPayload, forceRestart); const data = errorHandler(response); return { diff --git a/src/modules/xray-core/xray.service.ts b/src/modules/xray-core/xray.service.ts index 1bb8bd7..8db2ba7 100644 --- a/src/modules/xray-core/xray.service.ts +++ b/src/modules/xray-core/xray.service.ts @@ -1,13 +1,12 @@ import { ProcessInfo } from 'node-supervisord/dist/interfaces'; import { SupervisordClient } from 'node-supervisord'; -import { execa } from '@cjs-exporter/execa'; import { readPackageJSON } from 'pkg-types'; import { table } from 'table'; import ems from 'enhanced-ms'; import pRetry from 'p-retry'; import semver from 'semver'; -import { Injectable, Logger, OnApplicationBootstrap, OnModuleInit } from '@nestjs/common'; +import { Injectable, Logger, OnApplicationBootstrap } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { InjectSupervisord } from '@remnawave/supervisord-nestjs'; @@ -31,7 +30,7 @@ import { InternalService } from '../internal/internal.service'; const XRAY_PROCESS_NAME = 'xray' as const; @Injectable() -export class XrayService implements OnApplicationBootstrap, OnModuleInit { +export class XrayService implements OnApplicationBootstrap { private readonly logger = new Logger(XrayService.name); private readonly disableHashedSetCheck: boolean; @@ -58,14 +57,11 @@ export class XrayService implements OnApplicationBootstrap, OnModuleInit { ); } - async onModuleInit() { - this.xrayVersion = await this.getXrayVersionFromExec(); - } - async onApplicationBootstrap() { try { const pkg = await readPackageJSON(); + this.xrayVersion = this.getXrayVersionFromEnv(); this.systemStats = await getSystemStats(); this.nodeVersion = pkg.version || null; @@ -81,6 +77,7 @@ export class XrayService implements OnApplicationBootstrap, OnModuleInit { config: Record, ip: string, hashPayload: IHashPayload | null, + forceRestart: boolean, ): Promise> { const tm = performance.now(); @@ -116,7 +113,7 @@ export class XrayService implements OnApplicationBootstrap, OnModuleInit { this.isXrayStartedProccesing = true; - if (this.isXrayOnline && !this.disableHashedSetCheck) { + if (this.isXrayOnline && !this.disableHashedSetCheck && !forceRestart) { const { isOk } = await this.xtlsSdk.stats.getSysStats(); let shouldRestart = false; @@ -146,6 +143,10 @@ export class XrayService implements OnApplicationBootstrap, OnModuleInit { } } + if (forceRestart) { + this.logger.warn('Force restart requested'); + } + const fullConfig = generateApiConfig(config); this.internalService.extractUsersFromConfig(hashPayload, fullConfig); @@ -331,48 +332,17 @@ export class XrayService implements OnApplicationBootstrap, OnModuleInit { } public async killAllXrayProcesses(): Promise { - try { - try { - await this.supervisordApi.stopProcess(XRAY_PROCESS_NAME, true); - } catch (error) { - this.logger.error(`Response from supervisorctl stop: ${error}`); - } - - await execa('pkill', ['xray'], { reject: false }); - - await new Promise((resolve) => setTimeout(resolve, 1000)); - - await execa('pkill', ['-9', 'xray'], { reject: false }); - - try { - const { stdout } = await execa('lsof', ['-i', ':61000', '-t']); - if (stdout) { - await execa('kill', ['-9', stdout.trim()], { reject: false }); - } - } catch (e) { - this.logger.error(`Failed to kill Xray process: ${e}`); - } - - this.logger.log('Killed all Xray processes'); - } catch (error) { - this.logger.log(`No existing Xray processes found. Error: ${error}`); - } - } - - public async supervisorctlStop(): Promise { try { await this.supervisordApi.stopProcess(XRAY_PROCESS_NAME, true); - this.logger.log('Supervisorctl: XTLS stopped.'); + this.logger.log('Supervisord: Xray processes killed.'); } catch (error) { - this.logger.log('Supervisorctl: XTLS stop failed. Error: ', error); + this.logger.log(`Supervisord: No existing Xray processes found. Error: ${error}`); } } - private async getXrayVersionFromExec(): Promise { - const output = await execa(this.xrayPath, ['version']); - - const version = semver.valid(semver.coerce(output.stdout)); + private getXrayVersionFromEnv(): null | string { + const version = semver.valid(semver.coerce(process.env.XRAY_CORE_VERSION)); if (version) { this.xrayVersion = version; @@ -381,13 +351,12 @@ export class XrayService implements OnApplicationBootstrap, OnModuleInit { return version; } - public async getXrayInfo(): Promise<{ + public getXrayInfo(): { version: string | null; path: string; systemInfo: ISystemStats | null; - }> { - const output = await execa(this.xrayPath, ['version']); - const version = semver.valid(semver.coerce(output.stdout)); + } { + const version = this.getXrayVersionFromEnv(); if (version) { this.xrayVersion = version;