From 8eec2e3f387889ab3ad2180aaa0ed0ebea6da2f2 Mon Sep 17 00:00:00 2001 From: Julien Loizelet Date: Fri, 18 Jul 2025 16:02:53 +0900 Subject: [PATCH 01/11] feat(*): Migrate from CommonJS to ESM --- .eslintrc.js | 60 - eslint.config.mjs | 181 +- examples/basics/fetch-decisions-stream.ts | 3 +- examples/basics/get-ip-remediation.ts | 5 +- examples/express-server/helpers/index.ts | 15 +- examples/express-server/package.json | 33 +- examples/express-server/playwright.config.ts | 7 +- examples/express-server/server.ts | 12 +- examples/express-server/tests/constants.ts | 6 + .../tests/custom-configs-1.spec.ts | 12 +- .../tests/custom-configs-2.spec.ts | 10 +- examples/express-server/tests/helpers/base.ts | 10 +- .../express-server/tests/live-mode.spec.ts | 12 +- examples/express-server/tests/setup/common.ts | 4 +- .../express-server/tests/stream-mode.spec.ts | 12 +- examples/express-server/tsconfig.json | 24 +- jest-ejs-transform.cjs | 12 + jest.config.mjs | 24 + jest.config.ts | 17 - package-lock.json | 11889 ++++++++++++---- package.json | 28 +- src/helpers/__tests__/ip.test.ts | 28 +- src/helpers/decision.ts | 10 +- src/helpers/duration.ts | 2 +- src/helpers/ip.ts | 2 +- src/lib/__tests__/cache.test.ts | 4 +- src/lib/__tests__/helpers-duration.test.ts | 2 +- src/lib/__tests__/rendered.test.ts | 33 +- src/lib/bouncer/constants.ts | 4 +- src/lib/bouncer/index.ts | 53 +- src/lib/bouncer/types.ts | 10 +- src/lib/cache/decisions.ts | 2 +- src/lib/cache/helpers.ts | 2 +- src/lib/cache/in-memory.ts | 8 +- src/lib/cache/index.ts | 26 +- src/lib/cache/interfaces.ts | 2 +- src/lib/cache/keyv-adapter.ts | 29 +- src/lib/cache/types.ts | 6 +- src/lib/constants.ts | 10 +- src/lib/lapi-client/index.ts | 12 +- src/lib/lapi-client/metrics.ts | 4 +- src/lib/lapi-client/types.ts | 2 +- src/lib/rendered/constants.ts | 12 +- src/lib/rendered/index.ts | 16 +- src/lib/rendered/types.ts | 2 +- src/lib/types.ts | 2 +- src/types/ejs.d.ts | 6 + tsconfig.json | 56 +- tsup.config.ts | 16 + 49 files changed, 9207 insertions(+), 3530 deletions(-) delete mode 100644 .eslintrc.js create mode 100644 jest-ejs-transform.cjs create mode 100644 jest.config.mjs delete mode 100644 jest.config.ts create mode 100644 src/types/ejs.d.ts create mode 100644 tsup.config.ts diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 08c882e..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,60 +0,0 @@ -module.exports = { - env: { - browser: true, - es2021: true, - }, - extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:import/recommended', 'plugin:import/typescript'], - overrides: [ - { - env: { - node: true, - }, - files: ['.eslintrc.js'], - parserOptions: { - sourceType: 'script', - }, - }, - ], - parser: '@typescript-eslint/parser', - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module', - }, - settings: { - 'import/resolver': { - typescript: { - alwaysTryTypes: true, - project: './tsconfig.json', - }, - }, - 'import/parsers': { - '@typescript-eslint/parser': ['.ts', '.tsx'], - }, - }, - rules: { - 'import/no-unresolved': 'error', - 'import/order': [ - 'error', - { - groups: ['external', ['builtin', 'index', 'sibling', 'parent', 'internal'], 'object', 'type'], - 'newlines-between': 'always', - alphabetize: { order: 'asc', caseInsensitive: true }, - }, - ], - 'no-relative-import-paths/no-relative-import-paths': ['error', { allowSameFolder: false }], - 'prefer-arrow-functions/prefer-arrow-functions': [ - 'error', - { - allowNamedFunctions: false, - classPropertiesAllowed: false, - disallowPrototype: false, - returnStyle: 'unchanged', - singleReturnOnly: false, - }, - ], - 'prefer-template': 'error', - 'no-nested-ternary': 'error', - }, - ignorePatterns: ['**/*.ejs', 'dist/'], - plugins: ['@typescript-eslint', 'prefer-arrow-functions', 'eslint-plugin-import', 'no-relative-import-paths'], -}; diff --git a/eslint.config.mjs b/eslint.config.mjs index 827a5f7..596d37b 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -3,27 +3,92 @@ import { FlatCompat } from '@eslint/eslintrc'; import js from '@eslint/js'; import typescriptEslint from '@typescript-eslint/eslint-plugin'; import tsParser from '@typescript-eslint/parser'; -import _import from 'eslint-plugin-import'; -import noRelativeImportPaths from 'eslint-plugin-no-relative-import-paths'; +import eslintImport from 'eslint-plugin-import'; import preferArrowFunctions from 'eslint-plugin-prefer-arrow-functions'; +import jestPlugin from 'eslint-plugin-jest'; import globals from 'globals'; - import path from 'node:path'; -import process from 'node:process'; import { fileURLToPath } from 'node:url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); + +const jestGlobals = jestPlugin.envs?.['jest/globals']?.globals ?? jestPlugin.environments?.['jest/globals']?.globals ?? {}; + const compat = new FlatCompat({ baseDirectory: __dirname, recommendedConfig: js.configs.recommended, allConfig: js.configs.all, }); +const shared = { + plugins: { + '@typescript-eslint': fixupPluginRules(typescriptEslint), + 'prefer-arrow-functions': preferArrowFunctions, + import: fixupPluginRules(eslintImport), + }, + + languageOptions: { + parser: tsParser, + ecmaVersion: 'latest', + sourceType: 'module', + globals: { ...globals.node }, + parserOptions: { + project: path.join(__dirname, 'tsconfig.json'), + tsconfigRootDir: __dirname, + }, + }, + + settings: { + 'import/resolver': { + node: { extensions: ['.js', '.mjs', '.ts'] }, + typescript: { + project: [path.join(__dirname, 'tsconfig.json'), path.join(__dirname, 'tsconfig.spec.json')], + alwaysTryTypes: true, + }, + }, + 'import/parsers': { + '@typescript-eslint/parser': ['.ts', '.tsx'], + }, + }, + + rules: { + 'import/no-unresolved': 'error', + 'import/extensions': ['error', 'ignorePackages', { ts: 'never', tsx: 'never', js: 'never', mjs: 'never' }], + 'import/order': [ + 'error', + { + groups: ['external', ['builtin', 'index', 'sibling', 'parent', 'internal'], 'object', 'type'], + alphabetize: { order: 'asc', caseInsensitive: true }, + 'newlines-between': 'always', + }, + ], + 'prefer-arrow-functions/prefer-arrow-functions': [ + 'error', + { + allowNamedFunctions: false, + classPropertiesAllowed: false, + disallowPrototype: false, + returnStyle: 'unchanged', + singleReturnOnly: false, + }, + ], + 'prefer-template': 'error', + 'no-nested-ternary': 'error', + 'no-implicit-coercion': ['error', { boolean: true }], + '@typescript-eslint/naming-convention': [ + 'error', + { selector: 'typeLike', format: ['PascalCase'] }, + { selector: 'enum', format: ['UPPER_CASE'] }, + ], + }, +}; + export default [ { - ignores: process.env.CI ? ['**/*.ejs', '**/dist/', '**/examples'] : ['**/*.ejs', '**/dist/'], + ignores: ['**/*.ejs', '**/dist/**', '**/examples/**', 'eslint.config.mjs', 'jest.config.mjs'], }, + ...fixupConfigRules( compat.extends( 'eslint:recommended', @@ -32,97 +97,45 @@ export default [ 'plugin:import/typescript', ), ), + { - plugins: { - '@typescript-eslint': fixupPluginRules(typescriptEslint), - 'prefer-arrow-functions': preferArrowFunctions, - import: fixupPluginRules(_import), - 'no-relative-import-paths': noRelativeImportPaths, - }, + files: ['**/*.ts', '**/*.tsx'], + ...shared, + }, + { + files: ['tests/**/*.{ts,tsx}', '**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}'], + plugins: { ...shared.plugins, jest: jestPlugin }, languageOptions: { - globals: { - ...globals.browser, - }, - - parser: tsParser, - ecmaVersion: 'latest', - sourceType: 'module', + ...shared.languageOptions, + globals: { ...shared.languageOptions.globals, ...jestGlobals }, }, - - settings: { - 'import/resolver': { - typescript: { - alwaysTryTypes: true, - project: './tsconfig.json', - }, - }, - - 'import/parsers': { - '@typescript-eslint/parser': ['.ts', '.tsx'], - }, - }, - + settings: shared.settings, rules: { - 'import/no-unresolved': 'error', - - 'import/order': [ - 'error', - { - groups: ['external', ['builtin', 'index', 'sibling', 'parent', 'internal'], 'object', 'type'], - 'newlines-between': 'always', - alphabetize: { - order: 'asc', - caseInsensitive: true, - }, - }, - ], - - 'no-relative-import-paths/no-relative-import-paths': [ - 'error', - { - allowSameFolder: false, - }, - ], - - 'prefer-arrow-functions/prefer-arrow-functions': [ - 'error', - { - allowNamedFunctions: false, - classPropertiesAllowed: false, - disallowPrototype: false, - returnStyle: 'unchanged', - singleReturnOnly: false, - }, - ], - - 'prefer-template': 'error', - 'no-nested-ternary': 'error', - 'no-implicit-coercion': ['error', { boolean: true }], - - '@typescript-eslint/naming-convention': [ - 'error', - { - selector: 'typeLike', - format: ['PascalCase'], - }, - { - selector: 'enum', - format: ['UPPER_CASE'], - }, - ], + ...shared.rules, + 'import/no-extraneous-dependencies': ['error', { devDependencies: true }], }, }, + { - files: ['**/.eslintrc.js'], + files: ['*.config.{ts,js,mjs,cjs}'], + languageOptions: { + ...shared.languageOptions, + parserOptions: { project: null }, + }, + rules: { 'import/no-unresolved': 'off' }, + }, + { + files: ['jest-ejs-transform.cjs'], languageOptions: { + sourceType: 'script', globals: { - ...globals.node, + module: 'readonly', + exports: 'readonly', + require: 'readonly', }, - - ecmaVersion: 5, - sourceType: 'commonjs', }, + rules: { 'no-undef': 'off' }, }, ]; diff --git a/examples/basics/fetch-decisions-stream.ts b/examples/basics/fetch-decisions-stream.ts index 6d9d992..dbb1ba7 100644 --- a/examples/basics/fetch-decisions-stream.ts +++ b/examples/basics/fetch-decisions-stream.ts @@ -1,5 +1,4 @@ -import CrowdSecBouncer from 'src/lib/bouncer'; -import { CrowdSecBouncerConfigurations } from 'src/lib/bouncer/types'; +import { CrowdSecBouncer, CrowdSecBouncerConfigurations } from '../../src'; /** * Example usage of fetching decisions stream. diff --git a/examples/basics/get-ip-remediation.ts b/examples/basics/get-ip-remediation.ts index 1453bd1..3fb1714 100644 --- a/examples/basics/get-ip-remediation.ts +++ b/examples/basics/get-ip-remediation.ts @@ -1,6 +1,5 @@ -import CrowdSecBouncer from 'src/lib/bouncer'; -import { CrowdSecBouncerConfigurations } from 'src/lib/bouncer/types'; -import { BOUNCER_KEYS } from 'src/lib/constants'; +import { CrowdSecBouncer, CrowdSecBouncerConfigurations } from '../../src'; +import { BOUNCER_KEYS } from '../../src/lib/constants'; /** * Example of basic usage of the CrowdSec Bouncer. diff --git a/examples/express-server/helpers/index.ts b/examples/express-server/helpers/index.ts index 3f43857..1c84594 100644 --- a/examples/express-server/helpers/index.ts +++ b/examples/express-server/helpers/index.ts @@ -2,8 +2,11 @@ import dotenv from 'dotenv'; import dotenvSafe from 'dotenv-safe'; import pino from 'pino'; -import path from 'path'; +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); export const getExcludedPaths = () => { // Skip favicon requests as each access to the page will trigger a request to /favicon.ico // and there is no need to apply remediation twice @@ -30,14 +33,14 @@ export const getLogger = () => { // Load and validate environment variables from .env file export const loadEnv = () => { dotenvSafe.config({ - path: path.resolve(__dirname, '../.env'), - example: path.resolve(__dirname, '../.env.example'), + path: resolve(__dirname, '../.env'), + example: resolve(__dirname, '../.env.example'), }); dotenv.config(); // Load and validate the .env file in the crowdsec folder (will override any duplicate values from the main .env) dotenvSafe.config({ - path: path.resolve(__dirname, '../crowdsec/.env'), - example: path.resolve(__dirname, '../crowdsec/.env.example'), + path: resolve(__dirname, '../crowdsec/.env'), + example: resolve(__dirname, '../crowdsec/.env.example'), }); - dotenv.config({ path: path.resolve(__dirname, '../crowdsec/.env') }); + dotenv.config({ path: resolve(__dirname, '../crowdsec/.env') }); }; diff --git a/examples/express-server/package.json b/examples/express-server/package.json index c49eabd..dde3568 100644 --- a/examples/express-server/package.json +++ b/examples/express-server/package.json @@ -1,36 +1,39 @@ { "name": "cs-nodejs-lib-tests", "version": "1.0.0", + "private": true, + "type": "module", "main": "server.ts", "scripts": { - "start": "ts-node server.ts", - "watch:src": "nodemon --watch server.ts --watch ../../src --ext ejs,ts,js --exec 'npm run pack-locally && npm update'", - "watch:dist": "nodemon --watch ../../dist --ext ejs,ts,js --exec ts-node server.ts", - "dev": "concurrently \"npm run watch:src\" \"npm run watch:dist\"", - "start-e2e": "CS_NO_COLOR=1 ts-node server.ts | tee -a tests/logs/crowdsec.log", - "pack-locally": "(cd ../../ && npm install && npm pack) && mv ../../crowdsec-nodejs-bouncer-*.tgz cs-nodejs-bouncer.tgz" + "start": "tsx server.ts", + "start-e2e": "CS_NO_COLOR=1 tsx server.ts | tee -a tests/logs/crowdsec.log", + "pack-locally": "(cd ../../ && npm run build && npm pack --silent) && mv ../../crowdsec-nodejs-bouncer-*.tgz ./cs-nodejs-bouncer.tgz", + "watch:all": "nodemon --watch ../../dist --watch server.ts --watch helpers --watch tests --ext js,ts,ejs --exec \"npm install --no-save ./cs-nodejs-bouncer.tgz && tsx server.ts\"", + "dev": "npm run pack-locally && npm install --no-save ./cs-nodejs-bouncer.tgz && npm run watch:all" }, "dependencies": { - "@crowdsec/nodejs-bouncer": "file:cs-nodejs-bouncer.tgz", - "@types/express": "^4.17.17", - "@types/express-session": "^1.18.0", - "@types/node-cron": "^3.0.11", + "@crowdsec/nodejs-bouncer": "file:./cs-nodejs-bouncer.tgz", "concurrently": "^9.1.0", "dotenv": "^16.4.5", "dotenv-safe": "^9.1.0", "express": "^4.18.2", "express-session": "^1.18.1", - "module-alias": "^2.2.3", "node-cron": "^3.0.3", "nodemon": "^3.1.7", "pino": "^9.5.0", - "ts-node": "^10.9.1", - "typescript": "^4.9.3" + "typescript": "^5.6.3" }, "devDependencies": { "@playwright/test": "^1.50.1", "@types/dotenv-safe": "^8.1.6", - "@types/node": "^22.13.4", - "prettier": "^3.3.3" + "@types/express": "^4.17.17", + "@types/express-session": "^1.18.0", + "@types/node": "^20", + "@types/node-cron": "^3.0.11", + "prettier": "^3.3.3", + "tsx": "^4.19.3" + }, + "engines": { + "node": ">=20" } } diff --git a/examples/express-server/playwright.config.ts b/examples/express-server/playwright.config.ts index f18da18..913e9f8 100644 --- a/examples/express-server/playwright.config.ts +++ b/examples/express-server/playwright.config.ts @@ -5,7 +5,12 @@ import { defineConfig, devices } from '@playwright/test'; */ import dotenv from 'dotenv'; -import path from 'path'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +// recreate __dirname for ESM +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); dotenv.config({ path: path.resolve(__dirname, 'crowdsec/.env') }); const currentDateTime = new Date().toISOString().replace(/[:.]/g, '_').slice(0, -1); diff --git a/examples/express-server/server.ts b/examples/express-server/server.ts index 7923cd8..cab6c36 100644 --- a/examples/express-server/server.ts +++ b/examples/express-server/server.ts @@ -2,9 +2,13 @@ import { CrowdSecBouncer, CrowdSecBouncerConfigurations } from '@crowdsec/nodejs import express from 'express'; import nodeCron from 'node-cron'; -import { getExcludedPaths, getLogger, loadEnv } from 'examples/express-server/helpers'; -import { getE2ETestConfig, getE2EExcludedPaths, addE2ERoutes } from 'examples/express-server/tests/helpers/base'; -import path from 'path'; +import { getExcludedPaths, getLogger, loadEnv } from './helpers'; +import { getE2ETestConfig, getE2EExcludedPaths, addE2ERoutes } from './tests/helpers/base'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); // Load and validate environment variables loadEnv(); @@ -83,7 +87,7 @@ app.use(async (req, res, next) => { // Serve a simple webpage ("home" page) app.get('/', (_req, res) => { - res.sendFile(path.join(__dirname, 'index.html')); + res.sendFile(join(__dirname, 'index.html')); }); // This cron job will fetch the decisions from the CrowdSec LAPI every 120 seconds diff --git a/examples/express-server/tests/constants.ts b/examples/express-server/tests/constants.ts index 9b523c2..761790b 100644 --- a/examples/express-server/tests/constants.ts +++ b/examples/express-server/tests/constants.ts @@ -1,3 +1,9 @@ +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + export const HOME_TITLE = 'CrowdSec Node.js bouncer test page'; export const BAN_TITLE = 'CrowdSec | Ban Wall'; export const CAPTCHA_TITLE = 'CrowdSec | Captcha Wall'; diff --git a/examples/express-server/tests/custom-configs-1.spec.ts b/examples/express-server/tests/custom-configs-1.spec.ts index 231284c..49fa0e6 100644 --- a/examples/express-server/tests/custom-configs-1.spec.ts +++ b/examples/express-server/tests/custom-configs-1.spec.ts @@ -1,11 +1,11 @@ import { test, expect } from '@playwright/test'; -import { E2E_ENDPOINT, LOG_PATH } from 'examples/express-server/tests/constants'; -import { getBouncedIp } from 'examples/express-server/tests/helpers/base'; -import { addIpDecision } from 'examples/express-server/tests/helpers/cscli'; -import { getFileContent } from 'examples/express-server/tests/helpers/log'; -import { wait } from 'examples/express-server/tests/helpers/time'; -import { removeCscliDecisions, setupCommon } from 'examples/express-server/tests/setup/common'; +import { E2E_ENDPOINT, LOG_PATH } from './constants'; +import { getBouncedIp } from './helpers/base'; +import { addIpDecision } from './helpers/cscli'; +import { getFileContent } from './helpers/log'; +import { wait } from './helpers/time'; +import { removeCscliDecisions, setupCommon } from './setup/common'; const TEST_NAME = 'custom-configs-1'; const bouncedIp = getBouncedIp(); diff --git a/examples/express-server/tests/custom-configs-2.spec.ts b/examples/express-server/tests/custom-configs-2.spec.ts index 602ebf3..93d81de 100644 --- a/examples/express-server/tests/custom-configs-2.spec.ts +++ b/examples/express-server/tests/custom-configs-2.spec.ts @@ -1,10 +1,10 @@ import { test, expect } from '@playwright/test'; -import { CAPTCHA_TITLE } from 'examples/express-server/tests/constants'; -import { getBouncedIp } from 'examples/express-server/tests/helpers/base'; -import { addIpDecision } from 'examples/express-server/tests/helpers/cscli'; -import { wait } from 'examples/express-server/tests/helpers/time'; -import { setupCommon } from 'examples/express-server/tests/setup/common'; +import { CAPTCHA_TITLE } from './constants'; +import { getBouncedIp } from './helpers/base'; +import { addIpDecision } from './helpers/cscli'; +import { wait } from './helpers/time'; +import { setupCommon } from './setup/common'; const TEST_NAME = 'custom-configs-2'; const bouncedIp = getBouncedIp(); diff --git a/examples/express-server/tests/helpers/base.ts b/examples/express-server/tests/helpers/base.ts index 6c1a5c3..c3ca185 100644 --- a/examples/express-server/tests/helpers/base.ts +++ b/examples/express-server/tests/helpers/base.ts @@ -1,7 +1,13 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { E2E_ENDPOINT } from 'examples/express-server/tests/constants'; +import { E2E_ENDPOINT } from '../constants'; import fs from 'fs'; -import path from 'path'; + +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +// recreate __dirname for ESM +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); export const getBouncedIp = (): string => { const bouncedIp = process.env.BOUNCED_IP ?? ''; diff --git a/examples/express-server/tests/live-mode.spec.ts b/examples/express-server/tests/live-mode.spec.ts index 54009ef..5b68f39 100644 --- a/examples/express-server/tests/live-mode.spec.ts +++ b/examples/express-server/tests/live-mode.spec.ts @@ -1,11 +1,11 @@ import { test, expect } from '@playwright/test'; -import { HOME_TITLE, BAN_TITLE, CAPTCHA_TITLE, E2E_ENDPOINT, LOG_PATH } from 'examples/express-server/tests/constants'; -import { getBouncedIp, getCaptchaPhrase } from 'examples/express-server/tests/helpers/base'; -import { addIpDecision, removeIpDecision } from 'examples/express-server/tests/helpers/cscli'; -import { getFileContent, deleteFileContent } from 'examples/express-server/tests/helpers/log'; -import { wait } from 'examples/express-server/tests/helpers/time'; -import { setupCommon, removeCscliDecisions } from 'examples/express-server/tests/setup/common'; +import { HOME_TITLE, BAN_TITLE, CAPTCHA_TITLE, E2E_ENDPOINT, LOG_PATH } from './constants'; +import { getBouncedIp, getCaptchaPhrase } from './helpers/base'; +import { addIpDecision, removeIpDecision } from './helpers/cscli'; +import { getFileContent, deleteFileContent } from './helpers/log'; +import { wait } from './helpers/time'; +import { setupCommon, removeCscliDecisions } from './setup/common'; const TEST_NAME = 'live-mode'; const bouncedIp = getBouncedIp(); diff --git a/examples/express-server/tests/setup/common.ts b/examples/express-server/tests/setup/common.ts index 448a007..da6bffc 100644 --- a/examples/express-server/tests/setup/common.ts +++ b/examples/express-server/tests/setup/common.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; import { spawnSync } from 'child_process'; -import { E2E_ENDPOINT, LOG_PATH } from 'examples/express-server/tests/constants'; -import { getFileContent, deleteFileContent } from 'examples/express-server/tests/helpers/log'; +import { E2E_ENDPOINT, LOG_PATH } from '../constants'; +import { getFileContent, deleteFileContent } from '../helpers/log'; export const removeCscliDecisions = () => { const command = ['exec', '-i', 'nodejs-cs-crowdsec', 'sh', '-c', `cscli decisions delete --origin cscli`]; diff --git a/examples/express-server/tests/stream-mode.spec.ts b/examples/express-server/tests/stream-mode.spec.ts index ac5b0a0..3250f38 100644 --- a/examples/express-server/tests/stream-mode.spec.ts +++ b/examples/express-server/tests/stream-mode.spec.ts @@ -1,11 +1,11 @@ import { test, expect } from '@playwright/test'; -import { BAN_TITLE, E2E_ENDPOINT, HOME_TITLE, LOG_PATH } from 'examples/express-server/tests/constants'; -import { getBouncedIp } from 'examples/express-server/tests/helpers/base'; -import { addIpDecision } from 'examples/express-server/tests/helpers/cscli'; -import { getFileContent } from 'examples/express-server/tests/helpers/log'; -import { wait } from 'examples/express-server/tests/helpers/time'; -import { setupCommon } from 'examples/express-server/tests/setup/common'; +import { BAN_TITLE, E2E_ENDPOINT, HOME_TITLE, LOG_PATH } from './constants'; +import { getBouncedIp } from './helpers/base'; +import { addIpDecision } from './helpers/cscli'; +import { getFileContent } from './helpers/log'; +import { wait } from './helpers/time'; +import { setupCommon } from './setup/common'; const TEST_NAME = 'stream-mode'; const bouncedIp = getBouncedIp(); diff --git a/examples/express-server/tsconfig.json b/examples/express-server/tsconfig.json index 347a498..2f4e286 100644 --- a/examples/express-server/tsconfig.json +++ b/examples/express-server/tsconfig.json @@ -1,7 +1,21 @@ { - "extends": "../../tsconfig.json", - "compilerOptions": { - "esModuleInterop": true, - "allowSyntheticDefaultImports": true - } + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Node", + "strict": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "skipLibCheck": true, + "noEmit": true, + "types": [ + "node", + "express", + "express-session", + "node-cron" + ] + }, + "include": [ + "./**/*.ts" + ] } diff --git a/jest-ejs-transform.cjs b/jest-ejs-transform.cjs new file mode 100644 index 0000000..ad2c8e0 --- /dev/null +++ b/jest-ejs-transform.cjs @@ -0,0 +1,12 @@ +/** + * Jest transformer for *.ejs files. + * Reads the file contents and turns it into a string export that works + * in CommonJS *or* ESM test files because Jest always evaluates the + * transform output in a CJS wrapper. + */ +module.exports = { + process(src) { + // CJS export is safe: `module.exports = '…';` + return { code: `module.exports = ${JSON.stringify(src)};` }; + }, +}; diff --git a/jest.config.mjs b/jest.config.mjs new file mode 100644 index 0000000..86110aa --- /dev/null +++ b/jest.config.mjs @@ -0,0 +1,24 @@ +// jest.config.mjs +import { createDefaultEsmPreset } from 'ts-jest'; + +/** @type {import('jest').Config} */ +const esmPreset = createDefaultEsmPreset(); + +export default { + ...esmPreset, + + // merge the preset's "transform" with our own rule + transform: { + ...esmPreset.transform, + '\\.ejs$': '/jest-ejs-transform.cjs', + }, + + collectCoverage: true, + coverageReporters: ['text', 'cobertura'], + testEnvironment: 'node', + testPathIgnorePatterns: ['/node_modules/', '/dist/', '/examples/'], + + moduleNameMapper: { + '^src/(.*)$': '/src/$1', + }, +}; diff --git a/jest.config.ts b/jest.config.ts deleted file mode 100644 index ed23597..0000000 --- a/jest.config.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { Config } from 'jest'; - -const config: Config = { - collectCoverage: true, - coverageReporters: ['text', 'cobertura'], - preset: 'ts-jest', - testEnvironment: 'node', - testPathIgnorePatterns: ['/node_modules/', '/dist/', '/examples/'], - transform: { - '^.+\\.(ts|tsx)$': 'ts-jest', - }, - moduleNameMapper: { - '^src/(.*)$': '/src/$1', - }, -}; - -export default config; diff --git a/package-lock.json b/package-lock.json index 02268b2..a8f93e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "cache-manager": "^6.1.3", "ip-address": "^10.0.0", + "keyv": "^5.3.4", "lodash": "^4.17.21", "pino": "^9.4.0", "pino-pretty": "^11.2.2", @@ -21,26 +22,33 @@ "@eslint/eslintrc": "^3.1.0", "@eslint/js": "^9.12.0", "@jest/globals": "^29.7.0", + "@types/jest": "^30.0.0", "@types/lodash": "^4.17.10", + "@types/node": "^20.19.8", "@typescript-eslint/eslint-plugin": "^8.24.0", "@typescript-eslint/parser": "^8.24.0", "eslint": "^9.12.0", "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jest": "^29.0.1", "eslint-plugin-no-relative-import-paths": "^1.5.5", "eslint-plugin-prefer-arrow-functions": "^3.4.1", "eslint-plugin-simple-import-sort": "^12.1.1", "globals": "^15.11.0", - "jest": "^29.7.0", + "jest": "^30.0.4", "nock": "^14.0.0-beta.4", "prettier": "^3.3.3", "prettier-plugin-ejs": "^1.0.3", - "ts-jest": "^29.2.5", + "ts-jest": "^29.4.0", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", + "tsup": "^8.3.0", "tsx": "^4.19.3", "typescript": "^5.6.3" + }, + "engines": { + "node": ">=20" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -66,114 +74,47 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz", - "integrity": "sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", + "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.0", - "@babel/parser": "^7.24.0", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.0", - "@babel/types": "^7.24.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.6", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -198,29 +139,32 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", + "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "@babel/parser": "^7.28.0", + "@babel/types": "^7.28.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -233,67 +177,45 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" }, "engines": { "node": ">=6.9.0" @@ -303,169 +225,68 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", - "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.0.tgz", - "integrity": "sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==", - "dev": true, - "dependencies": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.0", - "@babel/types": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@babel/parser": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "@babel/types": "^7.28.0" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz", - "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -509,6 +330,38 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", @@ -534,12 +387,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", - "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -620,6 +474,22 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", @@ -636,12 +506,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -651,58 +522,48 @@ } }, "node_modules/@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.0.tgz", - "integrity": "sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0", - "debug": "^4.3.1", - "globals": "^11.1.0" + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", + "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.0", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "version": "7.28.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz", + "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -712,7 +573,8 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", @@ -736,6 +598,40 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@emnapi/core": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.4.tgz", + "integrity": "sha512-A9CnAbC6ARNMKcIcrQwq6HeHCjpcBZ5wSx4U01WXCqEKlrzB9F9315WDNHkrs2xbx7YjjSxbUYxuN6EQzpcY2g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.4.tgz", + "integrity": "sha512-hHyapA4A3gPaDCNfiqyZUStTMqIkKRshqPIuDOXv1hcBnD4U3l8cP0T1HMCfGRxQ6V64TGCcoswChANyOAwbQg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.3.tgz", + "integrity": "sha512-8K5IFFsQqF9wQNJptGbS6FNKgUTsSRYnTqNCG1vPP8jFdjSv18n2mQfJpkt2Oibo9iBEzcDnDxNwKTzC7svlJw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", @@ -1382,48 +1278,151 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "license": "ISC", "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { "argparse": "^1.0.7", @@ -1491,174 +1490,196 @@ } }, "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.0.4.tgz", + "integrity": "sha512-tMLCDvBJBwPqMm4OAiuKm2uF5y5Qe26KgcMn+nrDSWpEW+eeFmqA0iO4zJfL16GP7gE3bUUQ3hIuUJ22AqVRnw==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", + "@jest/types": "30.0.1", "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", + "chalk": "^4.1.2", + "jest-message-util": "30.0.2", + "jest-util": "30.0.2", "slash": "^3.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "node_modules/@jest/console/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" + "@sinclair/typebox": "^0.34.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "node_modules/@jest/console/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", "@types/node": "*", - "jest-mock": "^29.7.0" + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "node_modules/@jest/console/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", "dev": true, - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" + "license": "MIT" + }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "node_modules/@jest/console/node_modules/jest-message-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.2.tgz", + "integrity": "sha512-vXywcxmr0SsKXF/bAD7t7nMamRvPuJkras00gqYeB1V0WllxZrbZ0paRr3XqpFU2sYYjD0qAaG2fRyn/CGZ0aw==", "dev": true, + "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3" + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.0.1", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "node_modules/@jest/console/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", + "@jest/types": "30.0.1", "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "node_modules/@jest/console/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@jest/console/node_modules/pretty-format": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz", + "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" + "@jest/schemas": "30.0.1", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "node_modules/@jest/core": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.0.4.tgz", + "integrity": "sha512-MWScSO9GuU5/HoWjpXAOBs6F/iobvK1XlioelgOM9St7S0Z5WTI9kjCQLPeo4eQRRYusyLW25/J7J5lbFkrYXw==", "dev": true, + "license": "MIT", "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", + "@jest/console": "30.0.4", + "@jest/pattern": "30.0.1", + "@jest/reporters": "30.0.4", + "@jest/test-result": "30.0.4", + "@jest/transform": "30.0.4", + "@jest/types": "30.0.1", "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-changed-files": "30.0.2", + "jest-config": "30.0.4", + "jest-haste-map": "30.0.2", + "jest-message-util": "30.0.2", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.0.2", + "jest-resolve-dependencies": "30.0.4", + "jest-runner": "30.0.4", + "jest-runtime": "30.0.4", + "jest-snapshot": "30.0.4", + "jest-util": "30.0.2", + "jest-validate": "30.0.2", + "jest-watcher": "30.0.4", + "micromatch": "^4.0.8", + "pretty-format": "30.0.2", + "slash": "^3.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -1669,3732 +1690,8534 @@ } } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@jest/core/node_modules/@jest/expect-utils": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.4.tgz", + "integrity": "sha512-EgXecHDNfANeqOkcak0DxsoVI4qkDUsR7n/Lr2vtmTBjwLPBnnPOF71S11Q8IObWzxm2QgQoY6f9hzrRD3gHRA==", "dev": true, + "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.27.8" + "@jest/get-type": "30.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "node_modules/@jest/core/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" + "@sinclair/typebox": "^0.34.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "node_modules/@jest/core/node_modules/@jest/transform": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.4.tgz", + "integrity": "sha512-atvy4hRph/UxdCIBp+UB2jhEA/jJiUeGZ7QPgBi9jUUKNgi3WEoMXGNG7zbbELG2+88PMabUNCDchmqgJy3ELg==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "@babel/core": "^7.27.4", + "@jest/types": "30.0.1", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.0", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.2", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "node_modules/@jest/core/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "node_modules/@jest/core/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, + "license": "MIT" + }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@jest/core/node_modules/babel-plugin-istanbul": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", + "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz", - "integrity": "sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw==", + "node_modules/@jest/core/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/expect": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.4.tgz", + "integrity": "sha512-dDLGjnP2cKbEppxVICxI/Uf4YemmGMPNy0QytCbfafbpYk9AFQsxb8Uyrxii0RPK7FWgLGlSem+07WirwS3cFQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jest/expect-utils": "30.0.4", + "@jest/get-type": "30.0.1", + "jest-matcher-utils": "30.0.4", + "jest-message-util": "30.0.2", + "jest-mock": "30.0.2", + "jest-util": "30.0.2" }, "engines": { - "node": ">=6.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@jest/core/node_modules/jest-diff": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.4.tgz", + "integrity": "sha512-TSjceIf6797jyd+R64NXqicttROD+Qf98fex7CowmlSn7f8+En0da1Dglwr1AXxDtVizoxXYZBlUQwNhoOXkNw==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "pretty-format": "30.0.2" + }, "engines": { - "node": ">=6.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "node_modules/@jest/core/node_modules/jest-haste-map": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.2.tgz", + "integrity": "sha512-telJBKpNLeCb4MaX+I5k496556Y2FiKR/QLZc0+MGBYl4k3OO0472drlV2LUe7c1Glng5HuAu+5GLYp//GpdOQ==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.1", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "jest-worker": "30.0.2", + "micromatch": "^4.0.8", + "walker": "^1.0.8" + }, "engines": { - "node": ">=6.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.23.tgz", - "integrity": "sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==", + "node_modules/@jest/core/node_modules/jest-matcher-utils": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.4.tgz", + "integrity": "sha512-ubCewJ54YzeAZ2JeHHGVoU+eDIpQFsfPQs0xURPWoNiO42LGJ+QGgfSf+hFIRplkZDkhH5MOvuxHKXRTUU3dUQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "jest-diff": "30.0.4", + "pretty-format": "30.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@keyv/serialize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.1.tgz", - "integrity": "sha512-kKXeynfORDGPUEEl2PvTExM2zs+IldC6ZD8jPcfvI351MDNtfMlw9V9s4XZXuJNDK2qR5gbEKxRyoYx3quHUVQ==", + "node_modules/@jest/core/node_modules/jest-message-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.2.tgz", + "integrity": "sha512-vXywcxmr0SsKXF/bAD7t7nMamRvPuJkras00gqYeB1V0WllxZrbZ0paRr3XqpFU2sYYjD0qAaG2fRyn/CGZ0aw==", + "dev": true, "license": "MIT", "dependencies": { - "buffer": "^6.0.3" + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.0.1", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@jest/core/node_modules/jest-mock": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.2.tgz", + "integrity": "sha512-PnZOHmqup/9cT/y+pXIVbbi8ID6U1XHRmbvR7MvUy4SLqhCbwpkmXhLbsWbGewHrV5x/1bF7YDjs+x24/QSvFA==", "dev": true, + "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@jest/types": "30.0.1", + "@types/node": "*", + "jest-util": "30.0.2" }, "engines": { - "node": ">= 8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@jest/core/node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@jest/core/node_modules/jest-snapshot": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.4.tgz", + "integrity": "sha512-S/8hmSkeUib8WRUq9pWEb5zMfsOjiYWDWzFzKnjX7eDyKKgimsu9hcmsUEg8a7dPAw8s/FacxsXquq71pDgPjQ==", "dev": true, + "license": "MIT", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.0.4", + "@jest/get-type": "30.0.1", + "@jest/snapshot-utils": "30.0.4", + "@jest/transform": "30.0.4", + "@jest/types": "30.0.1", + "babel-preset-current-node-syntax": "^1.1.0", + "chalk": "^4.1.2", + "expect": "30.0.4", + "graceful-fs": "^4.2.11", + "jest-diff": "30.0.4", + "jest-matcher-utils": "30.0.4", + "jest-message-util": "30.0.2", + "jest-util": "30.0.2", + "pretty-format": "30.0.2", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/core/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": ">= 8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@nolyfill/is-core-module": { - "version": "1.0.39", - "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", - "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "node_modules/@jest/core/node_modules/jest-worker": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.2.tgz", + "integrity": "sha512-RN1eQmx7qSLFA+o9pfJKlqViwL5wt+OL3Vff/A+/cPsmuw7NPwfgl33AP+/agRmHzPOFgXviRycR9kYwlcRQXg==", "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.0.2", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, "engines": { - "node": ">=12.4.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "node_modules/@jest/core/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, - "dependencies": { - "type-detect": "4.0.8" + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "node_modules/@jest/core/node_modules/pretty-format": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz", + "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==", "dev": true, + "license": "MIT", "dependencies": { - "@sinonjs/commons": "^3.0.0" + "@jest/schemas": "30.0.1", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "node_modules/@jest/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "node_modules/@jest/core/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.0.0" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "node_modules/@jest/core/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@types/babel__traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", - "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "node_modules/@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "dependencies": { - "@types/node": "*" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "dependencies": { - "@types/istanbul-lib-coverage": "*" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "dependencies": { - "@types/istanbul-lib-report": "*" + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/@types/lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==", - "dev": true + "node_modules/@jest/get-type": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.0.1.tgz", + "integrity": "sha512-AyYdemXCptSRFirI5EPazNxyPwAL0jXt3zceFjaj8NFiKP9pOi0bfXonf6qkf82z2t3QWPeLCWWw4stPBzctLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } }, - "node_modules/@types/node": { - "version": "20.11.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.21.tgz", - "integrity": "sha512-/ySDLGscFPNasfqStUuWWPfL78jompfIoVzLJPVVAHBh6rpG68+pI2Gk+fNLeI8/f1yPYL4s46EleVIc20F1Ow==", + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "dependencies": { - "undici-types": "~5.26.4" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true - }, - "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "node_modules/@jest/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", "dev": true, + "license": "MIT", "dependencies": { - "@types/yargs-parser": "*" + "@types/node": "*", + "jest-regex-util": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true + "node_modules/@jest/pattern/node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.24.0.tgz", - "integrity": "sha512-aFcXEJJCI4gUdXgoo/j9udUYIHgF23MFkg09LFz2dzEmU0+1Plk4rQWv/IYKvPHAtlkkGoB3m5e6oUp+JPsNaQ==", + "node_modules/@jest/reporters": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.0.4.tgz", + "integrity": "sha512-6ycNmP0JSJEEys1FbIzHtjl9BP0tOZ/KN6iMeAKrdvGmUsa1qfRdlQRUDKJ4P84hJ3xHw1yTqJt4fvPNHhyE+g==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.24.0", - "@typescript-eslint/type-utils": "8.24.0", - "@typescript-eslint/utils": "8.24.0", - "@typescript-eslint/visitor-keys": "8.24.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "30.0.4", + "@jest/test-result": "30.0.4", + "@jest/transform": "30.0.4", + "@jest/types": "30.0.1", + "@jridgewell/trace-mapping": "^0.3.25", + "@types/node": "*", + "chalk": "^4.1.2", + "collect-v8-coverage": "^1.0.2", + "exit-x": "^0.2.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^5.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "30.0.2", + "jest-util": "30.0.2", + "jest-worker": "30.0.2", + "slash": "^3.0.0", + "string-length": "^4.0.2", + "v8-to-istanbul": "^9.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@typescript-eslint/parser": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.24.0.tgz", - "integrity": "sha512-MFDaO9CYiard9j9VepMNa9MTcqVvSny2N4hkY6roquzj8pdCBRENhErrteaQuu7Yjn1ppk0v1/ZF9CG3KIlrTA==", + "node_modules/@jest/reporters/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.24.0", - "@typescript-eslint/types": "8.24.0", - "@typescript-eslint/typescript-estree": "8.24.0", - "@typescript-eslint/visitor-keys": "8.24.0", - "debug": "^4.3.4" + "@sinclair/typebox": "^0.34.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.24.0.tgz", - "integrity": "sha512-HZIX0UByphEtdVBKaQBgTDdn9z16l4aTUz8e8zPQnyxwHBtf5vtl1L+OhH+m1FGV9DrRmoDuYKqzVrvWDcDozw==", + "node_modules/@jest/reporters/node_modules/@jest/transform": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.4.tgz", + "integrity": "sha512-atvy4hRph/UxdCIBp+UB2jhEA/jJiUeGZ7QPgBi9jUUKNgi3WEoMXGNG7zbbELG2+88PMabUNCDchmqgJy3ELg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.24.0", - "@typescript-eslint/visitor-keys": "8.24.0" + "@babel/core": "^7.27.4", + "@jest/types": "30.0.1", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.0", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.2", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.24.0.tgz", - "integrity": "sha512-8fitJudrnY8aq0F1wMiPM1UUgiXQRJ5i8tFjq9kGfRajU+dbPyOuHbl0qRopLEidy0MwqgTHDt6CnSeXanNIwA==", + "node_modules/@jest/reporters/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.24.0", - "@typescript-eslint/utils": "8.24.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@typescript-eslint/types": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.24.0.tgz", - "integrity": "sha512-VacJCBTyje7HGAw7xp11q439A+zeGG0p0/p2zsZwpnMzjPB5WteaWqt4g2iysgGFafrqvyLWqq6ZPZAOCoefCw==", + "node_modules/@jest/reporters/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.24.0.tgz", - "integrity": "sha512-ITjYcP0+8kbsvT9bysygfIfb+hBj6koDsu37JZG7xrCiy3fPJyNmfVtaGsgTUSEuTzcvME5YI5uyL5LD1EV5ZQ==", + "node_modules/@jest/reporters/node_modules/babel-plugin-istanbul": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", + "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jest/reporters/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", "dependencies": { - "@typescript-eslint/types": "8.24.0", - "@typescript-eslint/visitor-keys": "8.24.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.0.1" + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/utils": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.24.0.tgz", - "integrity": "sha512-07rLuUBElvvEb1ICnafYWr4hk8/U7X9RDCOqd9JcAMtjh/9oRmcfN4yGzbPVirgMR0+HLVHehmu19CWeh7fsmQ==", + "node_modules/@jest/reporters/node_modules/jest-haste-map": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.2.tgz", + "integrity": "sha512-telJBKpNLeCb4MaX+I5k496556Y2FiKR/QLZc0+MGBYl4k3OO0472drlV2LUe7c1Glng5HuAu+5GLYp//GpdOQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.24.0", - "@typescript-eslint/types": "8.24.0", - "@typescript-eslint/typescript-estree": "8.24.0" + "@jest/types": "30.0.1", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "jest-worker": "30.0.2", + "micromatch": "^4.0.8", + "walker": "^1.0.8" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.24.0.tgz", - "integrity": "sha512-kArLq83QxGLbuHrTMoOEWO+l2MwsNS2TGISEdx8xgqpkbytB07XmlQyQdNDrCc1ecSqx0cnmhGvpX+VBwqqSkg==", + "node_modules/@jest/reporters/node_modules/jest-message-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.2.tgz", + "integrity": "sha512-vXywcxmr0SsKXF/bAD7t7nMamRvPuJkras00gqYeB1V0WllxZrbZ0paRr3XqpFU2sYYjD0qAaG2fRyn/CGZ0aw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.24.0", - "eslint-visitor-keys": "^4.2.0" + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.0.1", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "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==", + "node_modules/@jest/reporters/node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "node_modules/@jest/reporters/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", + "dev": true, + "license": "MIT", "dependencies": { - "event-target-shim": "^5.0.0" + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": ">=6.5" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "node_modules/@jest/reporters/node_modules/jest-worker": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.2.tgz", + "integrity": "sha512-RN1eQmx7qSLFA+o9pfJKlqViwL5wt+OL3Vff/A+/cPsmuw7NPwfgl33AP+/agRmHzPOFgXviRycR9kYwlcRQXg==", "dev": true, - "bin": { - "acorn": "bin/acorn" + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.0.2", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" }, "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "node_modules/@jest/reporters/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.4.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@jest/reporters/node_modules/pretty-format": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz", + "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@jest/schemas": "30.0.1", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@jest/reporters/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, + "license": "ISC", "engines": { - "node": ">=8" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/ansi-regex": { + "node_modules/@jest/reporters/node_modules/write-file-atomic": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, "engines": { - "node": ">=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/@jest/snapshot-utils": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.0.4.tgz", + "integrity": "sha512-BEpX8M/Y5lG7MI3fmiO+xCnacOrVsnbqVrcDZIT8aSGkKV1w2WwvRQxSWw5SIS8ozg7+h8tSj5EO1Riqqxcdag==", "dev": true, + "license": "MIT", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@jest/types": "30.0.1", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" }, "engines": { - "node": ">= 8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "node_modules/@jest/snapshot-utils/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "@sinclair/typebox": "^0.34.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "node_modules/@jest/snapshot-utils/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "node_modules/@jest/snapshot-utils/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "node_modules/@jest/test-result": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.0.4.tgz", + "integrity": "sha512-Mfpv8kjyKTHqsuu9YugB6z1gcdB3TSSOaKlehtVaiNlClMkEHY+5ZqCY2CrEE3ntpBMlstX/ShDAf84HKWsyIw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "@jest/console": "30.0.4", + "@jest/types": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "node_modules/@jest/test-result/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "@sinclair/typebox": "^0.34.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "node_modules/@jest/test-result/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", - "dev": true + "node_modules/@jest/test-result/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "node_modules/@jest/test-sequencer": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.0.4.tgz", + "integrity": "sha512-bj6ePmqi4uxAE8EHE0Slmk5uBYd9Vd/PcVt06CsBxzH4bbA8nGsI1YbXl/NH+eii4XRtyrRx+Cikub0x8H4vDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.0.4", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.2", + "slash": "^3.0.0" + }, "engines": { - "node": ">=8.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "node_modules/@jest/test-sequencer/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, + "license": "MIT", "dependencies": { - "possible-typed-array-names": "^1.0.0" + "@sinclair/typebox": "^0.34.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "node_modules/@jest/test-sequencer/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "node_modules/@jest/test-sequencer/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, + "license": "MIT" + }, + "node_modules/@jest/test-sequencer/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "node_modules/@jest/test-sequencer/node_modules/jest-haste-map": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.2.tgz", + "integrity": "sha512-telJBKpNLeCb4MaX+I5k496556Y2FiKR/QLZc0+MGBYl4k3OO0472drlV2LUe7c1Glng5HuAu+5GLYp//GpdOQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "@jest/types": "30.0.1", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "jest-worker": "30.0.2", + "micromatch": "^4.0.8", + "walker": "^1.0.8" }, "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/@jest/test-sequencer/node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "node_modules/@jest/test-sequencer/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "node_modules/@jest/test-sequencer/node_modules/jest-worker": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.2.tgz", + "integrity": "sha512-RN1eQmx7qSLFA+o9pfJKlqViwL5wt+OL3Vff/A+/cPsmuw7NPwfgl33AP+/agRmHzPOFgXviRycR9kYwlcRQXg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.0.2", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "node_modules/@jest/test-sequencer/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/@jest/test-sequencer/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "dependencies": { - "fill-range": "^7.1.1" + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", "dev": true, + "license": "MIT", "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, - "dependencies": { - "node-int64": "^0.4.0" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", + "dev": true, + "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/cache-manager": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-6.1.3.tgz", - "integrity": "sha512-IcBseSv1GquLxlTb1nH5KhOQQwwOjMC5hkBras+8zTYD/bRSCgT9bIah1DZ+4eKc3vcqqYtfUCI5pYvOHmDXtw==", + "node_modules/@keyv/serialize": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.3.tgz", + "integrity": "sha512-qnEovoOp5Np2JDGonIDL6Ayihw0RhnRh6vxPuHo4RDn1UOzwEo4AeIfpL6UGIrsceWrCMiVPgwRjbHu4vYFc3g==", "license": "MIT", "dependencies": { - "keyv": "^5.2.1" + "buffer": "^6.0.3" } }, - "node_modules/cache-manager/node_modules/keyv": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.2.1.tgz", - "integrity": "sha512-tpIgCaY02VCW2Pz0zAn4guyct+IeH6Mb5wZdOvpe4oqXeQOJO0C3Wo8fTnf7P3ZD83Vr9kghbkNmzG3lTOhy/A==", + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@keyv/serialize": "*" + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz", + "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.1.tgz", + "integrity": "sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.45.1.tgz", + "integrity": "sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.45.1.tgz", + "integrity": "sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.45.1.tgz", + "integrity": "sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.45.1.tgz", + "integrity": "sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.45.1.tgz", + "integrity": "sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.45.1.tgz", + "integrity": "sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.45.1.tgz", + "integrity": "sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.45.1.tgz", + "integrity": "sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.45.1.tgz", + "integrity": "sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.45.1.tgz", + "integrity": "sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.45.1.tgz", + "integrity": "sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.45.1.tgz", + "integrity": "sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.45.1.tgz", + "integrity": "sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.45.1.tgz", + "integrity": "sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.45.1.tgz", + "integrity": "sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.45.1.tgz", + "integrity": "sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.45.1.tgz", + "integrity": "sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.45.1.tgz", + "integrity": "sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.45.1.tgz", + "integrity": "sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@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/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^30.0.0", + "pretty-format": "^30.0.0" + } + }, + "node_modules/@types/jest/node_modules/@jest/expect-utils": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.4.tgz", + "integrity": "sha512-EgXecHDNfANeqOkcak0DxsoVI4qkDUsR7n/Lr2vtmTBjwLPBnnPOF71S11Q8IObWzxm2QgQoY6f9hzrRD3gHRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@types/jest/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@types/jest/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@types/jest/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/jest/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@types/jest/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@types/jest/node_modules/expect": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.4.tgz", + "integrity": "sha512-dDLGjnP2cKbEppxVICxI/Uf4YemmGMPNy0QytCbfafbpYk9AFQsxb8Uyrxii0RPK7FWgLGlSem+07WirwS3cFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "30.0.4", + "@jest/get-type": "30.0.1", + "jest-matcher-utils": "30.0.4", + "jest-message-util": "30.0.2", + "jest-mock": "30.0.2", + "jest-util": "30.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@types/jest/node_modules/jest-diff": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.4.tgz", + "integrity": "sha512-TSjceIf6797jyd+R64NXqicttROD+Qf98fex7CowmlSn7f8+En0da1Dglwr1AXxDtVizoxXYZBlUQwNhoOXkNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "pretty-format": "30.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@types/jest/node_modules/jest-matcher-utils": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.4.tgz", + "integrity": "sha512-ubCewJ54YzeAZ2JeHHGVoU+eDIpQFsfPQs0xURPWoNiO42LGJ+QGgfSf+hFIRplkZDkhH5MOvuxHKXRTUU3dUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "jest-diff": "30.0.4", + "pretty-format": "30.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@types/jest/node_modules/jest-message-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.2.tgz", + "integrity": "sha512-vXywcxmr0SsKXF/bAD7t7nMamRvPuJkras00gqYeB1V0WllxZrbZ0paRr3XqpFU2sYYjD0qAaG2fRyn/CGZ0aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.0.1", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@types/jest/node_modules/jest-mock": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.2.tgz", + "integrity": "sha512-PnZOHmqup/9cT/y+pXIVbbi8ID6U1XHRmbvR7MvUy4SLqhCbwpkmXhLbsWbGewHrV5x/1bF7YDjs+x24/QSvFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.1", + "@types/node": "*", + "jest-util": "30.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@types/jest/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@types/jest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@types/jest/node_modules/pretty-format": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz", + "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.1", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.19.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.8.tgz", + "integrity": "sha512-HzbgCY53T6bfu4tT7Aq3TvViJyHjLjPNaAS3HOuMc9pw97KHsUtXNX4L+wu59g1WnjsZSko35MbEqnO58rihhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.24.0.tgz", + "integrity": "sha512-aFcXEJJCI4gUdXgoo/j9udUYIHgF23MFkg09LFz2dzEmU0+1Plk4rQWv/IYKvPHAtlkkGoB3m5e6oUp+JPsNaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.24.0", + "@typescript-eslint/type-utils": "8.24.0", + "@typescript-eslint/utils": "8.24.0", + "@typescript-eslint/visitor-keys": "8.24.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.24.0.tgz", + "integrity": "sha512-MFDaO9CYiard9j9VepMNa9MTcqVvSny2N4hkY6roquzj8pdCBRENhErrteaQuu7Yjn1ppk0v1/ZF9CG3KIlrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.24.0", + "@typescript-eslint/types": "8.24.0", + "@typescript-eslint/typescript-estree": "8.24.0", + "@typescript-eslint/visitor-keys": "8.24.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": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.24.0.tgz", + "integrity": "sha512-HZIX0UByphEtdVBKaQBgTDdn9z16l4aTUz8e8zPQnyxwHBtf5vtl1L+OhH+m1FGV9DrRmoDuYKqzVrvWDcDozw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.24.0", + "@typescript-eslint/visitor-keys": "8.24.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.24.0.tgz", + "integrity": "sha512-8fitJudrnY8aq0F1wMiPM1UUgiXQRJ5i8tFjq9kGfRajU+dbPyOuHbl0qRopLEidy0MwqgTHDt6CnSeXanNIwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.24.0", + "@typescript-eslint/utils": "8.24.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.24.0.tgz", + "integrity": "sha512-VacJCBTyje7HGAw7xp11q439A+zeGG0p0/p2zsZwpnMzjPB5WteaWqt4g2iysgGFafrqvyLWqq6ZPZAOCoefCw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.24.0.tgz", + "integrity": "sha512-ITjYcP0+8kbsvT9bysygfIfb+hBj6koDsu37JZG7xrCiy3fPJyNmfVtaGsgTUSEuTzcvME5YI5uyL5LD1EV5ZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.24.0", + "@typescript-eslint/visitor-keys": "8.24.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" + }, + "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 <5.8.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.24.0.tgz", + "integrity": "sha512-07rLuUBElvvEb1ICnafYWr4hk8/U7X9RDCOqd9JcAMtjh/9oRmcfN4yGzbPVirgMR0+HLVHehmu19CWeh7fsmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.24.0", + "@typescript-eslint/types": "8.24.0", + "@typescript-eslint/typescript-estree": "8.24.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.24.0.tgz", + "integrity": "sha512-kArLq83QxGLbuHrTMoOEWO+l2MwsNS2TGISEdx8xgqpkbytB07XmlQyQdNDrCc1ecSqx0cnmhGvpX+VBwqqSkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.24.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "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==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/babel-jest": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.0.4.tgz", + "integrity": "sha512-UjG2j7sAOqsp2Xua1mS/e+ekddkSu3wpf4nZUSvXNHuVWdaOUXQ77+uyjJLDE9i0atm5x4kds8K9yb5lRsRtcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "30.0.4", + "@types/babel__core": "^7.20.5", + "babel-plugin-istanbul": "^7.0.0", + "babel-preset-jest": "30.0.1", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0" + } + }, + "node_modules/babel-jest/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-jest/node_modules/@jest/transform": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.4.tgz", + "integrity": "sha512-atvy4hRph/UxdCIBp+UB2jhEA/jJiUeGZ7QPgBi9jUUKNgi3WEoMXGNG7zbbELG2+88PMabUNCDchmqgJy3ELg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.0.1", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.0", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.2", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-jest/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-jest/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-jest/node_modules/babel-plugin-istanbul": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", + "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/babel-jest/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-jest/node_modules/jest-haste-map": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.2.tgz", + "integrity": "sha512-telJBKpNLeCb4MaX+I5k496556Y2FiKR/QLZc0+MGBYl4k3OO0472drlV2LUe7c1Glng5HuAu+5GLYp//GpdOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.1", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "jest-worker": "30.0.2", + "micromatch": "^4.0.8", + "walker": "^1.0.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" + } + }, + "node_modules/babel-jest/node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-jest/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-jest/node_modules/jest-worker": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.2.tgz", + "integrity": "sha512-RN1eQmx7qSLFA+o9pfJKlqViwL5wt+OL3Vff/A+/cPsmuw7NPwfgl33AP+/agRmHzPOFgXviRycR9kYwlcRQXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.0.2", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-jest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/babel-jest/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/babel-jest/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.0.1.tgz", + "integrity": "sha512-zTPME3pI50NsFW8ZBaVIOeAxzEY7XHlmWeXXu9srI+9kNfzCUTy8MFan46xOGZY8NZThMqq+e3qZUKsvXbasnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", + "@types/babel__core": "^7.20.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.0.1.tgz", + "integrity": "sha512-+YHejD5iTWI46cZmcc/YtX4gaKBtdqCHCVfuVinizVpbmyjO3zYmeuyFdfA8duRqQZfgCAMlsfmkVbJ+e2MAJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "30.0.1", + "babel-preset-current-node-syntax": "^1.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/bundle-require": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz", + "integrity": "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "load-tsconfig": "^0.2.3" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.18" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cache-manager": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-6.1.3.tgz", + "integrity": "sha512-IcBseSv1GquLxlTb1nH5KhOQQwwOjMC5hkBras+8zTYD/bRSCgT9bIah1DZ+4eKc3vcqqYtfUCI5pYvOHmDXtw==", + "license": "MIT", + "dependencies": { + "keyv": "^5.2.1" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/callsites": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001727", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", + "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz", + "integrity": "sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", + "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.187", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.187.tgz", + "integrity": "sha512-cl5Jc9I0KGUoOoSbxvTywTa40uspGJt/BDBoDLoxJRSBpWh4FFXBsjNRHfQrONsV/OoEjDfHUmZQa2d6Ze4YgA==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz", + "integrity": "sha512-3d3JRbwsCLJsYgvb6NuWEG44jjPSOMuS73L/6+7BZuoKm3W+qXnSoIYVHi8dG7Qcg4inAY4jbzkZ7MnskePeDg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", + "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.1", + "@esbuild/android-arm": "0.25.1", + "@esbuild/android-arm64": "0.25.1", + "@esbuild/android-x64": "0.25.1", + "@esbuild/darwin-arm64": "0.25.1", + "@esbuild/darwin-x64": "0.25.1", + "@esbuild/freebsd-arm64": "0.25.1", + "@esbuild/freebsd-x64": "0.25.1", + "@esbuild/linux-arm": "0.25.1", + "@esbuild/linux-arm64": "0.25.1", + "@esbuild/linux-ia32": "0.25.1", + "@esbuild/linux-loong64": "0.25.1", + "@esbuild/linux-mips64el": "0.25.1", + "@esbuild/linux-ppc64": "0.25.1", + "@esbuild/linux-riscv64": "0.25.1", + "@esbuild/linux-s390x": "0.25.1", + "@esbuild/linux-x64": "0.25.1", + "@esbuild/netbsd-arm64": "0.25.1", + "@esbuild/netbsd-x64": "0.25.1", + "@esbuild/openbsd-arm64": "0.25.1", + "@esbuild/openbsd-x64": "0.25.1", + "@esbuild/sunos-x64": "0.25.1", + "@esbuild/win32-arm64": "0.25.1", + "@esbuild/win32-ia32": "0.25.1", + "@esbuild/win32-x64": "0.25.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", + "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.6.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.12.0", + "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.5", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.1.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz", + "integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==", + "dev": true, + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.3.5", + "enhanced-resolve": "^5.15.0", + "eslint-module-utils": "^2.8.1", + "fast-glob": "^3.3.2", + "get-tsconfig": "^4.7.5", + "is-bun-module": "^1.0.2", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "dev": true, + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-import/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/eslint-plugin-jest": { + "version": "29.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.0.1.tgz", + "integrity": "sha512-EE44T0OSMCeXhDrrdsbKAhprobKkPtJTbQz5yEktysNpHeDZTAL1SfDTNKmcFfJkY6yrQLtTKZALrD3j/Gpmiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.0.0" + }, + "engines": { + "node": "^20.12.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-no-relative-import-paths": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-relative-import-paths/-/eslint-plugin-no-relative-import-paths-1.5.5.tgz", + "integrity": "sha512-UjudFFdBbv93v0CsVdEKcMLbBzRIjeK2PubTctX57tgnHxZcMj1Jm8lDBWoETnPxk0S5g5QLSltEM+511yL4+w==", + "dev": true + }, + "node_modules/eslint-plugin-prefer-arrow-functions": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prefer-arrow-functions/-/eslint-plugin-prefer-arrow-functions-3.4.1.tgz", + "integrity": "sha512-c8NP0E8xpkRqDq2eDSRr+wA4jwkwOEVNnZx4YY3O0V9M7OhtKdQIj5zmzIXwu+ueURmbwYrnz65sEoLLoIVZpg==", + "dev": true, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "eslint": ">=8.0.0" + } + }, + "node_modules/eslint-plugin-simple-import-sort": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.1.tgz", + "integrity": "sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==", + "dev": true, + "peerDependencies": { + "eslint": ">=5.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "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==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "dev": true, + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-copy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-redact": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", + "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fix-dts-default-cjs-exports": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fix-dts-default-cjs-exports/-/fix-dts-default-cjs-exports-1.0.1.tgz", + "integrity": "sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "magic-string": "^0.30.17", + "mlly": "^1.7.4", + "rollup": "^4.34.8" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flat-cache/node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", + "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "15.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", + "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ip-address": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.0.tgz", + "integrity": "sha512-PphFaoy0TyGdIGpmd35iA22j/3Ay+84F+4f6Rk7lAOusu7NiAQd5qgDfmT8flQt3+d5L8EwfAoKwfrtTPjt9Jg==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz", + "integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==", + "dev": true, + "dependencies": { + "semver": "^7.6.3" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001591", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz", - "integrity": "sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==", + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "ansi-styles": "^4.1.0", + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, "engines": { "node": ">=10" } }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=12" + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": ">=10" } }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true + "node_modules/jake/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=7.0.0" + "node": "*" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "node_modules/jest": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.0.4.tgz", + "integrity": "sha512-9QE0RS4WwTj/TtTC4h/eFVmFAhGNVerSB9XpJh8sqaXlP73ILcPcZ7JWjjEtJJe2m8QyBLKKfPQuK+3F+Xij/g==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" + "@jest/core": "30.0.4", + "@jest/types": "30.0.1", + "import-local": "^3.2.0", + "jest-cli": "30.0.4" }, "bin": { - "create-jest": "bin/create-jest.js" + "jest": "bin/jest.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/jest-changed-files": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.0.2.tgz", + "integrity": "sha512-Ius/iRST9FKfJI+I+kpiDh8JuUlAISnRszF9ixZDIqJF17FckH5sOzKC8a0wd0+D+8em5ADRHA5V5MnfeDk2WA==", "dev": true, + "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "execa": "^5.1.1", + "jest-util": "30.0.2", + "p-limit": "^3.1.0" }, "engines": { - "node": ">= 8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "node_modules/jest-changed-files/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "@sinclair/typebox": "^0.34.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "node_modules/jest-changed-files/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-changed-files/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-changed-files/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "node_modules/jest-circus": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.0.4.tgz", + "integrity": "sha512-o6UNVfbXbmzjYgmVPtSQrr5xFZCtkDZGdTlptYvGFSN80RuOOlTe73djvMrs+QAuSERZWcHBNIOMH+OEqvjWuw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "@jest/environment": "30.0.4", + "@jest/expect": "30.0.4", + "@jest/test-result": "30.0.4", + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "co": "^4.6.0", + "dedent": "^1.6.0", + "is-generator-fn": "^2.1.0", + "jest-each": "30.0.2", + "jest-matcher-utils": "30.0.4", + "jest-message-util": "30.0.2", + "jest-runtime": "30.0.4", + "jest-snapshot": "30.0.4", + "jest-util": "30.0.2", + "p-limit": "^3.1.0", + "pretty-format": "30.0.2", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "node_modules/jest-circus/node_modules/@jest/environment": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.0.4.tgz", + "integrity": "sha512-5NT+sr7ZOb8wW7C4r7wOKnRQ8zmRWQT2gW4j73IXAKp5/PX1Z8MCStBLQDYfIG3n1Sw0NRfYGdp0iIPVooBAFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "30.0.4", + "@jest/types": "30.0.1", + "@types/node": "*", + "jest-mock": "30.0.2" + }, "engines": { - "node": "*" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "node_modules/jest-circus/node_modules/@jest/expect": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.0.4.tgz", + "integrity": "sha512-Z/DL7t67LBHSX4UzDyeYKqOxE/n7lbrrgEwWM3dGiH5Dgn35nk+YtgzKudmfIrBI8DRRrKYY5BCo3317HZV1Fw==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "expect": "30.0.4", + "jest-snapshot": "30.0.4" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "node_modules/jest-circus/node_modules/@jest/expect-utils": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.4.tgz", + "integrity": "sha512-EgXecHDNfANeqOkcak0DxsoVI4qkDUsR7n/Lr2vtmTBjwLPBnnPOF71S11Q8IObWzxm2QgQoY6f9hzrRD3gHRA==", "dev": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1" }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "node_modules/jest-circus/node_modules/@jest/fake-timers": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.0.4.tgz", + "integrity": "sha512-qZ7nxOcL5+gwBO6LErvwVy5k06VsX/deqo2XnVUSTV0TNC9lrg8FC3dARbi+5lmrr5VyX5drragK+xLcOjvjYw==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.1", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.0.2", + "jest-mock": "30.0.2", + "jest-util": "30.0.2" + }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "node_modules/jest-circus/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" + "@sinclair/typebox": "^0.34.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "node_modules/jest-circus/node_modules/@jest/transform": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.4.tgz", + "integrity": "sha512-atvy4hRph/UxdCIBp+UB2jhEA/jJiUeGZ7QPgBi9jUUKNgi3WEoMXGNG7zbbELG2+88PMabUNCDchmqgJy3ELg==", "dev": true, + "license": "MIT", "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "@babel/core": "^7.27.4", + "@jest/types": "30.0.1", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.0", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.2", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "node_modules/jest-circus/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "node_modules/jest-circus/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", "dev": true, - "engines": { - "node": ">=0.3.1" + "license": "MIT" + }, + "node_modules/jest-circus/node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" } }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "node_modules/jest-circus/node_modules/babel-plugin-istanbul": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", + "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/electron-to-chromium": { - "version": "1.4.685", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.685.tgz", - "integrity": "sha512-yDYeobbTEe4TNooEzOQO6xFqg9XnAkVy2Lod1C1B2it8u47JNLYvl9nLDWBamqUakWB8Jc1hhS1uHUNYTNQdfw==", - "dev": true - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "node_modules/jest-circus/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "node": ">=8" } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "node_modules/jest-circus/node_modules/expect": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.4.tgz", + "integrity": "sha512-dDLGjnP2cKbEppxVICxI/Uf4YemmGMPNy0QytCbfafbpYk9AFQsxb8Uyrxii0RPK7FWgLGlSem+07WirwS3cFQ==", + "dev": true, + "license": "MIT", "dependencies": { - "once": "^1.4.0" + "@jest/expect-utils": "30.0.4", + "@jest/get-type": "30.0.1", + "jest-matcher-utils": "30.0.4", + "jest-message-util": "30.0.2", + "jest-mock": "30.0.2", + "jest-util": "30.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/enhanced-resolve": { - "version": "5.15.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz", - "integrity": "sha512-3d3JRbwsCLJsYgvb6NuWEG44jjPSOMuS73L/6+7BZuoKm3W+qXnSoIYVHi8dG7Qcg4inAY4jbzkZ7MnskePeDg==", + "node_modules/jest-circus/node_modules/jest-diff": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.4.tgz", + "integrity": "sha512-TSjceIf6797jyd+R64NXqicttROD+Qf98fex7CowmlSn7f8+En0da1Dglwr1AXxDtVizoxXYZBlUQwNhoOXkNw==", "dev": true, + "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "pretty-format": "30.0.2" }, "engines": { - "node": ">=10.13.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/jest-circus/node_modules/jest-haste-map": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.2.tgz", + "integrity": "sha512-telJBKpNLeCb4MaX+I5k496556Y2FiKR/QLZc0+MGBYl4k3OO0472drlV2LUe7c1Glng5HuAu+5GLYp//GpdOQ==", "dev": true, + "license": "MIT", "dependencies": { - "is-arrayish": "^0.2.1" + "@jest/types": "30.0.1", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "jest-worker": "30.0.2", + "micromatch": "^4.0.8", + "walker": "^1.0.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "node_modules/jest-circus/node_modules/jest-matcher-utils": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.4.tgz", + "integrity": "sha512-ubCewJ54YzeAZ2JeHHGVoU+eDIpQFsfPQs0xURPWoNiO42LGJ+QGgfSf+hFIRplkZDkhH5MOvuxHKXRTUU3dUQ==", "dev": true, + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "jest-diff": "30.0.4", + "pretty-format": "30.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "node_modules/jest-circus/node_modules/jest-message-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.2.tgz", + "integrity": "sha512-vXywcxmr0SsKXF/bAD7t7nMamRvPuJkras00gqYeB1V0WllxZrbZ0paRr3XqpFU2sYYjD0qAaG2fRyn/CGZ0aw==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4" + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.0.1", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/jest-circus/node_modules/jest-mock": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.2.tgz", + "integrity": "sha512-PnZOHmqup/9cT/y+pXIVbbi8ID6U1XHRmbvR7MvUy4SLqhCbwpkmXhLbsWbGewHrV5x/1bF7YDjs+x24/QSvFA==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.1", + "@types/node": "*", + "jest-util": "30.0.2" + }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "node_modules/jest-circus/node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", "dev": true, - "dependencies": { - "es-errors": "^1.3.0" - }, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "node_modules/jest-circus/node_modules/jest-snapshot": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.4.tgz", + "integrity": "sha512-S/8hmSkeUib8WRUq9pWEb5zMfsOjiYWDWzFzKnjX7eDyKKgimsu9hcmsUEg8a7dPAw8s/FacxsXquq71pDgPjQ==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.0.4", + "@jest/get-type": "30.0.1", + "@jest/snapshot-utils": "30.0.4", + "@jest/transform": "30.0.4", + "@jest/types": "30.0.1", + "babel-preset-current-node-syntax": "^1.1.0", + "chalk": "^4.1.2", + "expect": "30.0.4", + "graceful-fs": "^4.2.11", + "jest-diff": "30.0.4", + "jest-matcher-utils": "30.0.4", + "jest-message-util": "30.0.2", + "jest-util": "30.0.2", + "pretty-format": "30.0.2", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "node_modules/jest-circus/node_modules/jest-worker": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.2.tgz", + "integrity": "sha512-RN1eQmx7qSLFA+o9pfJKlqViwL5wt+OL3Vff/A+/cPsmuw7NPwfgl33AP+/agRmHzPOFgXviRycR9kYwlcRQXg==", "dev": true, + "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.0.2", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "node_modules/jest-circus/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/esbuild": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", - "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", + "node_modules/jest-circus/node_modules/pretty-format": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz", + "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==", "dev": true, - "hasInstallScript": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "dependencies": { + "@jest/schemas": "30.0.1", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.1", - "@esbuild/android-arm": "0.25.1", - "@esbuild/android-arm64": "0.25.1", - "@esbuild/android-x64": "0.25.1", - "@esbuild/darwin-arm64": "0.25.1", - "@esbuild/darwin-x64": "0.25.1", - "@esbuild/freebsd-arm64": "0.25.1", - "@esbuild/freebsd-x64": "0.25.1", - "@esbuild/linux-arm": "0.25.1", - "@esbuild/linux-arm64": "0.25.1", - "@esbuild/linux-ia32": "0.25.1", - "@esbuild/linux-loong64": "0.25.1", - "@esbuild/linux-mips64el": "0.25.1", - "@esbuild/linux-ppc64": "0.25.1", - "@esbuild/linux-riscv64": "0.25.1", - "@esbuild/linux-s390x": "0.25.1", - "@esbuild/linux-x64": "0.25.1", - "@esbuild/netbsd-arm64": "0.25.1", - "@esbuild/netbsd-x64": "0.25.1", - "@esbuild/openbsd-arm64": "0.25.1", - "@esbuild/openbsd-x64": "0.25.1", - "@esbuild/sunos-x64": "0.25.1", - "@esbuild/win32-arm64": "0.25.1", - "@esbuild/win32-ia32": "0.25.1", - "@esbuild/win32-x64": "0.25.1" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "node_modules/jest-circus/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { - "node": ">=6" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/jest-circus/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/eslint": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", - "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", + "node_modules/jest-circus/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, + "license": "ISC", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.6.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.12.0", - "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "text-table": "^0.2.0" + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.0.4.tgz", + "integrity": "sha512-3dOrP3zqCWBkjoVG1zjYJpD9143N9GUCbwaF2pFF5brnIgRLHmKcCIw+83BvF1LxggfMWBA0gxkn6RuQVuRhIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "30.0.4", + "@jest/test-result": "30.0.4", + "@jest/types": "30.0.1", + "chalk": "^4.1.2", + "exit-x": "^0.2.2", + "import-local": "^3.2.0", + "jest-config": "30.0.4", + "jest-util": "30.0.2", + "jest-validate": "30.0.2", + "yargs": "^17.7.2" }, "bin": { - "eslint": "bin/eslint.js" + "jest": "bin/jest.js" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, "peerDependencies": { - "jiti": "*" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { - "jiti": { + "node-notifier": { "optional": true } } }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "node_modules/jest-cli/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" }, - "peerDependencies": { - "eslint": ">=7.0.0" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "node_modules/jest-cli/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/jest-cli/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", "dev": true, - "dependencies": { - "ms": "^2.1.1" + "license": "MIT" + }, + "node_modules/jest-cli/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz", - "integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==", + "node_modules/jest-cli/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", "dev": true, + "license": "MIT", "dependencies": { - "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.3.5", - "enhanced-resolve": "^5.15.0", - "eslint-module-utils": "^2.8.1", - "fast-glob": "^3.3.2", - "get-tsconfig": "^4.7.5", - "is-bun-module": "^1.0.2", - "is-glob": "^4.0.3" + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-cli/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" }, "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*", - "eslint-plugin-import-x": "*" - }, - "peerDependenciesMeta": { - "eslint-plugin-import": { - "optional": true - }, - "eslint-plugin-import-x": { - "optional": true - } + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/eslint-module-utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "node_modules/jest-config": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.0.4.tgz", + "integrity": "sha512-3dzbO6sh34thAGEjJIW0fgT0GA0EVlkski6ZzMcbW6dzhenylXAE/Mj2MI4HonroWbkKc6wU6bLVQ8dvBSZ9lA==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^3.2.7" + "@babel/core": "^7.27.4", + "@jest/get-type": "30.0.1", + "@jest/pattern": "30.0.1", + "@jest/test-sequencer": "30.0.4", + "@jest/types": "30.0.1", + "babel-jest": "30.0.4", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-circus": "30.0.4", + "jest-docblock": "30.0.1", + "jest-environment-node": "30.0.4", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.0.2", + "jest-runner": "30.0.4", + "jest-util": "30.0.2", + "jest-validate": "30.0.2", + "micromatch": "^4.0.8", + "parse-json": "^5.2.0", + "pretty-format": "30.0.2", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "esbuild-register": ">=3.4.0", + "ts-node": ">=9.0.0" }, "peerDependenciesMeta": { - "eslint": { + "@types/node": { + "optional": true + }, + "esbuild-register": { + "optional": true + }, + "ts-node": { "optional": true } } }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/jest-config/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/eslint-plugin-import": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", - "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "node_modules/jest-config/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, + "license": "MIT", "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", - "hasown": "^2.0.2", - "is-core-module": "^2.15.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.0", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", - "tsconfig-paths": "^3.15.0" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/jest-config/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "license": "MIT" }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "dependencies": { - "ms": "^2.1.1" + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/jest-config/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/eslint-plugin-import/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "node_modules/jest-config/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, + "license": "ISC", "dependencies": { - "minimist": "^1.2.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { - "json5": "lib/cli.js" + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/jest-config/node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/jest-config/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/eslint-plugin-import/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/jest-config/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "node_modules/jest-config/node_modules/pretty-format": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz", + "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==", "dev": true, + "license": "MIT", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "@jest/schemas": "30.0.1", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/eslint-plugin-no-relative-import-paths": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-no-relative-import-paths/-/eslint-plugin-no-relative-import-paths-1.5.5.tgz", - "integrity": "sha512-UjudFFdBbv93v0CsVdEKcMLbBzRIjeK2PubTctX57tgnHxZcMj1Jm8lDBWoETnPxk0S5g5QLSltEM+511yL4+w==", - "dev": true - }, - "node_modules/eslint-plugin-prefer-arrow-functions": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prefer-arrow-functions/-/eslint-plugin-prefer-arrow-functions-3.4.1.tgz", - "integrity": "sha512-c8NP0E8xpkRqDq2eDSRr+wA4jwkwOEVNnZx4YY3O0V9M7OhtKdQIj5zmzIXwu+ueURmbwYrnz65sEoLLoIVZpg==", + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, - "engines": { - "node": ">=18.0.0" + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, - "peerDependencies": { - "eslint": ">=8.0.0" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eslint-plugin-simple-import-sort": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.1.tgz", - "integrity": "sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==", + "node_modules/jest-docblock": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.0.1.tgz", + "integrity": "sha512-/vF78qn3DYphAaIc3jy4gA7XSAz167n9Bm/wn/1XhTLW7tTBIzXtCJpb/vcmc73NIIeeohCbdL94JasyXUZsGA==", "dev": true, - "peerDependencies": { - "eslint": ">=5.0.0" + "license": "MIT", + "dependencies": { + "detect-newline": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "node_modules/jest-each": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.0.2.tgz", + "integrity": "sha512-ZFRsTpe5FUWFQ9cWTMguCaiA6kkW5whccPy9JjD1ezxh+mJeqmz8naL8Fl/oSbNJv3rgB0x87WBIkA5CObIUZQ==", "dev": true, + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "@jest/get-type": "30.0.1", + "@jest/types": "30.0.1", + "chalk": "^4.1.2", + "jest-util": "30.0.2", + "pretty-format": "30.0.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/jest-each/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "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==", + "node_modules/jest-each/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "node_modules/jest-each/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/jest-each/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "node_modules/jest-each/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", "dev": true, + "license": "MIT", "dependencies": { - "acorn": "^8.12.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "node_modules/jest-each/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, + "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=12" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/jest-each/node_modules/pretty-format": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz", + "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==", "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.1", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, "engines": { - "node": ">=4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "node_modules/jest-environment-node": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.0.4.tgz", + "integrity": "sha512-p+rLEzC2eThXqiNh9GHHTC0OW5Ca4ZfcURp7scPjYBcmgpR9HG6750716GuUipYf2AcThU3k20B31USuiaaIEg==", "dev": true, + "license": "MIT", "dependencies": { - "estraverse": "^5.1.0" + "@jest/environment": "30.0.4", + "@jest/fake-timers": "30.0.4", + "@jest/types": "30.0.1", + "@types/node": "*", + "jest-mock": "30.0.2", + "jest-util": "30.0.2", + "jest-validate": "30.0.2" }, "engines": { - "node": ">=0.10" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/jest-environment-node/node_modules/@jest/environment": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.0.4.tgz", + "integrity": "sha512-5NT+sr7ZOb8wW7C4r7wOKnRQ8zmRWQT2gW4j73IXAKp5/PX1Z8MCStBLQDYfIG3n1Sw0NRfYGdp0iIPVooBAFQ==", "dev": true, + "license": "MIT", "dependencies": { - "estraverse": "^5.2.0" + "@jest/fake-timers": "30.0.4", + "@jest/types": "30.0.1", + "@types/node": "*", + "jest-mock": "30.0.2" }, "engines": { - "node": ">=4.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/jest-environment-node/node_modules/@jest/fake-timers": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.0.4.tgz", + "integrity": "sha512-qZ7nxOcL5+gwBO6LErvwVy5k06VsX/deqo2XnVUSTV0TNC9lrg8FC3dARbi+5lmrr5VyX5drragK+xLcOjvjYw==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.1", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.0.2", + "jest-mock": "30.0.2", + "jest-util": "30.0.2" + }, "engines": { - "node": ">=4.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/jest-environment-node/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "node_modules/jest-environment-node/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, "engines": { - "node": ">=6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" - } + "node_modules/jest-environment-node/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/jest-environment-node/node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/jest-environment-node/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "node_modules/jest-environment-node/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "node_modules/jest-environment-node/node_modules/jest-message-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.2.tgz", + "integrity": "sha512-vXywcxmr0SsKXF/bAD7t7nMamRvPuJkras00gqYeB1V0WllxZrbZ0paRr3XqpFU2sYYjD0qAaG2fRyn/CGZ0aw==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.0.1", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/fast-copy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", - "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "node_modules/jest-environment-node/node_modules/jest-mock": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.2.tgz", + "integrity": "sha512-PnZOHmqup/9cT/y+pXIVbbi8ID6U1XHRmbvR7MvUy4SLqhCbwpkmXhLbsWbGewHrV5x/1bF7YDjs+x24/QSvFA==", "dev": true, + "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "@jest/types": "30.0.1", + "@types/node": "*", + "jest-util": "30.0.2" }, "engines": { - "node": ">=8.6.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/jest-environment-node/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": ">= 6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fast-redact": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", - "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==", + "node_modules/jest-environment-node/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "node_modules/jest-environment-node/node_modules/pretty-format": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz", + "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==", "dev": true, + "license": "MIT", "dependencies": { - "reusify": "^1.0.4" + "@jest/schemas": "30.0.1", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, - "dependencies": { - "bser": "2.1.1" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "dependencies": { - "flat-cache": "^4.0.0" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dev": true, - "dependencies": { - "minimatch": "^5.0.1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "node_modules/jest-leak-detector": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.0.2.tgz", + "integrity": "sha512-U66sRrAYdALq+2qtKffBLDWsQ/XoNNs2Lcr83sc9lvE/hEpNafJlq2lXCPUBMNqamMECNxSIekLfe69qg4KMIQ==", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "@jest/get-type": "30.0.1", + "pretty-format": "30.0.2" }, "engines": { - "node": ">=10" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/jest-leak-detector/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, + "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "@sinclair/typebox": "^0.34.0" }, "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/jest-leak-detector/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-leak-detector/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, + "license": "MIT", "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "node_modules/jest-leak-detector/node_modules/pretty-format": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz", + "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==", "dev": true, + "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" + "@jest/schemas": "30.0.1", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, "engines": { - "node": ">=16" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/functions-have-names": { + "node_modules/jest-pnp-resolver": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "engines": { - "node": ">=6.9.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/jest-resolve": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.0.2.tgz", + "integrity": "sha512-q/XT0XQvRemykZsvRopbG6FQUT6/ra+XV6rPijyjT6D0msOyCvR2A5PlWZLd+fH0U8XWKZfDiAgrUNDNX2BkCw==", "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.2", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.0.2", + "jest-validate": "30.0.2", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" + }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "node_modules/jest-resolve-dependencies": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.0.4.tgz", + "integrity": "sha512-EQBYow19B/hKr4gUTn+l8Z+YLlP2X0IoPyp0UydOtrcPbIOYzJ8LKdFd+yrbwztPQvmlBFUwGPPEzHH1bAvFAw==", "dev": true, + "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "jest-regex-util": "30.0.1", + "jest-snapshot": "30.0.4" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "node_modules/jest-resolve-dependencies/node_modules/@jest/expect-utils": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.4.tgz", + "integrity": "sha512-EgXecHDNfANeqOkcak0DxsoVI4qkDUsR7n/Lr2vtmTBjwLPBnnPOF71S11Q8IObWzxm2QgQoY6f9hzrRD3gHRA==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1" + }, "engines": { - "node": ">=8.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/jest-resolve-dependencies/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, - "engines": { - "node": ">=10" + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "node_modules/jest-resolve-dependencies/node_modules/@jest/transform": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.4.tgz", + "integrity": "sha512-atvy4hRph/UxdCIBp+UB2jhEA/jJiUeGZ7QPgBi9jUUKNgi3WEoMXGNG7zbbELG2+88PMabUNCDchmqgJy3ELg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "@babel/core": "^7.27.4", + "@jest/types": "30.0.1", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.0", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.2", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/get-tsconfig": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", - "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", + "node_modules/jest-resolve-dependencies/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, + "license": "MIT", "dependencies": { - "resolve-pkg-maps": "^1.0.0" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/jest-resolve-dependencies/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "license": "MIT" + }, + "node_modules/jest-resolve-dependencies/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", "engines": { - "node": "*" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/jest-resolve-dependencies/node_modules/babel-plugin-istanbul": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", + "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "is-glob": "^4.0.3" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=12" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/jest-resolve-dependencies/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/jest-resolve-dependencies/node_modules/expect": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.4.tgz", + "integrity": "sha512-dDLGjnP2cKbEppxVICxI/Uf4YemmGMPNy0QytCbfafbpYk9AFQsxb8Uyrxii0RPK7FWgLGlSem+07WirwS3cFQ==", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "@jest/expect-utils": "30.0.4", + "@jest/get-type": "30.0.1", + "jest-matcher-utils": "30.0.4", + "jest-message-util": "30.0.2", + "jest-mock": "30.0.2", + "jest-util": "30.0.2" }, "engines": { - "node": "*" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/globals": { - "version": "15.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", - "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", + "node_modules/jest-resolve-dependencies/node_modules/jest-diff": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.4.tgz", + "integrity": "sha512-TSjceIf6797jyd+R64NXqicttROD+Qf98fex7CowmlSn7f8+En0da1Dglwr1AXxDtVizoxXYZBlUQwNhoOXkNw==", "dev": true, - "engines": { - "node": ">=18" + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "pretty-format": "30.0.2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "node_modules/jest-resolve-dependencies/node_modules/jest-haste-map": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.2.tgz", + "integrity": "sha512-telJBKpNLeCb4MaX+I5k496556Y2FiKR/QLZc0+MGBYl4k3OO0472drlV2LUe7c1Glng5HuAu+5GLYp//GpdOQ==", "dev": true, + "license": "MIT", "dependencies": { - "define-properties": "^1.1.3" + "@jest/types": "30.0.1", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "jest-worker": "30.0.2", + "micromatch": "^4.0.8", + "walker": "^1.0.8" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/jest-resolve-dependencies/node_modules/jest-matcher-utils": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.4.tgz", + "integrity": "sha512-ubCewJ54YzeAZ2JeHHGVoU+eDIpQFsfPQs0xURPWoNiO42LGJ+QGgfSf+hFIRplkZDkhH5MOvuxHKXRTUU3dUQ==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.3" + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "jest-diff": "30.0.4", + "pretty-format": "30.0.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "node_modules/jest-resolve-dependencies/node_modules/jest-message-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.2.tgz", + "integrity": "sha512-vXywcxmr0SsKXF/bAD7t7nMamRvPuJkras00gqYeB1V0WllxZrbZ0paRr3XqpFU2sYYjD0qAaG2fRyn/CGZ0aw==", "dev": true, + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.0.1", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "node_modules/jest-resolve-dependencies/node_modules/jest-mock": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.2.tgz", + "integrity": "sha512-PnZOHmqup/9cT/y+pXIVbbi8ID6U1XHRmbvR7MvUy4SLqhCbwpkmXhLbsWbGewHrV5x/1bF7YDjs+x24/QSvFA==", "dev": true, - "engines": { - "node": ">= 0.4" + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.1", + "@types/node": "*", + "jest-util": "30.0.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/jest-resolve-dependencies/node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "node_modules/jest-resolve-dependencies/node_modules/jest-snapshot": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.4.tgz", + "integrity": "sha512-S/8hmSkeUib8WRUq9pWEb5zMfsOjiYWDWzFzKnjX7eDyKKgimsu9hcmsUEg8a7dPAw8s/FacxsXquq71pDgPjQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.3" + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.0.4", + "@jest/get-type": "30.0.1", + "@jest/snapshot-utils": "30.0.4", + "@jest/transform": "30.0.4", + "@jest/types": "30.0.1", + "babel-preset-current-node-syntax": "^1.1.0", + "chalk": "^4.1.2", + "expect": "30.0.4", + "graceful-fs": "^4.2.11", + "jest-diff": "30.0.4", + "jest-matcher-utils": "30.0.4", + "jest-message-util": "30.0.2", + "jest-util": "30.0.2", + "pretty-format": "30.0.2", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve-dependencies/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/jest-resolve-dependencies/node_modules/jest-worker": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.2.tgz", + "integrity": "sha512-RN1eQmx7qSLFA+o9pfJKlqViwL5wt+OL3Vff/A+/cPsmuw7NPwfgl33AP+/agRmHzPOFgXviRycR9kYwlcRQXg==", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.0.2", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "node_modules/jest-resolve-dependencies/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10.17.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "node_modules/jest-resolve-dependencies/node_modules/pretty-format": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz", + "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.1", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, "engines": { - "node": ">= 4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "node_modules/jest-resolve-dependencies/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, + "license": "ISC", "engines": { - "node": ">=6" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "node_modules/jest-resolve-dependencies/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/jest-resolve-dependencies/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, "engines": { - "node": ">=0.8.19" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "node_modules/jest-resolve/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, + "license": "MIT", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "node_modules/jest-resolve/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, + "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/ip-address": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.0.tgz", - "integrity": "sha512-PphFaoy0TyGdIGpmd35iA22j/3Ay+84F+4f6Rk7lAOusu7NiAQd5qgDfmT8flQt3+d5L8EwfAoKwfrtTPjt9Jg==", + "node_modules/jest-resolve/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-resolve/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { - "node": ">= 12" + "node": ">=8" } }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "node_modules/jest-resolve/node_modules/jest-haste-map": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.2.tgz", + "integrity": "sha512-telJBKpNLeCb4MaX+I5k496556Y2FiKR/QLZc0+MGBYl4k3OO0472drlV2LUe7c1Glng5HuAu+5GLYp//GpdOQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" + "@jest/types": "30.0.1", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "jest-worker": "30.0.2", + "micromatch": "^4.0.8", + "walker": "^1.0.8" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "node_modules/jest-resolve/node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "node_modules/jest-resolve/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-bun-module": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz", - "integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==", + "node_modules/jest-resolve/node_modules/jest-worker": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.2.tgz", + "integrity": "sha512-RN1eQmx7qSLFA+o9pfJKlqViwL5wt+OL3Vff/A+/cPsmuw7NPwfgl33AP+/agRmHzPOFgXviRycR9kYwlcRQXg==", "dev": true, + "license": "MIT", "dependencies": { - "semver": "^7.6.3" + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.0.2", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "node_modules/jest-resolve/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "node_modules/jest-runner": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.0.4.tgz", + "integrity": "sha512-mxY0vTAEsowJwvFJo5pVivbCpuu6dgdXRmt3v3MXjBxFly7/lTk3Td0PaMyGOeNQUFmSuGEsGYqhbn7PA9OekQ==", "dev": true, + "license": "MIT", "dependencies": { - "is-typed-array": "^1.1.13" + "@jest/console": "30.0.4", + "@jest/environment": "30.0.4", + "@jest/test-result": "30.0.4", + "@jest/transform": "30.0.4", + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-docblock": "30.0.1", + "jest-environment-node": "30.0.4", + "jest-haste-map": "30.0.2", + "jest-leak-detector": "30.0.2", + "jest-message-util": "30.0.2", + "jest-resolve": "30.0.2", + "jest-runtime": "30.0.4", + "jest-util": "30.0.2", + "jest-watcher": "30.0.4", + "jest-worker": "30.0.2", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "node_modules/jest-runner/node_modules/@jest/environment": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.0.4.tgz", + "integrity": "sha512-5NT+sr7ZOb8wW7C4r7wOKnRQ8zmRWQT2gW4j73IXAKp5/PX1Z8MCStBLQDYfIG3n1Sw0NRfYGdp0iIPVooBAFQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "@jest/fake-timers": "30.0.4", + "@jest/types": "30.0.1", + "@types/node": "*", + "jest-mock": "30.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/jest-runner/node_modules/@jest/fake-timers": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.0.4.tgz", + "integrity": "sha512-qZ7nxOcL5+gwBO6LErvwVy5k06VsX/deqo2XnVUSTV0TNC9lrg8FC3dARbi+5lmrr5VyX5drragK+xLcOjvjYw==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.1", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.0.2", + "jest-mock": "30.0.2", + "jest-util": "30.0.2" + }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/jest-runner/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "node_modules/jest-runner/node_modules/@jest/transform": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.4.tgz", + "integrity": "sha512-atvy4hRph/UxdCIBp+UB2jhEA/jJiUeGZ7QPgBi9jUUKNgi3WEoMXGNG7zbbELG2+88PMabUNCDchmqgJy3ELg==", "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.0.1", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.0", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.2", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, "engines": { - "node": ">=6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/jest-runner/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, + "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "node_modules/jest-runner/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-runner/node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-number": { + "node_modules/jest-runner/node_modules/babel-plugin-istanbul": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", + "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, "engines": { - "node": ">=0.12.0" + "node": ">=12" } }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "node_modules/jest-runner/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/jest-haste-map": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.2.tgz", + "integrity": "sha512-telJBKpNLeCb4MaX+I5k496556Y2FiKR/QLZc0+MGBYl4k3OO0472drlV2LUe7c1Glng5HuAu+5GLYp//GpdOQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "@jest/types": "30.0.1", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "jest-worker": "30.0.2", + "micromatch": "^4.0.8", + "walker": "^1.0.8" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "node_modules/jest-runner/node_modules/jest-message-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.2.tgz", + "integrity": "sha512-vXywcxmr0SsKXF/bAD7t7nMamRvPuJkras00gqYeB1V0WllxZrbZ0paRr3XqpFU2sYYjD0qAaG2fRyn/CGZ0aw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.0.1", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "node_modules/jest-runner/node_modules/jest-mock": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.2.tgz", + "integrity": "sha512-PnZOHmqup/9cT/y+pXIVbbi8ID6U1XHRmbvR7MvUy4SLqhCbwpkmXhLbsWbGewHrV5x/1bF7YDjs+x24/QSvFA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7" + "@jest/types": "30.0.1", + "@types/node": "*", + "jest-util": "30.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/jest-runner/node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "node_modules/jest-runner/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "node_modules/jest-runner/node_modules/jest-worker": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.2.tgz", + "integrity": "sha512-RN1eQmx7qSLFA+o9pfJKlqViwL5wt+OL3Vff/A+/cPsmuw7NPwfgl33AP+/agRmHzPOFgXviRycR9kYwlcRQXg==", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.0.2", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "node_modules/jest-runner/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, - "dependencies": { - "which-typed-array": "^1.1.14" - }, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + }, + "node_modules/jest-runner/node_modules/pretty-format": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz", + "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "@jest/schemas": "30.0.1", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "node_modules/jest-runner/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { - "node": ">=8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", - "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "node_modules/jest-runner/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" + "has-flag": "^4.0.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "node_modules/jest-runner/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, + "license": "ISC", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=10" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "node_modules/jest-runtime": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.0.4.tgz", + "integrity": "sha512-tUQrZ8+IzoZYIHoPDQEB4jZoPyzBjLjq7sk0KVyd5UPRjRDOsN7o6UlvaGF8ddpGsjznl9PW+KRgWqCNO+Hn7w==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "@jest/environment": "30.0.4", + "@jest/fake-timers": "30.0.4", + "@jest/globals": "30.0.4", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.0.4", + "@jest/transform": "30.0.4", + "@jest/types": "30.0.1", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.2", + "jest-message-util": "30.0.2", + "jest-mock": "30.0.2", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.0.2", + "jest-snapshot": "30.0.4", + "jest-util": "30.0.2", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "engines": { - "node": ">=10" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "node_modules/jest-runtime/node_modules/@jest/environment": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.0.4.tgz", + "integrity": "sha512-5NT+sr7ZOb8wW7C4r7wOKnRQ8zmRWQT2gW4j73IXAKp5/PX1Z8MCStBLQDYfIG3n1Sw0NRfYGdp0iIPVooBAFQ==", "dev": true, + "license": "MIT", "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "@jest/fake-timers": "30.0.4", + "@jest/types": "30.0.1", + "@types/node": "*", + "jest-mock": "30.0.2" }, "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jake": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", - "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "node_modules/jest-runtime/node_modules/@jest/expect": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.0.4.tgz", + "integrity": "sha512-Z/DL7t67LBHSX4UzDyeYKqOxE/n7lbrrgEwWM3dGiH5Dgn35nk+YtgzKudmfIrBI8DRRrKYY5BCo3317HZV1Fw==", "dev": true, + "license": "MIT", "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" - }, - "bin": { - "jake": "bin/cli.js" + "expect": "30.0.4", + "jest-snapshot": "30.0.4" }, "engines": { - "node": ">=10" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jake/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/jest-runtime/node_modules/@jest/expect-utils": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.4.tgz", + "integrity": "sha512-EgXecHDNfANeqOkcak0DxsoVI4qkDUsR7n/Lr2vtmTBjwLPBnnPOF71S11Q8IObWzxm2QgQoY6f9hzrRD3gHRA==", "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@jest/get-type": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jake/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/jest-runtime/node_modules/@jest/fake-timers": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.0.4.tgz", + "integrity": "sha512-qZ7nxOcL5+gwBO6LErvwVy5k06VsX/deqo2XnVUSTV0TNC9lrg8FC3dARbi+5lmrr5VyX5drragK+xLcOjvjYw==", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "@jest/types": "30.0.1", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.0.2", + "jest-mock": "30.0.2", + "jest-util": "30.0.2" }, "engines": { - "node": "*" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "node_modules/jest-runtime/node_modules/@jest/globals": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.0.4.tgz", + "integrity": "sha512-avyZuxEHF2EUhFF6NEWVdxkRRV6iXXcIES66DLhuLlU7lXhtFG/ySq/a8SRZmEJSsLkNAFX6z6mm8KWyXe9OEA==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" + "@jest/environment": "30.0.4", + "@jest/expect": "30.0.4", + "@jest/types": "30.0.1", + "jest-mock": "30.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "node_modules/jest-runtime/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, + "license": "MIT", "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" + "@sinclair/typebox": "^0.34.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "node_modules/jest-runtime/node_modules/@jest/transform": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.4.tgz", + "integrity": "sha512-atvy4hRph/UxdCIBp+UB2jhEA/jJiUeGZ7QPgBi9jUUKNgi3WEoMXGNG7zbbELG2+88PMabUNCDchmqgJy3ELg==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", + "@babel/core": "^7.27.4", + "@jest/types": "30.0.1", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.0", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.2", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "write-file-atomic": "^5.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "node_modules/jest-runtime/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "node_modules/jest-runtime/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-runtime/node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" + "node": ">=10" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "node_modules/jest-runtime/node_modules/babel-plugin-istanbul": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", + "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "node_modules/jest-runtime/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", "dev": true, - "dependencies": { - "detect-newline": "^3.0.0" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "node_modules/jest-runtime/node_modules/expect": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.4.tgz", + "integrity": "sha512-dDLGjnP2cKbEppxVICxI/Uf4YemmGMPNy0QytCbfafbpYk9AFQsxb8Uyrxii0RPK7FWgLGlSem+07WirwS3cFQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" + "@jest/expect-utils": "30.0.4", + "@jest/get-type": "30.0.1", + "jest-matcher-utils": "30.0.4", + "jest-message-util": "30.0.2", + "jest-mock": "30.0.2", + "jest-util": "30.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "node_modules/jest-runtime/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, + "license": "ISC", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "node_modules/jest-runtime/node_modules/jest-diff": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.4.tgz", + "integrity": "sha512-TSjceIf6797jyd+R64NXqicttROD+Qf98fex7CowmlSn7f8+En0da1Dglwr1AXxDtVizoxXYZBlUQwNhoOXkNw==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "pretty-format": "30.0.2" + }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "node_modules/jest-runtime/node_modules/jest-haste-map": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.2.tgz", + "integrity": "sha512-telJBKpNLeCb4MaX+I5k496556Y2FiKR/QLZc0+MGBYl4k3OO0472drlV2LUe7c1Glng5HuAu+5GLYp//GpdOQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", + "@jest/types": "30.0.1", "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.2", + "jest-worker": "30.0.2", + "micromatch": "^4.0.8", "walker": "^1.0.8" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, "optionalDependencies": { - "fsevents": "^2.3.2" + "fsevents": "^2.3.3" } }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "node_modules/jest-runtime/node_modules/jest-matcher-utils": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.4.tgz", + "integrity": "sha512-ubCewJ54YzeAZ2JeHHGVoU+eDIpQFsfPQs0xURPWoNiO42LGJ+QGgfSf+hFIRplkZDkhH5MOvuxHKXRTUU3dUQ==", "dev": true, + "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "jest-diff": "30.0.4", + "pretty-format": "30.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "node_modules/jest-runtime/node_modules/jest-message-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.2.tgz", + "integrity": "sha512-vXywcxmr0SsKXF/bAD7t7nMamRvPuJkras00gqYeB1V0WllxZrbZ0paRr3XqpFU2sYYjD0qAaG2fRyn/CGZ0aw==", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.0.1", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "node_modules/jest-runtime/node_modules/jest-mock": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.2.tgz", + "integrity": "sha512-PnZOHmqup/9cT/y+pXIVbbi8ID6U1XHRmbvR7MvUy4SLqhCbwpkmXhLbsWbGewHrV5x/1bF7YDjs+x24/QSvFA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "@jest/types": "30.0.1", + "@types/node": "*", + "jest-util": "30.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "node_modules/jest-runtime/node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runtime/node_modules/jest-snapshot": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.4.tgz", + "integrity": "sha512-S/8hmSkeUib8WRUq9pWEb5zMfsOjiYWDWzFzKnjX7eDyKKgimsu9hcmsUEg8a7dPAw8s/FacxsXquq71pDgPjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.0.4", + "@jest/get-type": "30.0.1", + "@jest/snapshot-utils": "30.0.4", + "@jest/transform": "30.0.4", + "@jest/types": "30.0.1", + "babel-preset-current-node-syntax": "^1.1.0", + "chalk": "^4.1.2", + "expect": "30.0.4", + "graceful-fs": "^4.2.11", + "jest-diff": "30.0.4", + "jest-matcher-utils": "30.0.4", + "jest-message-util": "30.0.2", + "jest-util": "30.0.2", + "pretty-format": "30.0.2", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runtime/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", + "@jest/types": "30.0.1", "@types/node": "*", - "jest-util": "^29.7.0" + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "node_modules/jest-runtime/node_modules/jest-worker": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.2.tgz", + "integrity": "sha512-RN1eQmx7qSLFA+o9pfJKlqViwL5wt+OL3Vff/A+/cPsmuw7NPwfgl33AP+/agRmHzPOFgXviRycR9kYwlcRQXg==", "dev": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.0.2", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "node_modules/jest-runtime/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "node_modules/jest-runtime/node_modules/pretty-format": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz", + "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" + "@jest/schemas": "30.0.1", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "node_modules/jest-runtime/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, + "license": "ISC", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" + "has-flag": "^4.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "node_modules/jest-runtime/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, + "license": "ISC", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/jest-snapshot": { @@ -5425,72 +10248,228 @@ "semver": "^7.5.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.0.2.tgz", + "integrity": "sha512-noOvul+SFER4RIvNAwGn6nmV2fXqBq67j+hKGHKGFCmK4ks/Iy1FSrqQNBLGKlu4ZZIRL6Kg1U72N1nxuRCrGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1", + "@jest/types": "30.0.1", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-validate/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-validate/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-validate/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-validate/node_modules/pretty-format": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz", + "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.1", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-watcher": { + "version": "30.0.4", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.0.4.tgz", + "integrity": "sha512-YESbdHDs7aQOCSSKffG8jXqOKFqw4q4YqR+wHYpR5GWEQioGvL0BfbcjvKIvPEM0XGfsfJrka7jJz3Cc3gI4VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.0.4", + "@jest/types": "30.0.1", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "jest-util": "30.0.2", + "string-length": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/jest-watcher/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "@sinclair/typebox": "^0.34.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "node_modules/jest-watcher/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/jest-watcher/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", "dev": true, + "license": "MIT" + }, + "node_modules/jest-watcher/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "node_modules/jest-watcher/node_modules/jest-util": { + "version": "30.0.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", + "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", + "@jest/types": "30.0.1", "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-watcher/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/jest-worker": { @@ -5523,6 +10502,45 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jest/node_modules/@jest/schemas": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", + "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest/node_modules/@jest/types": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", + "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest/node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" + }, "node_modules/joycon": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", @@ -5535,7 +10553,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", @@ -5550,28 +10569,31 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -5604,21 +10626,12 @@ } }, "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.4.tgz", + "integrity": "sha512-ypEvQvInNpUe+u+w8BIcPkQvEqXquyyibWE/1NB5T2BTzIpS5cGEV1LZskDzPSTvNAaT4+5FutvzlvnkxOSKlw==", + "license": "MIT", "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" + "@keyv/serialize": "^1.0.3" } }, "node_modules/leven": { @@ -5626,6 +10639,7 @@ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -5643,12 +10657,35 @@ "node": ">= 0.8.0" } }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/load-tsconfig": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -5681,20 +10718,39 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true, + "license": "MIT" + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.5.3" }, @@ -5754,6 +10810,7 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -5782,12 +10839,63 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mlly": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", + "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.0", + "pathe": "^2.0.1", + "pkg-types": "^1.3.0", + "ufo": "^1.5.4" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.0.tgz", + "integrity": "sha512-M7NqKyhODKV1gRLdkwE7pDsZP2/SC2a2vHkOYh9MCpKMbWVfyVfUw5MaH83Fv6XMjxr5jryUp3IDDL9rlxsTeA==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5815,10 +10923,11 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -5834,6 +10943,7 @@ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.0.0" }, @@ -5841,6 +10951,16 @@ "node": ">=8" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -5947,6 +11067,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -6024,6 +11145,13 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6041,6 +11169,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -6087,11 +11216,43 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", @@ -6165,10 +11326,11 @@ "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" }, "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } @@ -6178,6 +11340,7 @@ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -6190,6 +11353,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -6203,6 +11367,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -6215,6 +11380,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -6230,6 +11396,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -6237,6 +11404,18 @@ "node": ">=8" } }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -6246,6 +11425,49 @@ "node": ">= 0.4" } }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6318,19 +11540,6 @@ "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.0.tgz", "integrity": "sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==" }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/propagate": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", @@ -6359,9 +11568,9 @@ } }, "node_modules/pure-rand": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", - "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", "dev": true, "funding": [ { @@ -6372,7 +11581,8 @@ "type": "opencollective", "url": "https://opencollective.com/fast-check" } - ] + ], + "license": "MIT" }, "node_modules/queue-microtask": { "version": "1.2.3", @@ -6400,10 +11610,11 @@ "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" }, "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" }, "node_modules/readable-stream": { "version": "4.5.2", @@ -6420,6 +11631,20 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/real-require": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", @@ -6451,6 +11676,7 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6477,6 +11703,7 @@ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, + "license": "MIT", "dependencies": { "resolve-from": "^5.0.0" }, @@ -6489,6 +11716,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -6506,18 +11734,9 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true, - "engines": { - "node": ">=10" + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, "node_modules/reusify": { @@ -6530,6 +11749,46 @@ "node": ">=0.10.0" } }, + "node_modules/rollup": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.45.1.tgz", + "integrity": "sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.45.1", + "@rollup/rollup-android-arm64": "4.45.1", + "@rollup/rollup-darwin-arm64": "4.45.1", + "@rollup/rollup-darwin-x64": "4.45.1", + "@rollup/rollup-freebsd-arm64": "4.45.1", + "@rollup/rollup-freebsd-x64": "4.45.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.45.1", + "@rollup/rollup-linux-arm-musleabihf": "4.45.1", + "@rollup/rollup-linux-arm64-gnu": "4.45.1", + "@rollup/rollup-linux-arm64-musl": "4.45.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.45.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.45.1", + "@rollup/rollup-linux-riscv64-gnu": "4.45.1", + "@rollup/rollup-linux-riscv64-musl": "4.45.1", + "@rollup/rollup-linux-s390x-gnu": "4.45.1", + "@rollup/rollup-linux-x64-gnu": "4.45.1", + "@rollup/rollup-linux-x64-musl": "4.45.1", + "@rollup/rollup-win32-arm64-msvc": "4.45.1", + "@rollup/rollup-win32-ia32-msvc": "4.45.1", + "@rollup/rollup-win32-x64-msvc": "4.45.1", + "fsevents": "~2.3.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -6621,10 +11880,11 @@ "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -6709,12 +11969,6 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -6737,6 +11991,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -6746,6 +12001,7 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -6799,6 +12055,7 @@ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, + "license": "MIT", "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -6821,6 +12078,22 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.trim": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", @@ -6882,11 +12155,26 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -6896,6 +12184,7 @@ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -6911,6 +12200,50 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6946,6 +12279,22 @@ "node": ">=4.x" } }, + "node_modules/synckit": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz", + "integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.4" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -6997,6 +12346,29 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/thread-stream": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", @@ -7010,21 +12382,64 @@ "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7037,6 +12452,26 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, "node_modules/ts-api-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", @@ -7050,20 +12485,28 @@ "typescript": ">=4.8.4" } }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/ts-jest": { - "version": "29.2.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", - "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", + "version": "29.4.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.0.tgz", + "integrity": "sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q==", "dev": true, + "license": "MIT", "dependencies": { "bs-logger": "^0.2.6", "ejs": "^3.1.10", "fast-json-stable-stringify": "^2.1.0", - "jest-util": "^29.0.0", "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.6.3", + "semver": "^7.7.2", + "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, "bin": { @@ -7074,10 +12517,11 @@ }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/transform": "^29.0.0", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", "typescript": ">=4.3 <6" }, "peerDependenciesMeta": { @@ -7095,14 +12539,31 @@ }, "esbuild": { "optional": true + }, + "jest-util": { + "optional": true } } }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, + "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -7164,6 +12625,90 @@ "node": ">=4" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/tsup": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.5.0.tgz", + "integrity": "sha512-VmBp77lWNQq6PfuMqCHD3xWl22vEoWsKajkF8t+yMBawlUS8JzEI+vOVMeuNZIuMML8qXRizFKi9oD5glKQVcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-require": "^5.1.0", + "cac": "^6.7.14", + "chokidar": "^4.0.3", + "consola": "^3.4.0", + "debug": "^4.4.0", + "esbuild": "^0.25.0", + "fix-dts-default-cjs-exports": "^1.0.0", + "joycon": "^3.1.1", + "picocolors": "^1.1.1", + "postcss-load-config": "^6.0.1", + "resolve-from": "^5.0.0", + "rollup": "^4.34.8", + "source-map": "0.8.0-beta.0", + "sucrase": "^3.35.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.11", + "tree-kill": "^1.2.2" + }, + "bin": { + "tsup": "dist/cli-default.js", + "tsup-node": "dist/cli-node.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@microsoft/api-extractor": "^7.36.0", + "@swc/core": "^1", + "postcss": "^8.4.12", + "typescript": ">=4.5.0" + }, + "peerDependenciesMeta": { + "@microsoft/api-extractor": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "postcss": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/tsup/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/tsup/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/tsx": { "version": "4.19.3", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz", @@ -7205,6 +12750,19 @@ "node": ">=4" } }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", @@ -7291,6 +12849,13 @@ "node": ">=14.17" } }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "dev": true, + "license": "MIT" + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -7307,15 +12872,51 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "funding": [ { @@ -7331,9 +12932,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -7358,10 +12960,11 @@ "dev": true }, "node_modules/v8-to-istanbul": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", - "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, + "license": "ISC", "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", @@ -7380,6 +12983,25 @@ "makeerror": "1.0.12" } }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7435,6 +13057,26 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -7470,6 +13112,7 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } @@ -7478,13 +13121,15 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", diff --git a/package.json b/package.json index b16d0db..e21e249 100644 --- a/package.json +++ b/package.json @@ -2,15 +2,24 @@ "name": "@crowdsec/nodejs-bouncer", "version": "0.1.0", "description": "CrowdSec NodeJS Bouncer. Composed of a behavior detection engine, able to block classical attacks like credential bruteforce, port scans, web scans, etc. Based on the type and number of blocked attacks, and after curation of those signals to avoid false positives and poisoning, a global IP reputation DB is maintained and shared with all network members. This npm module is a “bouncer”, which purpose is to block detected attacks with two remediation systems: ban or challenge detected attackers with a Captcha.", - "main": "dist/index.js", - "types": "dist/index.d.ts", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./package.json": "./package.json" + }, "files": [ "dist", "CHANGELOG.md" ], "scripts": { "clean": "rm -rf dist", - "build": "tsc", + "build": "npm run clean && tsup --config tsup.config.ts", + "build:types": "tsc --emitDeclarationOnly --declaration --declarationMap false --outDir dist", "prepack": "npm run build", "lint": "eslint .", "lint:all": "npm run lint && npm run prettify-check", @@ -41,6 +50,7 @@ "dependencies": { "cache-manager": "^6.1.3", "ip-address": "^10.0.0", + "keyv": "^5.3.4", "lodash": "^4.17.21", "pino": "^9.4.0", "pino-pretty": "^11.2.2", @@ -51,25 +61,33 @@ "@eslint/eslintrc": "^3.1.0", "@eslint/js": "^9.12.0", "@jest/globals": "^29.7.0", + "@types/jest": "^30.0.0", "@types/lodash": "^4.17.10", + "@types/node": "^20.19.8", "@typescript-eslint/eslint-plugin": "^8.24.0", "@typescript-eslint/parser": "^8.24.0", "eslint": "^9.12.0", "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jest": "^29.0.1", "eslint-plugin-no-relative-import-paths": "^1.5.5", "eslint-plugin-prefer-arrow-functions": "^3.4.1", "eslint-plugin-simple-import-sort": "^12.1.1", "globals": "^15.11.0", - "jest": "^29.7.0", + "jest": "^30.0.4", "nock": "^14.0.0-beta.4", "prettier": "^3.3.3", "prettier-plugin-ejs": "^1.0.3", - "ts-jest": "^29.2.5", + "ts-jest": "^29.4.0", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", + "tsup": "^8.3.0", "tsx": "^4.19.3", "typescript": "^5.6.3" + }, + "sideEffects": false, + "engines": { + "node": ">=20" } } diff --git a/src/helpers/__tests__/ip.test.ts b/src/helpers/__tests__/ip.test.ts index c774e54..7397c84 100644 --- a/src/helpers/__tests__/ip.test.ts +++ b/src/helpers/__tests__/ip.test.ts @@ -28,7 +28,7 @@ describe('getIpToRemediate', () => { it('should throw an error for range', () => { const ip = '192.168.0.0/24'; - expect(() => getIpToRemediate(ip)).toThrowError('Input IP (192.168.0.0/24): range is not supported'); + expect(() => getIpToRemediate(ip)).toThrow('Input IP (192.168.0.0/24): range is not supported'); }); it('should parse a valid IPv6 address', () => { @@ -39,7 +39,7 @@ describe('getIpToRemediate', () => { it('should throw an error for an invalid IP format', () => { const ip = 'invalid-ip'; - expect(() => getIpToRemediate(ip)).toThrowError('Input IP format: invalid-ip is invalid'); + expect(() => getIpToRemediate(ip)).toThrow('Input IP format: invalid-ip is invalid'); }); }); @@ -58,12 +58,12 @@ describe('getFirstIpFromRange', () => { it('should throw an error for an invalid range format', () => { const range = 'invalid-range'; - expect(() => getFirstIpFromRange(range)).toThrowError('Input (invalid-range) is not a range.'); + expect(() => getFirstIpFromRange(range)).toThrow('Input (invalid-range) is not a range.'); }); it('should throw an error for a single IP address', () => { const range = '192.168.0.1'; - expect(() => getFirstIpFromRange(range)).toThrowError('Input (192.168.0.1) is not a range.'); + expect(() => getFirstIpFromRange(range)).toThrow('Input (192.168.0.1) is not a range.'); }); }); @@ -94,7 +94,7 @@ describe('getIpOrRangeType', () => { it('should throw an error for an invalid IP or range format', () => { const invalidInput = 'invalid-ip'; - expect(() => getIpOrRangeType(invalidInput)).toThrowError('Input IP format: invalid-ip is invalid'); + expect(() => getIpOrRangeType(invalidInput)).toThrow('Input IP format: invalid-ip is invalid'); }); }); @@ -110,22 +110,22 @@ describe('getIpV4BucketRange', () => { it('should throw an error for an invalid range format', () => { const range = 'invalid-range'; - expect(() => getIpV4BucketRange(range)).toThrowError('Input Range format (invalid-range).'); + expect(() => getIpV4BucketRange(range)).toThrow('Input Range format (invalid-range).'); }); it('should throw an error for a single IP address', () => { const range = '192.168.0.1'; - expect(() => getIpV4BucketRange(range)).toThrowError('Input Range format (192.168.0.1).'); + expect(() => getIpV4BucketRange(range)).toThrow('Input Range format (192.168.0.1).'); }); it('should throw an error for an IPv6 range', () => { const range = '2001:0db8:85a3::/64'; - expect(() => getIpV4BucketRange(range)).toThrowError('Only Ip V4 Range format is supported.'); + expect(() => getIpV4BucketRange(range)).toThrow('Only Ip V4 Range format is supported.'); }); it('should throw an error for an empty string', () => { const range = ''; - expect(() => getIpV4BucketRange(range)).toThrowError('Input Range format ().'); + expect(() => getIpV4BucketRange(range)).toThrow('Input Range format ().'); }); }); @@ -187,7 +187,7 @@ describe('isIpV4InRange', () => { throw new Error('Test error'); }); - expect(() => isIpV4InRange(ip, range)).toThrowError('Error checking IP in range: Test error'); + expect(() => isIpV4InRange(ip, range)).toThrow('Error checking IP in range: Test error'); }); it('should throw error when an unexpected error occurs', () => { const ip = '192.168.1.1'; @@ -198,7 +198,7 @@ describe('isIpV4InRange', () => { throw 'Test error'; }); - expect(() => isIpV4InRange(ip, range)).toThrowError('Error checking IP in range: Unknown error'); + expect(() => isIpV4InRange(ip, range)).toThrow('Error checking IP in range: Unknown error'); }); }); @@ -211,16 +211,16 @@ describe('getIpV4BucketIndexForIp', () => { it('should throw an error for an IPv6 address', () => { const ip = '2001:0db8:85a3:0000:0000:8a2e:0370:7334'; - expect(() => getIpV4BucketIndexForIp(ip)).toThrowError('Only Ip V4 format is supported.'); + expect(() => getIpV4BucketIndexForIp(ip)).toThrow('Only Ip V4 format is supported.'); }); it('should throw an error for an invalid IP format', () => { const ip = 'invalid-ip'; - expect(() => getIpV4BucketIndexForIp(ip)).toThrowError('Input IP format: invalid-ip is invalid'); + expect(() => getIpV4BucketIndexForIp(ip)).toThrow('Input IP format: invalid-ip is invalid'); }); it('should throw an error for an empty string', () => { const ip = ''; - expect(() => getIpV4BucketIndexForIp(ip)).toThrowError('Input IP format: is invalid'); + expect(() => getIpV4BucketIndexForIp(ip)).toThrow('Input IP format: is invalid'); }); }); diff --git a/src/helpers/decision.ts b/src/helpers/decision.ts index 458791b..61e86a2 100644 --- a/src/helpers/decision.ts +++ b/src/helpers/decision.ts @@ -1,7 +1,7 @@ -import { convertDurationToMilliseconds } from 'src/helpers/duration'; -import { CrowdSecBouncerConfigurations } from 'src/lib/bouncer/types'; -import { ID_SEPARATOR, REMEDIATION_BYPASS, CACHE_EXPIRATION_FOR_BAD_IP, ORIGIN_LISTS, ORIGIN_LISTS_SEPARATOR } from 'src/lib/constants'; -import logger from 'src/lib/logger'; +import { convertDurationToMilliseconds } from './duration'; +import { CrowdSecBouncerConfigurations } from '../lib/bouncer/types'; +import { ID_SEPARATOR, REMEDIATION_BYPASS, CACHE_EXPIRATION_FOR_BAD_IP, ORIGIN_LISTS, ORIGIN_LISTS_SEPARATOR } from '../lib/constants'; +import logger from '../lib/logger'; import { CachableDecision, Decision, @@ -14,7 +14,7 @@ import { Duration, Scenario, CachableOrigin, -} from 'src/lib/types'; +} from '../lib/types'; const validateRawDecision = (rawDecision: Decision): boolean => { if (rawDecision.origin === ORIGIN_LISTS && !rawDecision.scenario) { diff --git a/src/helpers/duration.ts b/src/helpers/duration.ts index c222f3e..b44e782 100644 --- a/src/helpers/duration.ts +++ b/src/helpers/duration.ts @@ -1,4 +1,4 @@ -import { Duration } from 'src/lib/types'; +import { Duration } from '../lib/types'; /** * The function `parseExpiration` takes a duration string and returns the TTL in milliseconds. diff --git a/src/helpers/ip.ts b/src/helpers/ip.ts index e17562f..2ffe2ea 100644 --- a/src/helpers/ip.ts +++ b/src/helpers/ip.ts @@ -1,6 +1,6 @@ import { Address4, Address6 } from 'ip-address'; -import { IP_TYPE_V4, IP_TYPE_V6, IPV4_BUCKET_SIZE } from 'src/lib/constants'; +import { IP_TYPE_V4, IP_TYPE_V6, IPV4_BUCKET_SIZE } from '../lib/constants'; export type IpType = typeof IP_TYPE_V4 | typeof IP_TYPE_V6; diff --git a/src/lib/__tests__/cache.test.ts b/src/lib/__tests__/cache.test.ts index 1f65abe..5025549 100644 --- a/src/lib/__tests__/cache.test.ts +++ b/src/lib/__tests__/cache.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it, jest, afterAll, beforeAll, afterEach, beforeEach } from '@jest/globals'; -import Keyv from 'keyv'; +import KeyvStore from 'keyv'; import * as ipModule from 'src/helpers/ip'; import CacheStorage from 'src/lib/cache'; @@ -14,7 +14,7 @@ let keyvAdapter: KeyvAdapter; describe('Cache', () => { describe('KeyvAdapter', () => { beforeAll(() => { - const storage = new Keyv(); + const storage = new KeyvStore(); keyvAdapter = new KeyvAdapter(storage); }); diff --git a/src/lib/__tests__/helpers-duration.test.ts b/src/lib/__tests__/helpers-duration.test.ts index 1f8bed1..900988d 100644 --- a/src/lib/__tests__/helpers-duration.test.ts +++ b/src/lib/__tests__/helpers-duration.test.ts @@ -47,6 +47,6 @@ describe('⏳ Parse duration', () => { expect(() => { convertDurationToMilliseconds(duration); - }).toThrowError('Unable to parse the following duration: invalid.'); + }).toThrow('Unable to parse the following duration: invalid.'); }); }); diff --git a/src/lib/__tests__/rendered.test.ts b/src/lib/__tests__/rendered.test.ts index 12b7a4a..3dab8d1 100644 --- a/src/lib/__tests__/rendered.test.ts +++ b/src/lib/__tests__/rendered.test.ts @@ -1,21 +1,10 @@ -import { beforeEach, describe, expect, it, jest } from '@jest/globals'; +import { describe, expect, it } from '@jest/globals'; -import fs from 'fs'; import { generateTemplate, renderBanWall, renderCaptchaWall } from 'src/lib/rendered'; -import { DEFAULT_COLORS, DEFAULT_TEXTS, TEMPLATES_PATH } from 'src/lib/rendered/constants'; +import { DEFAULT_COLORS, DEFAULT_TEXTS } from 'src/lib/rendered/constants'; import { BaseWallOptions } from 'src/lib/rendered/types'; -jest.mock('fs/promises', () => ({ - readFile: jest.fn(), -})); - -const readFileSpy = jest.spyOn(fs.promises, 'readFile'); - describe('📄 Generate Template', () => { - beforeEach(() => { - readFileSpy.mockClear(); - }); - it('should generate a base template', async () => { // Call the generateTemplate function const wall = await generateTemplate('base', { @@ -28,11 +17,6 @@ describe('📄 Generate Template', () => { expect(wall).toBeTruthy(); - expect(readFileSpy).toHaveBeenCalled(); - - // Assert that the readRawFile function was called with the correct arguments - expect(readFileSpy).toHaveBeenCalledWith(`${TEMPLATES_PATH}/base.ejs`, 'utf8'); - // Assert that the generated template matches the snapshot expect(wall).toMatchSnapshot(); }); @@ -43,12 +27,6 @@ describe('📄 Generate Template', () => { expect(wall).toBeTruthy(); - expect(readFileSpy).toHaveBeenCalled(); - - // Assert that the readRawFile function was called with the correct arguments - expect(readFileSpy).toHaveBeenNthCalledWith(1, `${TEMPLATES_PATH}/ban.ejs`, 'utf8'); - expect(readFileSpy).toHaveBeenNthCalledWith(2, `${TEMPLATES_PATH}/base.ejs`, 'utf8'); - // Assert that the generated template matches the snapshot expect(wall).toMatchSnapshot(); }); @@ -59,13 +37,6 @@ describe('📄 Generate Template', () => { expect(wall).toBeTruthy(); - expect(readFileSpy).toHaveBeenCalled(); - - // Assert that the readRawFile function was called with the correct arguments - expect(readFileSpy).toHaveBeenNthCalledWith(1, `${TEMPLATES_PATH}/captcha.ejs`, 'utf8'); - expect(readFileSpy).toHaveBeenNthCalledWith(2, `${TEMPLATES_PATH}/captcha-css.ejs`, 'utf8'); - expect(readFileSpy).toHaveBeenNthCalledWith(3, `${TEMPLATES_PATH}/base.ejs`, 'utf8'); - // Assert that the generated template matches the snapshot expect(wall).toMatchSnapshot(); }); diff --git a/src/lib/bouncer/constants.ts b/src/lib/bouncer/constants.ts index d4e3490..8eafc5a 100644 --- a/src/lib/bouncer/constants.ts +++ b/src/lib/bouncer/constants.ts @@ -1,5 +1,5 @@ -import { REMEDIATION_BYPASS, REMEDIATION_CAPTCHA, REMEDIATION_BAN } from 'src/lib/constants'; -import { Remediation } from 'src/lib/types'; +import { REMEDIATION_BYPASS, REMEDIATION_CAPTCHA, REMEDIATION_BAN } from '../constants'; +import { Remediation } from '../types'; // From lower priority to higher priority. export const ORDERED_REMEDIATIONS: Remediation[] = [REMEDIATION_BYPASS, REMEDIATION_CAPTCHA, REMEDIATION_BAN]; diff --git a/src/lib/bouncer/index.ts b/src/lib/bouncer/index.ts index 1e82c59..14a0ff4 100644 --- a/src/lib/bouncer/index.ts +++ b/src/lib/bouncer/index.ts @@ -1,21 +1,15 @@ -import { last, sortBy } from 'lodash'; +import lodash from 'lodash'; import svgCaptcha from 'svg-captcha-fixed'; -import { buildCachableDecision, convertRawDecisionsToDecisions } from 'src/helpers/decision'; -import { getFirstIpFromRange, getIpOrRangeType, getIpToRemediate } from 'src/helpers/ip'; -import { CaptchaGenerator } from 'src/lib/bouncer/captcha'; -import { - BOUNCING_LEVEL_DISABLED, - BOUNCING_LEVEL_FLEX, - BOUNCING_LEVEL_NORMAL, - ORDERED_REMEDIATIONS, - CAPTCHA_ERROR, -} from 'src/lib/bouncer/constants'; -import { CaptchaSubmission, CrowdSecBouncerConfigurations } from 'src/lib/bouncer/types'; -import CacheStorage from 'src/lib/cache'; -import { CAPTCHA_FLOW, ORIGINS_COUNT_KEY } from 'src/lib/cache/constants'; -import { getCacheKey } from 'src/lib/cache/helpers'; -import { CachableCaptchaFlow, CachableDecisionContent, CachableOriginsCount, CaptchaFlow, OriginCount } from 'src/lib/cache/types'; +import { CaptchaGenerator } from './captcha'; +import { BOUNCING_LEVEL_DISABLED, BOUNCING_LEVEL_FLEX, BOUNCING_LEVEL_NORMAL, ORDERED_REMEDIATIONS, CAPTCHA_ERROR } from './constants'; +import { CaptchaSubmission, CrowdSecBouncerConfigurations } from './types'; +import { buildCachableDecision, convertRawDecisionsToDecisions } from '../../helpers/decision'; +import { getFirstIpFromRange, getIpOrRangeType, getIpToRemediate } from '../../helpers/ip'; +import CacheStorage from '../cache'; +import { CAPTCHA_FLOW, ORIGINS_COUNT_KEY } from '../cache/constants'; +import { getCacheKey } from '../cache/helpers'; +import { CachableCaptchaFlow, CachableDecisionContent, CachableOriginsCount, CaptchaFlow, OriginCount } from '../cache/types'; import { BOUNCER_KEYS, CACHE_EXPIRATION_FOR_CAPTCHA_FLOW, @@ -30,14 +24,16 @@ import { SCOPE_IP, SCOPE_RANGE, VERSION, -} from 'src/lib/constants'; -import LapiClient from 'src/lib/lapi-client'; -import { MetricsBuilder, MetricItem } from 'src/lib/lapi-client/metrics'; -import { GetDecisionsOptions } from 'src/lib/lapi-client/types'; -import logger from 'src/lib/logger'; -import { renderBanWall, renderCaptchaWall } from 'src/lib/rendered'; -import { BanWallOptions, CaptchaWallOptions, WallsOptions } from 'src/lib/rendered/types'; -import { CachableDecision, CachableOrigin, Remediation } from 'src/lib/types'; +} from '../constants'; +import LapiClient from '../lapi-client'; +import { MetricsBuilder, MetricItem } from '../lapi-client/metrics'; +import { GetDecisionsOptions } from '../lapi-client/types'; +import logger from '../logger'; +import { renderBanWall, renderCaptchaWall } from '../rendered'; +import { BanWallOptions, CaptchaWallOptions, WallsOptions } from '../rendered/types'; +import { CachableDecision, CachableOrigin, Remediation } from '../types'; + +const { last, sortBy } = lodash; type CaptchaCreation = { cacheKey: string; @@ -55,6 +51,8 @@ type GetResponseParams = { origin: CachableOrigin; }; +type IpRemediationResult = Record & Record; + class CrowdSecBouncer { public readonly cacheStorage: CacheStorage; private readonly captcha: CaptchaGenerator; @@ -67,12 +65,7 @@ class CrowdSecBouncer { * @param ip - The IP address to get the remediation for. * @returns The remediation and its origin for the IP address. */ - public getIpRemediation = async ( - ip: string, - ): Promise<{ - [BOUNCER_KEYS.REMEDIATION]: Remediation; - [BOUNCER_KEYS.ORIGIN]: CachableOrigin; - }> => { + public getIpRemediation = async (ip: string): Promise => { const ipToRemediate = getIpToRemediate(ip); logger.debug(`Getting remediation for IP ${ip}`); diff --git a/src/lib/bouncer/types.ts b/src/lib/bouncer/types.ts index f8b714b..1d4f7e9 100644 --- a/src/lib/bouncer/types.ts +++ b/src/lib/bouncer/types.ts @@ -1,8 +1,8 @@ -import { BOUNCING_LEVEL_DISABLED, BOUNCING_LEVEL_FLEX, BOUNCING_LEVEL_NORMAL } from 'src/lib/bouncer/constants'; -import { CacheConfigurations } from 'src/lib/cache/types'; -import { LapiClientConfigurations } from 'src/lib/lapi-client/types'; -import { WallsOptions } from 'src/lib/rendered/types'; -import { CachableOrigin, Remediation } from 'src/lib/types'; +import { BOUNCING_LEVEL_DISABLED, BOUNCING_LEVEL_FLEX, BOUNCING_LEVEL_NORMAL } from './constants'; +import { CacheConfigurations } from '../cache/types'; +import { LapiClientConfigurations } from '../lapi-client/types'; +import { WallsOptions } from '../rendered/types'; +import { CachableOrigin, Remediation } from '../types'; type BouncingLevel = typeof BOUNCING_LEVEL_DISABLED | typeof BOUNCING_LEVEL_FLEX | typeof BOUNCING_LEVEL_NORMAL; diff --git a/src/lib/cache/decisions.ts b/src/lib/cache/decisions.ts index 8b1d3d0..fca52cd 100644 --- a/src/lib/cache/decisions.ts +++ b/src/lib/cache/decisions.ts @@ -1,4 +1,4 @@ -import { CachableDecisionItem, CachableDecisionContent } from 'src/lib/cache/types'; +import { CachableDecisionItem, CachableDecisionContent } from './types'; const getMaxExpiration = (valuesToCache: CachableDecisionContent[]): number => { return valuesToCache.reduce((maxExpiration, value) => { diff --git a/src/lib/cache/helpers.ts b/src/lib/cache/helpers.ts index 065448a..2868334 100644 --- a/src/lib/cache/helpers.ts +++ b/src/lib/cache/helpers.ts @@ -1,4 +1,4 @@ -import { CACHE_SEPARATOR } from 'src/lib/constants'; +import { CACHE_SEPARATOR } from '../constants'; export const getCacheKey = (prefix: string, value: string): string => { const result = `${prefix}${CACHE_SEPARATOR}${value}`; diff --git a/src/lib/cache/in-memory.ts b/src/lib/cache/in-memory.ts index d4c1464..79b03bc 100644 --- a/src/lib/cache/in-memory.ts +++ b/src/lib/cache/in-memory.ts @@ -1,11 +1,11 @@ -import Keyv from 'keyv'; +import KeyvStore from 'keyv'; -import KeyvAdapter from 'src/lib/cache/keyv-adapter'; +import KeyvAdapter from './keyv-adapter'; -const globalStorage = new Keyv(); +const globalStorage = new KeyvStore(); class InMemory extends KeyvAdapter { - constructor(storage: Keyv = globalStorage) { + constructor(storage: KeyvStore = globalStorage) { super(storage); } } diff --git a/src/lib/cache/index.ts b/src/lib/cache/index.ts index f6374d0..b79e161 100644 --- a/src/lib/cache/index.ts +++ b/src/lib/cache/index.ts @@ -1,15 +1,17 @@ -import { max } from 'lodash'; - -import { getIpV4BucketRange, IpV4Range, getIpOrRangeType, getIpV4BucketIndexForIp, isIpV4InRange } from 'src/helpers/ip'; -import { CONFIG, WARMUP, IPV4_BUCKET_KEY, ORIGINS_COUNT_KEY, FIRST_LAPI_CALL, LAST_METRICS_SENT } from 'src/lib/cache/constants'; -import { updateDecisionItem } from 'src/lib/cache/decisions'; -import { getCacheKey } from 'src/lib/cache/helpers'; -import InMemory from 'src/lib/cache/in-memory'; -import { CacheAdapter } from 'src/lib/cache/interfaces'; -import { CachableDecisionContent, CachableDecisionItem, CacheConfigurations, CachableOriginsCount, OriginCount } from 'src/lib/cache/types'; -import { SCOPE_IP, SCOPE_RANGE, IP_TYPE_V4 } from 'src/lib/constants'; -import logger from 'src/lib/logger'; -import { CachableDecision, CachableIdentifier, Value, Remediation, CachableOrigin } from 'src/lib/types'; +import lodash from 'lodash'; + +import { SCOPE_IP, SCOPE_RANGE, IP_TYPE_V4 } from '../constants'; +import logger from '../logger'; +import { CONFIG, WARMUP, IPV4_BUCKET_KEY, ORIGINS_COUNT_KEY, FIRST_LAPI_CALL, LAST_METRICS_SENT } from './constants'; +import { updateDecisionItem } from './decisions'; +import { getCacheKey } from './helpers'; +import InMemory from './in-memory'; +import { CacheAdapter } from './interfaces'; +import { CachableDecisionContent, CachableDecisionItem, CacheConfigurations, CachableOriginsCount, OriginCount } from './types'; +import { getIpV4BucketRange, IpV4Range, getIpOrRangeType, getIpV4BucketIndexForIp, isIpV4InRange } from '../../helpers/ip'; +import { CachableDecision, CachableIdentifier, Value, Remediation, CachableOrigin } from '../types'; + +const { max } = lodash; type UpsertMetricsOriginsCountParams = { origin: CachableOrigin; diff --git a/src/lib/cache/interfaces.ts b/src/lib/cache/interfaces.ts index 3005790..9fca63b 100644 --- a/src/lib/cache/interfaces.ts +++ b/src/lib/cache/interfaces.ts @@ -1,4 +1,4 @@ -import { CachableItem } from 'src/lib/cache/types'; +import { CachableItem } from './types'; export interface CacheAdapter { /** diff --git a/src/lib/cache/keyv-adapter.ts b/src/lib/cache/keyv-adapter.ts index d62a9b8..204f381 100644 --- a/src/lib/cache/keyv-adapter.ts +++ b/src/lib/cache/keyv-adapter.ts @@ -1,37 +1,32 @@ -import { createCache } from 'cache-manager'; -// @ts-expect-error - Keyv is a CommonJS module, TypeScript expects a different import style -import { Keyv } from 'keyv'; +import KeyvStore from 'keyv'; -import { CacheAdapter } from 'src/lib/cache/interfaces'; -import { CachableItem } from 'src/lib/cache/types'; - -type CacheAdapterType = ReturnType; +import type { CacheAdapter } from './interfaces'; +import type { CachableItem } from './types'; class KeyvAdapter implements CacheAdapter { - private readonly adapter: CacheAdapterType; + private readonly storage: KeyvStore; - constructor(storage: Keyv) { - this.adapter = createCache({ - stores: [storage], - }); + constructor(storage: KeyvStore) { + this.storage = storage; } async getItem(key: string): Promise { - const content = await this.adapter.get(key); - return content ? { key, content } : null; + const content = await this.storage.get(key); + return content === undefined || content === null ? null : { key, content }; } async setItem(item: CachableItem, ttl?: number): Promise { - await this.adapter.set(item.key, item.content, ttl); + await this.storage.set(item.key, item.content, ttl); return item; } async deleteItem(key: string): Promise { - return this.adapter.del(key); + return this.storage.delete(key); } async clear(): Promise { - return this.adapter.clear(); + await this.storage.clear(); + return true; } } diff --git a/src/lib/cache/types.ts b/src/lib/cache/types.ts index 90522fb..e3792fa 100644 --- a/src/lib/cache/types.ts +++ b/src/lib/cache/types.ts @@ -1,6 +1,6 @@ -import { CaptchaObj } from 'src/lib/bouncer/captcha'; -import { CacheAdapter } from 'src/lib/cache/interfaces'; -import { CachableOrigin, CachableIdentifier, Remediation, CachableExpiresAt } from 'src/lib/types'; +import { CachableOrigin, CachableIdentifier, Remediation, CachableExpiresAt } from '../types'; +import { CacheAdapter } from './interfaces'; +import { CaptchaObj } from '../bouncer/captcha'; export type CachableDecisionContent = { id: CachableIdentifier; diff --git a/src/lib/constants.ts b/src/lib/constants.ts index ba366f4..f43c24c 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -37,11 +37,11 @@ export enum REFRESH_KEYS { DELETED = 'deleted', } -export enum BOUNCER_KEYS { - REMEDIATION = 'remediation', - ORIGIN = 'origin', - CAPTCHA_PHRASE = 'captchaPhrase', -} +export const BOUNCER_KEYS = { + REMEDIATION: 'remediation', + ORIGIN: 'origin', + CAPTCHA_PHRASE: 'captchaPhrase', +} as const; export const METRICS_TYPE = 'crowdsec-nodejs-bouncer'; diff --git a/src/lib/lapi-client/index.ts b/src/lib/lapi-client/index.ts index 1067f9e..be13aca 100644 --- a/src/lib/lapi-client/index.ts +++ b/src/lib/lapi-client/index.ts @@ -1,13 +1,13 @@ -import { REFRESH_KEYS, VERSION, USER_AGENT_PREFIX } from 'src/lib/constants'; -import { FinalMetrics } from 'src/lib/lapi-client/metrics'; -import { GetDecisionsOptions, LapiClientConfigurations } from 'src/lib/lapi-client/types'; -import logger from 'src/lib/logger'; -import { ConnectionHealth, Decision } from 'src/lib/types'; +import { FinalMetrics } from './metrics'; +import { GetDecisionsOptions, LapiClientConfigurations } from './types'; +import { REFRESH_KEYS, VERSION, USER_AGENT_PREFIX } from '../constants'; +import logger from '../logger'; +import { ConnectionHealth, Decision } from '../types'; type CallLapiParams = { path: string; method: 'GET' | 'POST'; - body?: BodyInit | null; + body?: RequestInit['body']; }; class LapiClient { diff --git a/src/lib/lapi-client/metrics.ts b/src/lib/lapi-client/metrics.ts index 5c9e3f8..0848276 100644 --- a/src/lib/lapi-client/metrics.ts +++ b/src/lib/lapi-client/metrics.ts @@ -1,6 +1,6 @@ +import { METRICS_TYPE } from '../constants'; +import { CachableOrigin, Remediation } from '../types'; import os from 'os'; -import { METRICS_TYPE } from 'src/lib/constants'; -import { CachableOrigin, Remediation } from 'src/lib/types'; type MetricsProperties = { name: string; diff --git a/src/lib/lapi-client/types.ts b/src/lib/lapi-client/types.ts index 93e7993..cf6a81d 100644 --- a/src/lib/lapi-client/types.ts +++ b/src/lib/lapi-client/types.ts @@ -1,4 +1,4 @@ -import { Origin, Scope } from 'src/lib/types'; +import { Origin, Scope } from '../types'; export type LapiClientConfigurations = { url: string; diff --git a/src/lib/rendered/constants.ts b/src/lib/rendered/constants.ts index ae04fe6..c90c3b7 100644 --- a/src/lib/rendered/constants.ts +++ b/src/lib/rendered/constants.ts @@ -1,4 +1,7 @@ -import path from 'path'; +import banTpl from './templates/ban.ejs'; +import baseTpl from './templates/base.ejs'; +import captchaCssTpl from './templates/captcha-css.ejs'; +import captchaTpl from './templates/captcha.ejs'; export const DEFAULT_COLORS = { text: { @@ -33,4 +36,9 @@ export const DEFAULT_TEXTS = { }, }; -export const TEMPLATES_PATH = path.join(__dirname, '..', 'rendered', 'templates'); +export const RENDERED_TEMPLATES = { + ban: banTpl, + captcha: captchaTpl, + base: baseTpl, + 'captcha-css': captchaCssTpl, +} as const; diff --git a/src/lib/rendered/index.ts b/src/lib/rendered/index.ts index ab0711a..3940bdd 100644 --- a/src/lib/rendered/index.ts +++ b/src/lib/rendered/index.ts @@ -1,14 +1,14 @@ -import { template } from 'lodash'; +import lodash from 'lodash'; -import fs from 'fs'; -import { DEFAULT_COLORS, DEFAULT_TEXTS, TEMPLATES_PATH } from 'src/lib/rendered/constants'; -import { BanWallOptions, BaseWallOptions, CaptchaWallOptions, TemplateType } from 'src/lib/rendered/types'; +import { DEFAULT_COLORS, DEFAULT_TEXTS, RENDERED_TEMPLATES } from './constants'; +import { BanWallOptions, BaseWallOptions, CaptchaWallOptions, TemplateType } from './types'; + +const { template: compileTemplate } = lodash; export const generateTemplate = async (templateName: TemplateType, data: Record): Promise => { - const templatePath = `${TEMPLATES_PATH}/${templateName}.ejs`; - const content = await fs.promises.readFile(templatePath, 'utf8'); - const compiled = template(content); - return compiled(data); + const src = RENDERED_TEMPLATES[templateName]; + if (!src) throw new Error(`Unknown template: ${templateName}`); + return compileTemplate(src)(data); }; export const renderBanWall = async (options?: BanWallOptions): Promise => { diff --git a/src/lib/rendered/types.ts b/src/lib/rendered/types.ts index 7a4064f..73157ed 100644 --- a/src/lib/rendered/types.ts +++ b/src/lib/rendered/types.ts @@ -1,4 +1,4 @@ -import { DEFAULT_COLORS, DEFAULT_TEXTS } from 'src/lib/rendered/constants'; +import { DEFAULT_COLORS, DEFAULT_TEXTS } from './constants'; export type TemplateType = 'ban' | 'captcha' | 'base' | 'captcha-css'; diff --git a/src/lib/types.ts b/src/lib/types.ts index 85cc2da..efe221d 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,4 +1,4 @@ -import { ID_SEPARATOR } from 'src/lib/constants'; +import { ID_SEPARATOR } from './constants'; export type OkConnectionHealth = { status: 'OK'; diff --git a/src/types/ejs.d.ts b/src/types/ejs.d.ts new file mode 100644 index 0000000..96e15fd --- /dev/null +++ b/src/types/ejs.d.ts @@ -0,0 +1,6 @@ +// src/types/ejs.d.ts +declare module '*.ejs' { + /** Raw template text (already UTF-8 decoded). */ + const content: string; + export default content; +} diff --git a/tsconfig.json b/tsconfig.json index 484cb86..a6c3267 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,24 +1,36 @@ { - "compilerOptions": { - "baseUrl": ".", - "target": "es2016", - "module": "commonjs", - "outDir": "dist", - "rootDir": ".", - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "skipLibCheck": true, - "declaration": true - }, - "include": ["src/**/*", "index.ts"], - "exclude": ["node_modules", "dist", "jest.config.ts", "tests"], - "ts-node": { - "require": ["tsconfig-paths/register"], - "transpileOnly": true, - "files": true, - "compilerOptions": { - "rootDir": "." - } - } + "compilerOptions": { + "target": "ES2022", + "lib": [ + "ES2022" + ], + "module": "ESNext", + "moduleResolution": "Bundler", + "types": [ + "node" + ], + "rootDir": "src", + "outDir": "dist/tsc", + "declaration": true, + "emitDeclarationOnly": true, + "declarationMap": false, + "sourceMap": true, + "strict": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "isolatedModules": true + }, + "include": [ + "src/**/*", + "index.ts" + ], + "exclude": [ + "node_modules", + "dist", + "jest.config.ts", + "tests" + ] } diff --git a/tsup.config.ts b/tsup.config.ts new file mode 100644 index 0000000..2ac47bd --- /dev/null +++ b/tsup.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from 'tsup'; + +export default defineConfig({ + entry: ['src/index.ts'], + outDir: 'dist', + format: ['esm'], // ESM-only + dts: true, // generate dist/index.d.ts + sourcemap: true, + clean: true, + platform: 'node', + target: 'node20', + splitting: false, + treeshake: true, + tsconfig: 'tsconfig.json', + loader: { '.ejs': 'text' }, +}); From e2904c3d2548863695c99f50485746eb2a8e2e83 Mon Sep 17 00:00:00 2001 From: Julien Loizelet Date: Fri, 18 Jul 2025 18:12:25 +0900 Subject: [PATCH 02/11] test(*): Add NextJS example --- examples/nextjs/.gitignore | 44 +++++++ examples/nextjs/README.md | 20 +++ examples/nextjs/eslint.config.mjs | 16 +++ examples/nextjs/libs/crowdsec.ts | 46 +++++++ examples/nextjs/libs/helpers/index.ts | 23 ++++ examples/nextjs/next.config.ts | 28 ++++ examples/nextjs/package.json | 30 +++++ examples/nextjs/public/file.svg | 1 + examples/nextjs/public/globe.svg | 1 + examples/nextjs/public/next.svg | 1 + examples/nextjs/public/vercel.svg | 1 + examples/nextjs/public/window.svg | 1 + examples/nextjs/src/app/favicon.ico | Bin 0 -> 25931 bytes examples/nextjs/src/app/globals.css | 42 ++++++ examples/nextjs/src/app/layout.tsx | 30 +++++ examples/nextjs/src/app/page.module.css | 167 ++++++++++++++++++++++++ examples/nextjs/src/app/page.tsx | 17 +++ examples/nextjs/src/middleware.ts | 21 +++ examples/nextjs/tsconfig.json | 27 ++++ src/lib/logger.ts | 42 ++++-- 20 files changed, 545 insertions(+), 13 deletions(-) create mode 100644 examples/nextjs/.gitignore create mode 100644 examples/nextjs/README.md create mode 100644 examples/nextjs/eslint.config.mjs create mode 100644 examples/nextjs/libs/crowdsec.ts create mode 100644 examples/nextjs/libs/helpers/index.ts create mode 100644 examples/nextjs/next.config.ts create mode 100644 examples/nextjs/package.json create mode 100644 examples/nextjs/public/file.svg create mode 100644 examples/nextjs/public/globe.svg create mode 100644 examples/nextjs/public/next.svg create mode 100644 examples/nextjs/public/vercel.svg create mode 100644 examples/nextjs/public/window.svg create mode 100644 examples/nextjs/src/app/favicon.ico create mode 100644 examples/nextjs/src/app/globals.css create mode 100644 examples/nextjs/src/app/layout.tsx create mode 100644 examples/nextjs/src/app/page.module.css create mode 100644 examples/nextjs/src/app/page.tsx create mode 100644 examples/nextjs/src/middleware.ts create mode 100644 examples/nextjs/tsconfig.json diff --git a/examples/nextjs/.gitignore b/examples/nextjs/.gitignore new file mode 100644 index 0000000..ecde258 --- /dev/null +++ b/examples/nextjs/.gitignore @@ -0,0 +1,44 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +# package-lock.json +package-lock.json diff --git a/examples/nextjs/README.md b/examples/nextjs/README.md new file mode 100644 index 0000000..943aabd --- /dev/null +++ b/examples/nextjs/README.md @@ -0,0 +1,20 @@ +This is a [Next.js](https://nextjs.org) project used for demonstrating the integration of CrowdSec with a Next.js +application. + +## Getting Started + +First, build the bouncer package and install the dependencies: + +```bash +npm run package-locally +npm install +``` + +Then, run the development server: + +```bash +npm run dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + diff --git a/examples/nextjs/eslint.config.mjs b/examples/nextjs/eslint.config.mjs new file mode 100644 index 0000000..c85fb67 --- /dev/null +++ b/examples/nextjs/eslint.config.mjs @@ -0,0 +1,16 @@ +import { dirname } from "path"; +import { fileURLToPath } from "url"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const compat = new FlatCompat({ + baseDirectory: __dirname, +}); + +const eslintConfig = [ + ...compat.extends("next/core-web-vitals", "next/typescript"), +]; + +export default eslintConfig; diff --git a/examples/nextjs/libs/crowdsec.ts b/examples/nextjs/libs/crowdsec.ts new file mode 100644 index 0000000..9f96dda --- /dev/null +++ b/examples/nextjs/libs/crowdsec.ts @@ -0,0 +1,46 @@ +'use server'; + +import { CrowdSecBouncer, CrowdSecBouncerConfigurations } from '@crowdsec/nodejs-bouncer'; +import { NextResponse } from 'next/server'; + +import { loadEnv } from './helpers'; + +// Load and validate environment variables +loadEnv(); + +const config: CrowdSecBouncerConfigurations = { + url: process.env.LAPI_URL ?? 'http://localhost:8080', + bouncerApiToken: process.env.BOUNCER_KEY ?? '', +}; + +const bouncer = new CrowdSecBouncer(config); + +export const validateRequestWithCrowdSec = async () => { + const ip = process.env.BOUNCED_IP as string; // In a production scenario, the user's real IP should be retrieved. + + try { + console.log(`Checking CrowdSec remediation for IP: ${ip}`); + const remediationData = await bouncer.getIpRemediation(ip); + const { origin, remediation } = remediationData; + console.log(`Decision is : ${remediation}`); + if (remediation === 'ban') { + const bouncerResponse = await bouncer.getResponse({ + ip, + origin, + remediation, + }); + console.log(`Will show a ban wall`); + // If the decision is to block, return a 403 response + return new NextResponse(bouncerResponse.html, { + status: bouncerResponse.status, + headers: { + 'Content-Type': 'text/html; charset=utf-8', + }, + }); + } + // @TODO: Handle other remediation types like 'captcha' if needed + } catch (err) { + // Log the error for debugging purposes + console.error('CrowdSec check failed:', err); + } +}; diff --git a/examples/nextjs/libs/helpers/index.ts b/examples/nextjs/libs/helpers/index.ts new file mode 100644 index 0000000..40fb9a1 --- /dev/null +++ b/examples/nextjs/libs/helpers/index.ts @@ -0,0 +1,23 @@ +import dotenv from 'dotenv'; +import dotenvSafe from 'dotenv-safe'; + +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +// Load and validate environment variables from .env file +export const loadEnv = () => { + dotenvSafe.config({ + path: resolve(__dirname, '../../.env'), + example: resolve(__dirname, '../../.env.example'), + }); + dotenv.config(); + // Load and validate the .env file in the crowdsec folder (will override any duplicate values from the main .env) + dotenvSafe.config({ + path: resolve(__dirname, '../../crowdsec/.env'), + example: resolve(__dirname, '../../crowdsec/.env.example'), + }); + dotenv.config({ path: resolve(__dirname, '../crowdsec/.env') }); +}; diff --git a/examples/nextjs/next.config.ts b/examples/nextjs/next.config.ts new file mode 100644 index 0000000..81852c6 --- /dev/null +++ b/examples/nextjs/next.config.ts @@ -0,0 +1,28 @@ +// next.config.ts +import path from 'node:path'; +import CopyWebpackPlugin from 'copy-webpack-plugin'; +import type { NextConfig } from 'next'; + +const nextConfig: NextConfig = { + experimental: { + nodeMiddleware: true, // ← enable Node.js middleware support + }, + webpack(config, { isServer }) { + if (isServer) { + config.plugins = config.plugins || []; + config.plugins.push( + new CopyWebpackPlugin({ + patterns: [ + { + from: path.resolve(__dirname, 'node_modules/svg-captcha-fixed/fonts'), + to: path.resolve(__dirname, '.next/server/fonts'), + }, + ], + }), + ); + } + return config; + }, +}; + +export default nextConfig; diff --git a/examples/nextjs/package.json b/examples/nextjs/package.json new file mode 100644 index 0000000..e4ed2fb --- /dev/null +++ b/examples/nextjs/package.json @@ -0,0 +1,30 @@ +{ + "name": "nextjs", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "pack-locally": "(cd ../../ && npm run build && npm pack --silent) && mv ../../crowdsec-nodejs-bouncer-*.tgz ./cs-nodejs-bouncer.tgz" + }, + "dependencies": { + "@crowdsec/nodejs-bouncer": "file:./cs-nodejs-bouncer.tgz", + "next": "canary", + "react": "19.1.0", + "react-dom": "19.1.0" + }, + "devDependencies": { + "@eslint/eslintrc": "^3", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "copy-webpack-plugin": "^13.0.0", + "eslint": "^9", + "eslint-config-next": "15.4.1", + "typescript": "^5", + "dotenv": "^17.2.0", + "dotenv-safe": "^9.1.0" + } +} diff --git a/examples/nextjs/public/file.svg b/examples/nextjs/public/file.svg new file mode 100644 index 0000000..004145c --- /dev/null +++ b/examples/nextjs/public/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/nextjs/public/globe.svg b/examples/nextjs/public/globe.svg new file mode 100644 index 0000000..567f17b --- /dev/null +++ b/examples/nextjs/public/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/nextjs/public/next.svg b/examples/nextjs/public/next.svg new file mode 100644 index 0000000..5174b28 --- /dev/null +++ b/examples/nextjs/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/nextjs/public/vercel.svg b/examples/nextjs/public/vercel.svg new file mode 100644 index 0000000..7705396 --- /dev/null +++ b/examples/nextjs/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/nextjs/public/window.svg b/examples/nextjs/public/window.svg new file mode 100644 index 0000000..b2b2a44 --- /dev/null +++ b/examples/nextjs/public/window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/nextjs/src/app/favicon.ico b/examples/nextjs/src/app/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..718d6fea4835ec2d246af9800eddb7ffb276240c GIT binary patch literal 25931 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 LrJugUA?W`A8`#=m literal 0 HcmV?d00001 diff --git a/examples/nextjs/src/app/globals.css b/examples/nextjs/src/app/globals.css new file mode 100644 index 0000000..e3734be --- /dev/null +++ b/examples/nextjs/src/app/globals.css @@ -0,0 +1,42 @@ +:root { + --background: #ffffff; + --foreground: #171717; +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +html, +body { + max-width: 100vw; + overflow-x: hidden; +} + +body { + color: var(--foreground); + background: var(--background); + font-family: Arial, Helvetica, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +* { + box-sizing: border-box; + padding: 0; + margin: 0; +} + +a { + color: inherit; + text-decoration: none; +} + +@media (prefers-color-scheme: dark) { + html { + color-scheme: dark; + } +} diff --git a/examples/nextjs/src/app/layout.tsx b/examples/nextjs/src/app/layout.tsx new file mode 100644 index 0000000..4f8ea58 --- /dev/null +++ b/examples/nextjs/src/app/layout.tsx @@ -0,0 +1,30 @@ +import type { Metadata } from 'next'; +import { Geist, Geist_Mono } from 'next/font/google'; +import './globals.css'; + +const geistSans = Geist({ + variable: '--font-geist-sans', + subsets: ['latin'], +}); + +const geistMono = Geist_Mono({ + variable: '--font-geist-mono', + subsets: ['latin'], +}); + +export const metadata: Metadata = { + title: 'CrowdSec Node.js bouncer test page', + description: 'Example page to test CrowdSec Node.js bouncer integration with Next.js', +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + {children} + + ); +} diff --git a/examples/nextjs/src/app/page.module.css b/examples/nextjs/src/app/page.module.css new file mode 100644 index 0000000..58c71af --- /dev/null +++ b/examples/nextjs/src/app/page.module.css @@ -0,0 +1,167 @@ +.page { + --gray-rgb: 0, 0, 0; + --gray-alpha-200: rgba(var(--gray-rgb), 0.08); + --gray-alpha-100: rgba(var(--gray-rgb), 0.05); + + --button-primary-hover: #383838; + --button-secondary-hover: #f2f2f2; + + display: grid; + grid-template-rows: 20px 1fr 20px; + align-items: center; + justify-items: center; + min-height: 100svh; + padding: 80px; + gap: 64px; + font-family: var(--font-geist-sans); +} + +@media (prefers-color-scheme: dark) { + .page { + --gray-rgb: 255, 255, 255; + --gray-alpha-200: rgba(var(--gray-rgb), 0.145); + --gray-alpha-100: rgba(var(--gray-rgb), 0.06); + + --button-primary-hover: #ccc; + --button-secondary-hover: #1a1a1a; + } +} + +.main { + display: flex; + flex-direction: column; + gap: 32px; + grid-row-start: 2; +} + +.main ol { + font-family: var(--font-geist-mono); + padding-left: 0; + margin: 0; + font-size: 14px; + line-height: 24px; + letter-spacing: -0.01em; + list-style-position: inside; +} + +.main li:not(:last-of-type) { + margin-bottom: 8px; +} + +.main code { + font-family: inherit; + background: var(--gray-alpha-100); + padding: 2px 4px; + border-radius: 4px; + font-weight: 600; +} + +.ctas { + display: flex; + gap: 16px; +} + +.ctas a { + appearance: none; + border-radius: 128px; + height: 48px; + padding: 0 20px; + border: 1px solid transparent; + transition: + background 0.2s, + color 0.2s, + border-color 0.2s; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 16px; + line-height: 20px; + font-weight: 500; +} + +a.primary { + background: var(--foreground); + color: var(--background); + gap: 8px; +} + +a.secondary { + border-color: var(--gray-alpha-200); + min-width: 158px; +} + +.footer { + grid-row-start: 3; + display: flex; + gap: 24px; +} + +.footer a { + display: flex; + align-items: center; + gap: 8px; +} + +.footer img { + flex-shrink: 0; +} + +/* Enable hover only on non-touch devices */ +@media (hover: hover) and (pointer: fine) { + a.primary:hover { + background: var(--button-primary-hover); + border-color: transparent; + } + + a.secondary:hover { + background: var(--button-secondary-hover); + border-color: transparent; + } + + .footer a:hover { + text-decoration: underline; + text-underline-offset: 4px; + } +} + +@media (max-width: 600px) { + .page { + padding: 32px; + padding-bottom: 80px; + } + + .main { + align-items: center; + } + + .main ol { + text-align: center; + } + + .ctas { + flex-direction: column; + } + + .ctas a { + font-size: 14px; + height: 40px; + padding: 0 16px; + } + + a.secondary { + min-width: auto; + } + + .footer { + flex-wrap: wrap; + align-items: center; + justify-content: center; + } +} + +@media (prefers-color-scheme: dark) { + .logo { + filter: invert(); + } +} diff --git a/examples/nextjs/src/app/page.tsx b/examples/nextjs/src/app/page.tsx new file mode 100644 index 0000000..768d8cb --- /dev/null +++ b/examples/nextjs/src/app/page.tsx @@ -0,0 +1,17 @@ +import Image from 'next/image'; +import styles from './page.module.css'; + +export default function Home() { + return ( +
+
+ Next.js logo +
+

Welcome to the Test Page

+

If you see this, you're not banned.

+
+
+
+
+ ); +} diff --git a/examples/nextjs/src/middleware.ts b/examples/nextjs/src/middleware.ts new file mode 100644 index 0000000..62cef4b --- /dev/null +++ b/examples/nextjs/src/middleware.ts @@ -0,0 +1,21 @@ +import type { NextRequest } from 'next/server'; +import { NextResponse } from 'next/server'; +import { validateRequestWithCrowdSec } from '../libs/crowdsec'; + +// force Node.js runtime for this middleware +export const config = { + runtime: 'nodejs', // ← switch from Edge to Node.js + matcher: ['/:path*'], // ← or whatever paths you need +}; + +export async function middleware(_req: NextRequest) { + console.log('Middleware triggered: validating request with CrowdSec'); + const crowdsecResponse = await validateRequestWithCrowdSec(); + + if (crowdsecResponse) { + // This returns your CrowdSec response (e.g., Forbidden) + return crowdsecResponse; + } + + return NextResponse.next(); +} diff --git a/examples/nextjs/tsconfig.json b/examples/nextjs/tsconfig.json new file mode 100644 index 0000000..c133409 --- /dev/null +++ b/examples/nextjs/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/src/lib/logger.ts b/src/lib/logger.ts index 1e2841c..6448054 100644 --- a/src/lib/logger.ts +++ b/src/lib/logger.ts @@ -1,15 +1,31 @@ -import { pino } from 'pino'; - -const LOG_LEVEL = process.env.LOG_LEVEL || 'debug'; - -const logger = pino({ - level: LOG_LEVEL, - transport: { - target: 'pino-pretty', - options: { - colorize: !process.env.CS_NO_COLOR, - }, - }, -}); +import { pino, Logger } from 'pino'; + +const LOG_LEVEL = process.env.LOG_LEVEL ?? 'debug'; + +// Detect clean Node.js runtime (bundler or Edge runtime will fall back without transport) +const isNode = typeof process !== 'undefined' && Boolean(process.versions?.node); + +let logger: Logger; + +if (isNode) { + try { + logger = pino({ + level: LOG_LEVEL, + transport: { + target: 'pino-pretty', + options: { + // Disable colors if CS_NO_COLOR is set + colorize: !process.env.CS_NO_COLOR, + }, + }, + }); + } catch { + // If transport resolution fails (e.g. webpack), fallback to default pino + logger = pino({ level: LOG_LEVEL }); + } +} else { + // Non-Node environments: plain JSON output + logger = pino({ level: LOG_LEVEL }); +} export default logger; From 89edf809993356e9cd9f30ac8922cbf402bb1cb2 Mon Sep 17 00:00:00 2001 From: Julien Loizelet Date: Fri, 25 Jul 2025 10:55:45 +0900 Subject: [PATCH 03/11] feat(*): Add captchaAction setting Make nextjs example works --- CHANGELOG.md | 14 ++ examples/express-server/README.md | 12 +- examples/nextjs/README.md | 166 ++++++++++++++++-- examples/nextjs/crowdsec/custom-config.yaml | 7 + examples/nextjs/docker-compose.yml | 10 ++ examples/nextjs/libs/crowdsec.ts | 46 ----- examples/nextjs/next.config.ts | 3 - examples/nextjs/package.json | 11 +- .../app/api/crowdsec}/helpers/index.ts | 10 +- examples/nextjs/src/app/api/crowdsec/route.ts | 43 +++++ .../nextjs/src/app/crowdsec-captcha/route.ts | 36 ++++ examples/nextjs/src/middleware.ts | 40 +++-- src/lib/rendered/index.ts | 1 + src/lib/rendered/templates/captcha.ejs | 2 +- src/lib/rendered/types.ts | 1 + 15 files changed, 313 insertions(+), 89 deletions(-) create mode 100644 examples/nextjs/crowdsec/custom-config.yaml create mode 100644 examples/nextjs/docker-compose.yml delete mode 100644 examples/nextjs/libs/crowdsec.ts rename examples/nextjs/{libs => src/app/api/crowdsec}/helpers/index.ts (61%) create mode 100644 examples/nextjs/src/app/api/crowdsec/route.ts create mode 100644 examples/nextjs/src/app/crowdsec-captcha/route.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 371bc23..995e0dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,20 @@ The [public API](https://semver.org/spec/v2.0.0.html#spec-item-1) of this librar properties and constants belonging to the `src` folder. +--- + +## [0.2.0](https://github.com/crowdsecurity/nodejs-cs-bouncer/releases/tag/v0.2.0) - 2025-??-?? + +[_Compare with previous release_](https://github.com/crowdsecurity/nodejs-cs-bouncer/compare/v0.1.0...v0.2.0) + +### Changed + +- **Breaking Change**: Migrate from CommonJS to ESM + +### Added + +- Add optional `captchaAction` configuration to set the action attribute of the captcha form + --- ## [0.1.0](https://github.com/crowdsecurity/nodejs-cs-bouncer/releases/tag/v0.1.0) - 2025-03-28 diff --git a/examples/express-server/README.md b/examples/express-server/README.md index 4ecdc46..55e9d5c 100644 --- a/examples/express-server/README.md +++ b/examples/express-server/README.md @@ -12,11 +12,11 @@ It aims to help developers to understand how to integrate CrowdSec remediation i - [Technical overview](#technical-overview) - [Test the bouncer](#test-the-bouncer) - - [Pre-requisites](#pre-requisites) - - [Prepare the tests](#prepare-the-tests) - - [Test a "bypass" remediation](#test-a-bypass-remediation) - - [Test a "ban" remediation](#test-a-ban-remediation) - - [Test a "captcha" remediation](#test-a-captcha-remediation) + - [Pre-requisites](#pre-requisites) + - [Prepare the tests](#prepare-the-tests) + - [Test a "bypass" remediation](#test-a-bypass-remediation) + - [Test a "ban" remediation](#test-a-ban-remediation) + - [Test a "captcha" remediation](#test-a-captcha-remediation) @@ -35,7 +35,7 @@ const { origin, remediation } = remediationData; - Depending on the value of the remediation, we apply it: - - let the process continue with `next()`if there is no remediation (bypass) + - let the process continue with `next()` if there is no remediation (bypass) - block the user with a ban or captcha wall remediation: diff --git a/examples/nextjs/README.md b/examples/nextjs/README.md index 943aabd..b46f474 100644 --- a/examples/nextjs/README.md +++ b/examples/nextjs/README.md @@ -1,20 +1,166 @@ -This is a [Next.js](https://nextjs.org) project used for demonstrating the integration of CrowdSec with a Next.js -application. +# Express server basic implementation -## Getting Started +The `express-server` folder contains a basic implementation of the CrowdSec NodeJs +remediation component. -First, build the bouncer package and install the dependencies: +It aims to help developers to understand how to integrate CrowdSec remediation in their NodeJs application. -```bash -npm run package-locally -npm install +**Table of Contents** + + + + +- [Technical overview](#technical-overview) +- [Test the bouncer](#test-the-bouncer) + - [Pre-requisites](#pre-requisites) + - [Prepare the tests](#prepare-the-tests) + - [Test a "bypass" remediation](#test-a-bypass-remediation) + - [Test a "ban" remediation](#test-a-ban-remediation) + - [Test a "captcha" remediation](#test-a-captcha-remediation) + + + +## Technical overview + +All the logic is done in the `src/middleware.ts` and `src/app/api/crowdsec` files: + +- we use a middleware to act before rendering the page + +- We retrieve the remediation for the current tested IP: + +```js +const remediationData = await bouncer.getIpRemediation(ip); +const { origin, remediation } = remediationData; +``` + +- Depending on the value of the remediation, we apply it: + + - let the process continue if there is no remediation (bypass) + + - block the user with a ban wall remediation: + + ```js + + // Display Ban wall + if (remediation === 'ban') { + const bouncerResponse = await bouncer.getResponse({ + ip, + origin, + remediation, + }); + return new NextResponse(bouncerResponse.html, { + status: bouncerResponse.status, + headers: { + 'Content-Type': 'text/html; charset=utf-8', + }, + }); + } + ``` + +## Test the bouncer + +### Pre-requisites + +- Node.js and Docker installed on your machine + + - You can run `nvm use` from the root folder to use the recommended NodeJS version for this project + +- Copy the `.env.example` file to `.env` and fill in the required values + +- Copy the `crowdsec/.env.example` file to `crowdsec/.env` and fill in the required values + +- Install all dependencies using a local archive. + + Run the following commands from the `express-server` folder: + + ```shell + npm run pack-locally && npm install + ``` + +### Prepare the tests + +1. Launch the docker instance: + +```shell +docker compose up +``` + +This will instantiate a CrowdSec container with a `http://localhost:8080` LAPI url. + +2. Create a bouncer + +In another terminal, create a bouncer if you haven't already: + +```shell +docker exec -ti nodejs-cs-nextjs-crowdsec sh -c 'cscli bouncers add NodeBouncer --key $BOUNCER_KEY' +``` + +We are using here the `BOUNCER_KEY` variable defined in `crowdsec/.env` file. + +3. Launch the Express Server + +```shell +npm run start ``` -Then, run the development server: +For development, you can use: -```bash +```shell npm run dev ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +This will launch an Express server accessible on `http://localhost:3000` (aka "the home page") with +`tests/express-server/server.ts` file as entry point. + +You should see different log messages in your terminal when you access the home page. + +### Test a "bypass" remediation + +As you don't have yet any decisions, you can access the `http://localhost:3000` page and just see the normal content " +Welcome to the Test Page". + +![](./docs/bypass.png) + +You should see `Final remediation for IP is bypass` in the terminal. + +### Test a "ban" remediation + +First, add a ban remediation for the IP that will be tested: + +```shell +docker exec -ti nodejs-cs-nextjs-crowdsec sh -c 'cscli decisions add --ip $BOUNCED_IP --duration 12m --type ban' +``` + +We are using here the `BOUNCED_IP` variable defined in `crowdsec/.env` file. + +You should see the success message `Decision successfully added`. + +If you try to access the home page (after one minute as it is the default ttl for clean IP), you should the "Access +Denied" ban wall. + +![](./docs/ban-wall.png) + +You should see `Final remediation for IP is ban` in terminal. + +### Test a "captcha" remediation + +First, remove your last decision: + +```shell +docker exec -ti nodejs-cs-crowdsec sh -c 'cscli decisions delete --ip $BOUNCED_IP' +``` + +Then, add a captcha decision: + +```shell +docker exec -ti nodejs-cs-crowdsec sh -c 'cscli decisions add --ip $BOUNCED_IP --duration 12m --type captcha' +``` + +If you try to access the home page (after two minutes as it is the default ttl for malicious IP), you should the "Access +Denied" captcha wall. + +![](./docs/captcha-wall.png) + +You should see `Final remediation for IP is captcha` in terminal. +For this basic implementation, we just redirect user to `/` after resolution. diff --git a/examples/nextjs/crowdsec/custom-config.yaml b/examples/nextjs/crowdsec/custom-config.yaml new file mode 100644 index 0000000..e628c94 --- /dev/null +++ b/examples/nextjs/crowdsec/custom-config.yaml @@ -0,0 +1,7 @@ +common: + daemonize: false + pid_dir: /var/run/ + log_media: file + log_level: info + log_dir: /var/log/ + working_dir: . diff --git a/examples/nextjs/docker-compose.yml b/examples/nextjs/docker-compose.yml new file mode 100644 index 0000000..7b9f51d --- /dev/null +++ b/examples/nextjs/docker-compose.yml @@ -0,0 +1,10 @@ +services: + crowdsec: + container_name: nodejs-cs-nextjs-crowdsec + image: crowdsecurity/crowdsec:latest + ports: + - '8080:8080' + env_file: + - ./crowdsec/.env + volumes: + - ./crowdsec/custom-config.yaml:/etc/crowdsec/config.yaml.local diff --git a/examples/nextjs/libs/crowdsec.ts b/examples/nextjs/libs/crowdsec.ts deleted file mode 100644 index 9f96dda..0000000 --- a/examples/nextjs/libs/crowdsec.ts +++ /dev/null @@ -1,46 +0,0 @@ -'use server'; - -import { CrowdSecBouncer, CrowdSecBouncerConfigurations } from '@crowdsec/nodejs-bouncer'; -import { NextResponse } from 'next/server'; - -import { loadEnv } from './helpers'; - -// Load and validate environment variables -loadEnv(); - -const config: CrowdSecBouncerConfigurations = { - url: process.env.LAPI_URL ?? 'http://localhost:8080', - bouncerApiToken: process.env.BOUNCER_KEY ?? '', -}; - -const bouncer = new CrowdSecBouncer(config); - -export const validateRequestWithCrowdSec = async () => { - const ip = process.env.BOUNCED_IP as string; // In a production scenario, the user's real IP should be retrieved. - - try { - console.log(`Checking CrowdSec remediation for IP: ${ip}`); - const remediationData = await bouncer.getIpRemediation(ip); - const { origin, remediation } = remediationData; - console.log(`Decision is : ${remediation}`); - if (remediation === 'ban') { - const bouncerResponse = await bouncer.getResponse({ - ip, - origin, - remediation, - }); - console.log(`Will show a ban wall`); - // If the decision is to block, return a 403 response - return new NextResponse(bouncerResponse.html, { - status: bouncerResponse.status, - headers: { - 'Content-Type': 'text/html; charset=utf-8', - }, - }); - } - // @TODO: Handle other remediation types like 'captcha' if needed - } catch (err) { - // Log the error for debugging purposes - console.error('CrowdSec check failed:', err); - } -}; diff --git a/examples/nextjs/next.config.ts b/examples/nextjs/next.config.ts index 81852c6..5ba31a0 100644 --- a/examples/nextjs/next.config.ts +++ b/examples/nextjs/next.config.ts @@ -4,9 +4,6 @@ import CopyWebpackPlugin from 'copy-webpack-plugin'; import type { NextConfig } from 'next'; const nextConfig: NextConfig = { - experimental: { - nodeMiddleware: true, // ← enable Node.js middleware support - }, webpack(config, { isServer }) { if (isServer) { config.plugins = config.plugins || []; diff --git a/examples/nextjs/package.json b/examples/nextjs/package.json index e4ed2fb..d6e0077 100644 --- a/examples/nextjs/package.json +++ b/examples/nextjs/package.json @@ -11,20 +11,21 @@ }, "dependencies": { "@crowdsec/nodejs-bouncer": "file:./cs-nodejs-bouncer.tgz", - "next": "canary", + "next": "^15.4.2", "react": "19.1.0", "react-dom": "19.1.0" }, "devDependencies": { "@eslint/eslintrc": "^3", + "@types/dotenv-safe": "^8.1.6", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "copy-webpack-plugin": "^13.0.0", - "eslint": "^9", - "eslint-config-next": "15.4.1", - "typescript": "^5", "dotenv": "^17.2.0", - "dotenv-safe": "^9.1.0" + "dotenv-safe": "^9.1.0", + "eslint": "^9", + "eslint-config-next": "^15.4.1", + "typescript": "^5" } } diff --git a/examples/nextjs/libs/helpers/index.ts b/examples/nextjs/src/app/api/crowdsec/helpers/index.ts similarity index 61% rename from examples/nextjs/libs/helpers/index.ts rename to examples/nextjs/src/app/api/crowdsec/helpers/index.ts index 40fb9a1..c20445c 100644 --- a/examples/nextjs/libs/helpers/index.ts +++ b/examples/nextjs/src/app/api/crowdsec/helpers/index.ts @@ -10,14 +10,14 @@ const __dirname = dirname(__filename); // Load and validate environment variables from .env file export const loadEnv = () => { dotenvSafe.config({ - path: resolve(__dirname, '../../.env'), - example: resolve(__dirname, '../../.env.example'), + path: resolve(__dirname, '../../../../../.env'), + example: resolve(__dirname, '../../../../../.env.example'), }); dotenv.config(); // Load and validate the .env file in the crowdsec folder (will override any duplicate values from the main .env) dotenvSafe.config({ - path: resolve(__dirname, '../../crowdsec/.env'), - example: resolve(__dirname, '../../crowdsec/.env.example'), + path: resolve(__dirname, '../../../../../crowdsec/.env'), + example: resolve(__dirname, '../../../../../crowdsec/.env.example'), }); - dotenv.config({ path: resolve(__dirname, '../crowdsec/.env') }); + dotenv.config({ path: resolve(__dirname, '../../../../../crowdsec/.env') }); }; diff --git a/examples/nextjs/src/app/api/crowdsec/route.ts b/examples/nextjs/src/app/api/crowdsec/route.ts new file mode 100644 index 0000000..c35b529 --- /dev/null +++ b/examples/nextjs/src/app/api/crowdsec/route.ts @@ -0,0 +1,43 @@ +'use server'; + +import { CrowdSecBouncer, CrowdSecBouncerConfigurations } from '@crowdsec/nodejs-bouncer'; +import { NextResponse } from 'next/server'; + +import { loadEnv } from './helpers'; + +// Load and validate environment variables +loadEnv(); + +const config: CrowdSecBouncerConfigurations = { + url: process.env.LAPI_URL ?? 'http://localhost:8080', + bouncerApiToken: process.env.BOUNCER_KEY ?? '', + wallsOptions: { + captcha: { + captchaAction: '/crowdsec-captcha', + }, + }, +}; + +const bouncer = new CrowdSecBouncer(config); + +export async function POST(req: Request) { + const ip = process.env.BOUNCED_IP as string; // In a production scenario, the user's real IP should be retrieved. + + console.log('CrowdSec API route called with IP:', ip); + + try { + const { remediation, origin } = await bouncer.getIpRemediation(ip); + const bouncerResponse = await bouncer.getResponse({ ip, origin, remediation }); + + if (remediation === 'ban' || remediation === 'captcha') { + return new NextResponse(bouncerResponse.html, { + status: bouncerResponse.status, + }); + } + + return new NextResponse(null, { status: 200 }); + } catch (err) { + console.error('CrowdSec API route error:', err); + return new NextResponse(null, { status: 500 }); + } +} diff --git a/examples/nextjs/src/app/crowdsec-captcha/route.ts b/examples/nextjs/src/app/crowdsec-captcha/route.ts new file mode 100644 index 0000000..468e777 --- /dev/null +++ b/examples/nextjs/src/app/crowdsec-captcha/route.ts @@ -0,0 +1,36 @@ +import { NextResponse } from 'next/server'; +import { CrowdSecBouncer, CrowdSecBouncerConfigurations } from '@crowdsec/nodejs-bouncer'; +import { loadEnv } from '../../app/api/crowdsec/helpers'; + +// Load and validate environment variables +loadEnv(); + +const config: CrowdSecBouncerConfigurations = { + url: process.env.LAPI_URL ?? 'http://localhost:8080', + bouncerApiToken: process.env.BOUNCER_KEY ?? '', + wallsOptions: { + captcha: { + captchaAction: '/crowdsec-captcha', + }, + }, +}; + +const bouncer = new CrowdSecBouncer(config); + +export async function POST(req: Request) { + const form = await req.formData(); + const ip = process.env.BOUNCED_IP!; + const phrase = form.get('phrase')?.toString() || ''; + const refresh = (form.get('crowdsec_captcha_refresh')?.toString() as '1') || '0'; + + try { + const remediationData = await bouncer.getIpRemediation(ip); + const { origin } = remediationData; + await bouncer.handleCaptchaSubmission({ ip, userPhrase: phrase, refresh, origin }); + const captchaSuccessUrl = '/'; + return NextResponse.redirect(new URL(captchaSuccessUrl, req.url)); + } catch (err) { + console.error('[CrowdSec] captcha submission failed:', err); + return new NextResponse('Captcha verification failed.', { status: 400 }); + } +} diff --git a/examples/nextjs/src/middleware.ts b/examples/nextjs/src/middleware.ts index 62cef4b..6943793 100644 --- a/examples/nextjs/src/middleware.ts +++ b/examples/nextjs/src/middleware.ts @@ -1,20 +1,34 @@ -import type { NextRequest } from 'next/server'; import { NextResponse } from 'next/server'; -import { validateRequestWithCrowdSec } from '../libs/crowdsec'; +import type { NextRequest } from 'next/server'; + +export async function middleware(req: NextRequest) { + const { pathname } = req.nextUrl; + if (pathname === '/crowdsec-captcha') { + return NextResponse.next(); + } + + const acceptHeader = req.headers.get('accept') || ''; -// force Node.js runtime for this middleware -export const config = { - runtime: 'nodejs', // ← switch from Edge to Node.js - matcher: ['/:path*'], // ← or whatever paths you need -}; + // Only run middleware for full HTML page requests + if (!acceptHeader.includes('text/html')) { + return NextResponse.next(); + } + const checkUrl = `${req.nextUrl.origin}/api/crowdsec`; -export async function middleware(_req: NextRequest) { - console.log('Middleware triggered: validating request with CrowdSec'); - const crowdsecResponse = await validateRequestWithCrowdSec(); + try { + const res = await fetch(checkUrl, { + method: 'POST', + }); - if (crowdsecResponse) { - // This returns your CrowdSec response (e.g., Forbidden) - return crowdsecResponse; + if (res.status !== 200) { + const html = await res.text(); + return new NextResponse(html, { + status: res.status, + headers: { 'Content-Type': 'text/html; charset=utf-8' }, + }); + } + } catch (err) { + console.error('CrowdSec check failed in middleware:', err); } return NextResponse.next(); diff --git a/src/lib/rendered/index.ts b/src/lib/rendered/index.ts index 3940bdd..eda3055 100644 --- a/src/lib/rendered/index.ts +++ b/src/lib/rendered/index.ts @@ -55,6 +55,7 @@ export const renderCaptchaWall = async (options?: CaptchaWallOptions): Promise

<%- texts.error %>

<% } %> -
+> diff --git a/src/lib/rendered/types.ts b/src/lib/rendered/types.ts index 73157ed..cc49b01 100644 --- a/src/lib/rendered/types.ts +++ b/src/lib/rendered/types.ts @@ -26,6 +26,7 @@ export type CaptchaWallOptions = BaseWallOptions & texts: Partial<(typeof DEFAULT_TEXTS)['captcha']>; }> & { captchaImageTag?: string; + captchaAction?: string; }; export type WallsOptions = { From 7098b93daa4a3610bfe03c0d83019728a24b948d Mon Sep 17 00:00:00 2001 From: Julien Loizelet Date: Fri, 25 Jul 2025 13:48:18 +0900 Subject: [PATCH 04/11] feat(logger): Remove pino-pretty and color --- .gitignore | 3 + examples/express-server/docker-compose.yml | 2 +- examples/express-server/helpers/index.ts | 6 - examples/nextjs/.env.example | 3 + examples/nextjs/.gitignore | 4 +- examples/nextjs/crowdsec/.env.example | 2 + examples/nextjs/docker-compose.yml | 2 +- examples/nextjs/eslint.config.mjs | 12 +- examples/nextjs/package.json | 9 +- .../src/app/api/crowdsec/helpers/index.ts | 7 + examples/nextjs/src/app/api/crowdsec/route.ts | 12 +- .../nextjs/src/app/crowdsec-captcha/route.ts | 2 +- examples/nextjs/src/app/globals.css | 42 ++-- examples/nextjs/src/app/page.module.css | 216 +++++++++--------- package.json | 1 - src/helpers/__tests__/decision.test.ts | 6 +- src/helpers/__tests__/ip.test.ts | 11 +- src/lib/__tests__/bouncer.test.ts | 22 +- src/lib/__tests__/cache.test.ts | 14 +- src/lib/__tests__/helpers-duration.test.ts | 2 +- src/lib/__tests__/lapi-client.test.ts | 8 +- src/lib/__tests__/logger.test.ts | 2 +- src/lib/__tests__/metrics.test.ts | 4 +- src/lib/__tests__/rendered.test.ts | 6 +- src/lib/bouncer/index.ts | 2 +- src/lib/logger.ts | 28 +-- src/lib/rendered/templates/captcha.ejs | 2 +- 27 files changed, 205 insertions(+), 225 deletions(-) create mode 100644 examples/nextjs/.env.example create mode 100644 examples/nextjs/crowdsec/.env.example diff --git a/.gitignore b/.gitignore index f8905bd..355c6ca 100644 --- a/.gitignore +++ b/.gitignore @@ -129,3 +129,6 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +# CLaude +.claude diff --git a/examples/express-server/docker-compose.yml b/examples/express-server/docker-compose.yml index beb9496..e290c72 100644 --- a/examples/express-server/docker-compose.yml +++ b/examples/express-server/docker-compose.yml @@ -5,6 +5,6 @@ services: ports: - '8080:8080' env_file: - - ./crowdsec/.env + - crowdsec/.env volumes: - ./crowdsec/custom-config.yaml:/etc/crowdsec/config.yaml.local diff --git a/examples/express-server/helpers/index.ts b/examples/express-server/helpers/index.ts index 1c84594..a942363 100644 --- a/examples/express-server/helpers/index.ts +++ b/examples/express-server/helpers/index.ts @@ -21,12 +21,6 @@ export const getExcludedPaths = () => { export const getLogger = () => { return pino({ level: process.env.TEST_LOG_LEVEL ?? 'debug', - transport: { - target: 'pino-pretty', - options: { - colorize: false, - }, - }, }); }; diff --git a/examples/nextjs/.env.example b/examples/nextjs/.env.example new file mode 100644 index 0000000..5a515bc --- /dev/null +++ b/examples/nextjs/.env.example @@ -0,0 +1,3 @@ +LAPI_URL='http://localhost:8080' +TEST_LOG_LEVEL='debug' + diff --git a/examples/nextjs/.gitignore b/examples/nextjs/.gitignore index ecde258..53f105e 100644 --- a/examples/nextjs/.gitignore +++ b/examples/nextjs/.gitignore @@ -31,7 +31,7 @@ yarn-error.log* .pnpm-debug.log* # env files (can opt-in for committing if needed) -.env* +.env # vercel .vercel @@ -41,4 +41,4 @@ yarn-error.log* next-env.d.ts # package-lock.json -package-lock.json +package-lock.json \ No newline at end of file diff --git a/examples/nextjs/crowdsec/.env.example b/examples/nextjs/crowdsec/.env.example new file mode 100644 index 0000000..b04630d --- /dev/null +++ b/examples/nextjs/crowdsec/.env.example @@ -0,0 +1,2 @@ +BOUNCER_KEY='1234' +BOUNCED_IP='172.19.0.1' \ No newline at end of file diff --git a/examples/nextjs/docker-compose.yml b/examples/nextjs/docker-compose.yml index 7b9f51d..d9969d1 100644 --- a/examples/nextjs/docker-compose.yml +++ b/examples/nextjs/docker-compose.yml @@ -5,6 +5,6 @@ services: ports: - '8080:8080' env_file: - - ./crowdsec/.env + - ../express-server/crowdsec/.env volumes: - ./crowdsec/custom-config.yaml:/etc/crowdsec/config.yaml.local diff --git a/examples/nextjs/eslint.config.mjs b/examples/nextjs/eslint.config.mjs index c85fb67..6121785 100644 --- a/examples/nextjs/eslint.config.mjs +++ b/examples/nextjs/eslint.config.mjs @@ -1,16 +1,14 @@ -import { dirname } from "path"; -import { fileURLToPath } from "url"; -import { FlatCompat } from "@eslint/eslintrc"; +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; +import { FlatCompat } from '@eslint/eslintrc'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const compat = new FlatCompat({ - baseDirectory: __dirname, + baseDirectory: __dirname, }); -const eslintConfig = [ - ...compat.extends("next/core-web-vitals", "next/typescript"), -]; +const eslintConfig = [...compat.extends('next/core-web-vitals', 'next/typescript')]; export default eslintConfig; diff --git a/examples/nextjs/package.json b/examples/nextjs/package.json index d6e0077..a08e4f6 100644 --- a/examples/nextjs/package.json +++ b/examples/nextjs/package.json @@ -3,15 +3,18 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev", + "dev": "npm run pack-locally && npm install --no-save ./cs-nodejs-bouncer.tgz && next dev", "build": "next build", - "start": "next start", + "start": "npm run pack-locally && npm install --no-save ./cs-nodejs-bouncer.tgz && next build && next start", "lint": "next lint", "pack-locally": "(cd ../../ && npm run build && npm pack --silent) && mv ../../crowdsec-nodejs-bouncer-*.tgz ./cs-nodejs-bouncer.tgz" }, "dependencies": { "@crowdsec/nodejs-bouncer": "file:./cs-nodejs-bouncer.tgz", + "dotenv": "^17.2.0", + "dotenv-safe": "^9.1.0", "next": "^15.4.2", + "pino": "^9.4.0", "react": "19.1.0", "react-dom": "19.1.0" }, @@ -22,8 +25,6 @@ "@types/react": "^19", "@types/react-dom": "^19", "copy-webpack-plugin": "^13.0.0", - "dotenv": "^17.2.0", - "dotenv-safe": "^9.1.0", "eslint": "^9", "eslint-config-next": "^15.4.1", "typescript": "^5" diff --git a/examples/nextjs/src/app/api/crowdsec/helpers/index.ts b/examples/nextjs/src/app/api/crowdsec/helpers/index.ts index c20445c..341d6b0 100644 --- a/examples/nextjs/src/app/api/crowdsec/helpers/index.ts +++ b/examples/nextjs/src/app/api/crowdsec/helpers/index.ts @@ -1,5 +1,6 @@ import dotenv from 'dotenv'; import dotenvSafe from 'dotenv-safe'; +import pino from 'pino'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -21,3 +22,9 @@ export const loadEnv = () => { }); dotenv.config({ path: resolve(__dirname, '../../../../../crowdsec/.env') }); }; + +export const getLogger = () => { + return pino({ + level: process.env.TEST_LOG_LEVEL ?? 'debug', + }); +}; diff --git a/examples/nextjs/src/app/api/crowdsec/route.ts b/examples/nextjs/src/app/api/crowdsec/route.ts index c35b529..d4f11a8 100644 --- a/examples/nextjs/src/app/api/crowdsec/route.ts +++ b/examples/nextjs/src/app/api/crowdsec/route.ts @@ -3,7 +3,7 @@ import { CrowdSecBouncer, CrowdSecBouncerConfigurations } from '@crowdsec/nodejs-bouncer'; import { NextResponse } from 'next/server'; -import { loadEnv } from './helpers'; +import { loadEnv, getLogger } from './helpers'; // Load and validate environment variables loadEnv(); @@ -20,10 +20,13 @@ const config: CrowdSecBouncerConfigurations = { const bouncer = new CrowdSecBouncer(config); +// Set up the logger for this example +const logger = getLogger(); + export async function POST(req: Request) { const ip = process.env.BOUNCED_IP as string; // In a production scenario, the user's real IP should be retrieved. - console.log('CrowdSec API route called with IP:', ip); + logger.info(`CrowdSec API route called with IP: ${ip}`); try { const { remediation, origin } = await bouncer.getIpRemediation(ip); @@ -37,7 +40,8 @@ export async function POST(req: Request) { return new NextResponse(null, { status: 200 }); } catch (err) { - console.error('CrowdSec API route error:', err); - return new NextResponse(null, { status: 500 }); + logger.error(`CrowdSec API route error: ${err}`); + // If an error occurs, don't block the user + return new NextResponse(null, { status: 200 }); } } diff --git a/examples/nextjs/src/app/crowdsec-captcha/route.ts b/examples/nextjs/src/app/crowdsec-captcha/route.ts index 468e777..3160c53 100644 --- a/examples/nextjs/src/app/crowdsec-captcha/route.ts +++ b/examples/nextjs/src/app/crowdsec-captcha/route.ts @@ -1,6 +1,6 @@ import { NextResponse } from 'next/server'; import { CrowdSecBouncer, CrowdSecBouncerConfigurations } from '@crowdsec/nodejs-bouncer'; -import { loadEnv } from '../../app/api/crowdsec/helpers'; +import { loadEnv } from '@/app/api/crowdsec/helpers'; // Load and validate environment variables loadEnv(); diff --git a/examples/nextjs/src/app/globals.css b/examples/nextjs/src/app/globals.css index e3734be..79a3e36 100644 --- a/examples/nextjs/src/app/globals.css +++ b/examples/nextjs/src/app/globals.css @@ -1,42 +1,42 @@ :root { - --background: #ffffff; - --foreground: #171717; + --background: #ffffff; + --foreground: #171717; } @media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } + :root { + --background: #0a0a0a; + --foreground: #ededed; + } } html, body { - max-width: 100vw; - overflow-x: hidden; + max-width: 100vw; + overflow-x: hidden; } body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + color: var(--foreground); + background: var(--background); + font-family: Arial, Helvetica, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } * { - box-sizing: border-box; - padding: 0; - margin: 0; + box-sizing: border-box; + padding: 0; + margin: 0; } a { - color: inherit; - text-decoration: none; + color: inherit; + text-decoration: none; } @media (prefers-color-scheme: dark) { - html { - color-scheme: dark; - } + html { + color-scheme: dark; + } } diff --git a/examples/nextjs/src/app/page.module.css b/examples/nextjs/src/app/page.module.css index 58c71af..1d6b0f7 100644 --- a/examples/nextjs/src/app/page.module.css +++ b/examples/nextjs/src/app/page.module.css @@ -1,167 +1,167 @@ .page { - --gray-rgb: 0, 0, 0; - --gray-alpha-200: rgba(var(--gray-rgb), 0.08); - --gray-alpha-100: rgba(var(--gray-rgb), 0.05); + --gray-rgb: 0, 0, 0; + --gray-alpha-200: rgba(var(--gray-rgb), 0.08); + --gray-alpha-100: rgba(var(--gray-rgb), 0.05); - --button-primary-hover: #383838; - --button-secondary-hover: #f2f2f2; + --button-primary-hover: #383838; + --button-secondary-hover: #f2f2f2; - display: grid; - grid-template-rows: 20px 1fr 20px; - align-items: center; - justify-items: center; - min-height: 100svh; - padding: 80px; - gap: 64px; - font-family: var(--font-geist-sans); + display: grid; + grid-template-rows: 20px 1fr 20px; + align-items: center; + justify-items: center; + min-height: 100svh; + padding: 80px; + gap: 64px; + font-family: var(--font-geist-sans); } @media (prefers-color-scheme: dark) { - .page { - --gray-rgb: 255, 255, 255; - --gray-alpha-200: rgba(var(--gray-rgb), 0.145); - --gray-alpha-100: rgba(var(--gray-rgb), 0.06); + .page { + --gray-rgb: 255, 255, 255; + --gray-alpha-200: rgba(var(--gray-rgb), 0.145); + --gray-alpha-100: rgba(var(--gray-rgb), 0.06); - --button-primary-hover: #ccc; - --button-secondary-hover: #1a1a1a; - } + --button-primary-hover: #ccc; + --button-secondary-hover: #1a1a1a; + } } .main { - display: flex; - flex-direction: column; - gap: 32px; - grid-row-start: 2; + display: flex; + flex-direction: column; + gap: 32px; + grid-row-start: 2; } .main ol { - font-family: var(--font-geist-mono); - padding-left: 0; - margin: 0; - font-size: 14px; - line-height: 24px; - letter-spacing: -0.01em; - list-style-position: inside; + font-family: var(--font-geist-mono); + padding-left: 0; + margin: 0; + font-size: 14px; + line-height: 24px; + letter-spacing: -0.01em; + list-style-position: inside; } .main li:not(:last-of-type) { - margin-bottom: 8px; + margin-bottom: 8px; } .main code { - font-family: inherit; - background: var(--gray-alpha-100); - padding: 2px 4px; - border-radius: 4px; - font-weight: 600; + font-family: inherit; + background: var(--gray-alpha-100); + padding: 2px 4px; + border-radius: 4px; + font-weight: 600; } .ctas { - display: flex; - gap: 16px; + display: flex; + gap: 16px; } .ctas a { - appearance: none; - border-radius: 128px; - height: 48px; - padding: 0 20px; - border: 1px solid transparent; - transition: - background 0.2s, - color 0.2s, - border-color 0.2s; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - font-size: 16px; - line-height: 20px; - font-weight: 500; + appearance: none; + border-radius: 128px; + height: 48px; + padding: 0 20px; + border: 1px solid transparent; + transition: + background 0.2s, + color 0.2s, + border-color 0.2s; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 16px; + line-height: 20px; + font-weight: 500; } a.primary { - background: var(--foreground); - color: var(--background); - gap: 8px; + background: var(--foreground); + color: var(--background); + gap: 8px; } a.secondary { - border-color: var(--gray-alpha-200); - min-width: 158px; + border-color: var(--gray-alpha-200); + min-width: 158px; } .footer { - grid-row-start: 3; - display: flex; - gap: 24px; + grid-row-start: 3; + display: flex; + gap: 24px; } .footer a { - display: flex; - align-items: center; - gap: 8px; + display: flex; + align-items: center; + gap: 8px; } .footer img { - flex-shrink: 0; + flex-shrink: 0; } /* Enable hover only on non-touch devices */ @media (hover: hover) and (pointer: fine) { - a.primary:hover { - background: var(--button-primary-hover); - border-color: transparent; - } + a.primary:hover { + background: var(--button-primary-hover); + border-color: transparent; + } - a.secondary:hover { - background: var(--button-secondary-hover); - border-color: transparent; - } + a.secondary:hover { + background: var(--button-secondary-hover); + border-color: transparent; + } - .footer a:hover { - text-decoration: underline; - text-underline-offset: 4px; - } + .footer a:hover { + text-decoration: underline; + text-underline-offset: 4px; + } } @media (max-width: 600px) { - .page { - padding: 32px; - padding-bottom: 80px; - } + .page { + padding: 32px; + padding-bottom: 80px; + } - .main { - align-items: center; - } + .main { + align-items: center; + } - .main ol { - text-align: center; - } + .main ol { + text-align: center; + } - .ctas { - flex-direction: column; - } + .ctas { + flex-direction: column; + } - .ctas a { - font-size: 14px; - height: 40px; - padding: 0 16px; - } + .ctas a { + font-size: 14px; + height: 40px; + padding: 0 16px; + } - a.secondary { - min-width: auto; - } + a.secondary { + min-width: auto; + } - .footer { - flex-wrap: wrap; - align-items: center; - justify-content: center; - } + .footer { + flex-wrap: wrap; + align-items: center; + justify-content: center; + } } @media (prefers-color-scheme: dark) { - .logo { - filter: invert(); - } + .logo { + filter: invert(); + } } diff --git a/package.json b/package.json index e21e249..0a9767e 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,6 @@ "keyv": "^5.3.4", "lodash": "^4.17.21", "pino": "^9.4.0", - "pino-pretty": "^11.2.2", "svg-captcha-fixed": "^1.5.2" }, "devDependencies": { diff --git a/src/helpers/__tests__/decision.test.ts b/src/helpers/__tests__/decision.test.ts index 24cf55b..679c8c0 100644 --- a/src/helpers/__tests__/decision.test.ts +++ b/src/helpers/__tests__/decision.test.ts @@ -1,8 +1,8 @@ import { afterAll, afterEach, describe, expect, it, jest } from '@jest/globals'; -import { convertRawDecisionsToDecisions } from 'src/helpers/decision'; -import * as decisionModule from 'src/helpers/decision'; -import logger from 'src/lib/logger'; +import logger from '../../lib/logger'; +import * as decisionModule from '../decision'; +import { convertRawDecisionsToDecisions } from '../decision'; const configs = { url: 'http://example.com/api', diff --git a/src/helpers/__tests__/ip.test.ts b/src/helpers/__tests__/ip.test.ts index 7397c84..1b151c2 100644 --- a/src/helpers/__tests__/ip.test.ts +++ b/src/helpers/__tests__/ip.test.ts @@ -1,15 +1,8 @@ import { jest, describe, expect, it, afterEach, afterAll } from '@jest/globals'; import { Address4 } from 'ip-address'; -import { - getIpToRemediate, - getFirstIpFromRange, - getIpOrRangeType, - getIpV4BucketRange, - isIpV4InRange, - getIpV4BucketIndexForIp, -} from 'src/helpers/ip'; -import { IP_TYPE_V4, IP_TYPE_V6 } from 'src/lib/constants'; +import { IP_TYPE_V4, IP_TYPE_V6 } from '../../lib/constants'; +import { getIpToRemediate, getFirstIpFromRange, getIpOrRangeType, getIpV4BucketRange, isIpV4InRange, getIpV4BucketIndexForIp } from '../ip'; afterEach(() => { jest.restoreAllMocks(); diff --git a/src/lib/__tests__/bouncer.test.ts b/src/lib/__tests__/bouncer.test.ts index d405cd3..3127c70 100644 --- a/src/lib/__tests__/bouncer.test.ts +++ b/src/lib/__tests__/bouncer.test.ts @@ -1,18 +1,18 @@ import { afterEach, beforeEach, beforeAll, describe, expect, it, jest, afterAll } from '@jest/globals'; import nock, { cleanAll as nockCleanAll } from 'nock'; +import CrowdSecBouncer from '../bouncer'; +import { CrowdSecBouncerConfigurations } from '../bouncer/types'; +import CacheStorage from '../cache'; +import { ORIGINS_COUNT_KEY } from '../cache/constants'; +import { getCacheKey } from '../cache/helpers'; +import InMemory from '../cache/in-memory'; +import { CachableDecisionContent, CachableDecisionItem } from '../cache/types'; +import { BOUNCER_KEYS, REFRESH_KEYS, REMEDIATION_BAN, REMEDIATION_BYPASS, REMEDIATION_CAPTCHA, SCOPE_IP, VERSION } from '../constants'; +import logger from '../logger'; +import * as rendered from '../rendered'; +import { Remediation } from '../types'; import os from 'os'; -import CrowdSecBouncer from 'src/lib/bouncer'; -import { CrowdSecBouncerConfigurations } from 'src/lib/bouncer/types'; -import CacheStorage from 'src/lib/cache'; -import { ORIGINS_COUNT_KEY } from 'src/lib/cache/constants'; -import { getCacheKey } from 'src/lib/cache/helpers'; -import InMemory from 'src/lib/cache/in-memory'; -import { CachableDecisionContent, CachableDecisionItem } from 'src/lib/cache/types'; -import { BOUNCER_KEYS, REFRESH_KEYS, REMEDIATION_BAN, REMEDIATION_BYPASS, REMEDIATION_CAPTCHA, SCOPE_IP, VERSION } from 'src/lib/constants'; -import logger from 'src/lib/logger'; -import * as rendered from 'src/lib/rendered'; -import { Remediation } from 'src/lib/types'; const configs: CrowdSecBouncerConfigurations = { url: 'http://example.com/api', diff --git a/src/lib/__tests__/cache.test.ts b/src/lib/__tests__/cache.test.ts index 5025549..dca0d5b 100644 --- a/src/lib/__tests__/cache.test.ts +++ b/src/lib/__tests__/cache.test.ts @@ -1,13 +1,13 @@ import { describe, expect, it, jest, afterAll, beforeAll, afterEach, beforeEach } from '@jest/globals'; import KeyvStore from 'keyv'; -import * as ipModule from 'src/helpers/ip'; -import CacheStorage from 'src/lib/cache'; -import InMemory from 'src/lib/cache/in-memory'; -import KeyvAdapter from 'src/lib/cache/keyv-adapter'; -import { SCOPE_IP, SCOPE_RANGE } from 'src/lib/constants'; -import logger from 'src/lib/logger'; -import { CachableDecision } from 'src/lib/types'; +import * as ipModule from '../../helpers/ip'; +import CacheStorage from '../cache'; +import InMemory from '../cache/in-memory'; +import KeyvAdapter from '../cache/keyv-adapter'; +import { SCOPE_IP, SCOPE_RANGE } from '../constants'; +import logger from '../logger'; +import { CachableDecision } from '../types'; let keyvAdapter: KeyvAdapter; diff --git a/src/lib/__tests__/helpers-duration.test.ts b/src/lib/__tests__/helpers-duration.test.ts index 900988d..ad6bdf1 100644 --- a/src/lib/__tests__/helpers-duration.test.ts +++ b/src/lib/__tests__/helpers-duration.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it, jest, afterAll, beforeAll, afterEach } from '@jest/globals'; -import { convertDurationToMilliseconds } from 'src/helpers/duration'; +import { convertDurationToMilliseconds } from '../../helpers/duration'; beforeAll(() => { jest.useFakeTimers().setSystemTime(new Date('2020-01-01')); diff --git a/src/lib/__tests__/lapi-client.test.ts b/src/lib/__tests__/lapi-client.test.ts index 8d70f60..808fc83 100644 --- a/src/lib/__tests__/lapi-client.test.ts +++ b/src/lib/__tests__/lapi-client.test.ts @@ -1,10 +1,10 @@ import { afterAll, afterEach, describe, expect, it, jest } from '@jest/globals'; import nock, { cleanAll as nockCleanAll } from 'nock'; -import LapiClient from 'src/lib/lapi-client'; -import { LapiClientConfigurations } from 'src/lib/lapi-client/types'; -import logger from 'src/lib/logger'; -import { Decision } from 'src/lib/types'; +import LapiClient from '../lapi-client'; +import { LapiClientConfigurations } from '../lapi-client/types'; +import logger from '../logger'; +import { Decision } from '../types'; const configs: LapiClientConfigurations & { userAgent: string; diff --git a/src/lib/__tests__/logger.test.ts b/src/lib/__tests__/logger.test.ts index 8536d57..26c83ae 100644 --- a/src/lib/__tests__/logger.test.ts +++ b/src/lib/__tests__/logger.test.ts @@ -1,6 +1,6 @@ import { afterAll, afterEach, describe, expect, it } from '@jest/globals'; -import logger from 'src/lib/logger'; +import logger from '../logger'; describe('Logger', () => { afterAll(async () => { diff --git a/src/lib/__tests__/metrics.test.ts b/src/lib/__tests__/metrics.test.ts index 1eaaacc..9c1aa58 100644 --- a/src/lib/__tests__/metrics.test.ts +++ b/src/lib/__tests__/metrics.test.ts @@ -1,8 +1,8 @@ import { beforeEach, describe, expect, it, jest } from '@jest/globals'; +import { METRICS_TYPE } from '../constants'; +import { MetricsBuilder } from '../lapi-client/metrics'; import os from 'os'; -import { METRICS_TYPE } from 'src/lib/constants'; -import { MetricsBuilder } from 'src/lib/lapi-client/metrics'; jest.mock('os', () => ({ type: jest.fn(() => 'Linux'), diff --git a/src/lib/__tests__/rendered.test.ts b/src/lib/__tests__/rendered.test.ts index 3dab8d1..c6beeca 100644 --- a/src/lib/__tests__/rendered.test.ts +++ b/src/lib/__tests__/rendered.test.ts @@ -1,8 +1,8 @@ import { describe, expect, it } from '@jest/globals'; -import { generateTemplate, renderBanWall, renderCaptchaWall } from 'src/lib/rendered'; -import { DEFAULT_COLORS, DEFAULT_TEXTS } from 'src/lib/rendered/constants'; -import { BaseWallOptions } from 'src/lib/rendered/types'; +import { generateTemplate, renderBanWall, renderCaptchaWall } from '../rendered'; +import { DEFAULT_COLORS, DEFAULT_TEXTS } from '../rendered/constants'; +import { BaseWallOptions } from '../rendered/types'; describe('📄 Generate Template', () => { it('should generate a base template', async () => { diff --git a/src/lib/bouncer/index.ts b/src/lib/bouncer/index.ts index 14a0ff4..3c3a7f2 100644 --- a/src/lib/bouncer/index.ts +++ b/src/lib/bouncer/index.ts @@ -51,7 +51,7 @@ type GetResponseParams = { origin: CachableOrigin; }; -type IpRemediationResult = Record & Record; +export type IpRemediationResult = Record & Record; class CrowdSecBouncer { public readonly cacheStorage: CacheStorage; diff --git a/src/lib/logger.ts b/src/lib/logger.ts index 6448054..a9008ff 100644 --- a/src/lib/logger.ts +++ b/src/lib/logger.ts @@ -1,31 +1,7 @@ import { pino, Logger } from 'pino'; -const LOG_LEVEL = process.env.LOG_LEVEL ?? 'debug'; +const LOG_LEVEL = process?.env?.LOG_LEVEL ?? 'debug'; -// Detect clean Node.js runtime (bundler or Edge runtime will fall back without transport) -const isNode = typeof process !== 'undefined' && Boolean(process.versions?.node); - -let logger: Logger; - -if (isNode) { - try { - logger = pino({ - level: LOG_LEVEL, - transport: { - target: 'pino-pretty', - options: { - // Disable colors if CS_NO_COLOR is set - colorize: !process.env.CS_NO_COLOR, - }, - }, - }); - } catch { - // If transport resolution fails (e.g. webpack), fallback to default pino - logger = pino({ level: LOG_LEVEL }); - } -} else { - // Non-Node environments: plain JSON output - logger = pino({ level: LOG_LEVEL }); -} +const logger: Logger = pino({ level: LOG_LEVEL }); export default logger; diff --git a/src/lib/rendered/templates/captcha.ejs b/src/lib/rendered/templates/captcha.ejs index 5797ea1..1bc68f9 100644 --- a/src/lib/rendered/templates/captcha.ejs +++ b/src/lib/rendered/templates/captcha.ejs @@ -16,7 +16,7 @@ <% if (texts.error) { %>

<%- texts.error %>

<% } %> -> +> From a29c31f66c300a35a8a9d25cea39da6f8e5098bd Mon Sep 17 00:00:00 2001 From: Julien Loizelet Date: Fri, 25 Jul 2025 13:56:45 +0900 Subject: [PATCH 05/11] feat(build): Install tsup before build --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0a9767e..0b77384 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ ], "scripts": { "clean": "rm -rf dist", - "build": "npm run clean && tsup --config tsup.config.ts", + "build": "npm run clean && npm install && tsup --config tsup.config.ts", "build:types": "tsc --emitDeclarationOnly --declaration --declarationMap false --outDir dist", "prepack": "npm run build", "lint": "eslint .", From cf88b9eacfe585c920581c4621a4f0278c6273b8 Mon Sep 17 00:00:00 2001 From: Julien Loizelet Date: Fri, 25 Jul 2025 14:20:01 +0900 Subject: [PATCH 06/11] test(e2e): Handle new log format without pino-pretty --- .../tests/custom-configs-1.spec.ts | 4 ++-- examples/express-server/tests/helpers/log.ts | 21 +++++++++++++++++++ .../express-server/tests/live-mode.spec.ts | 16 +++++++------- .../express-server/tests/stream-mode.spec.ts | 6 +++--- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/examples/express-server/tests/custom-configs-1.spec.ts b/examples/express-server/tests/custom-configs-1.spec.ts index 49fa0e6..0aa0187 100644 --- a/examples/express-server/tests/custom-configs-1.spec.ts +++ b/examples/express-server/tests/custom-configs-1.spec.ts @@ -3,7 +3,7 @@ import { test, expect } from '@playwright/test'; import { E2E_ENDPOINT, LOG_PATH } from './constants'; import { getBouncedIp } from './helpers/base'; import { addIpDecision } from './helpers/cscli'; -import { getFileContent } from './helpers/log'; +import { getLogMessages } from './helpers/log'; import { wait } from './helpers/time'; import { removeCscliDecisions, setupCommon } from './setup/common'; @@ -21,7 +21,7 @@ test('Should fallback to configured fallback in case of unknown ', async ({ page // Remediation should be a ban because fallback is configured to ban await expect(page).toHaveTitle('Custom Ban'); // Custom ban title as defined in the config await wait(1000, 'Wait for logs to be written'); - const logContent = await getFileContent(LOG_PATH); + const logContent = await getLogMessages(LOG_PATH); expect(logContent).toContain(`Cache found for IP ${bouncedIp}: []`); // No cache for this IP as we just cleared it expect(logContent).toMatch( new RegExp(`Stored decisions: \\[{"id":"cscli-mfa-ip-${bouncedIp}","origin":"cscli","expiresAt":\\d+,"value":"mfa"}\\]`), diff --git a/examples/express-server/tests/helpers/log.ts b/examples/express-server/tests/helpers/log.ts index f913c7e..1e9379e 100644 --- a/examples/express-server/tests/helpers/log.ts +++ b/examples/express-server/tests/helpers/log.ts @@ -17,3 +17,24 @@ export const deleteFileContent = async (filePath: string) => { return false; } }; + +export const parseJsonLogs = (logContent: string): string[] => { + return logContent + .split('\n') + .filter(line => line.trim()) + .map(line => { + try { + const parsed = JSON.parse(line); + return parsed.msg || ''; + } catch { + // Handle pino-pretty format: [timestamp] LEVEL (pid): message + const match = line.match(/^\[[\d:.]+\]\s+\w+\s+\(\d+\):\s+(.*)$/); + return match ? match[1] : line; + } + }); +}; + +export const getLogMessages = async (filePath: string): Promise => { + const content = await getFileContent(filePath); + return parseJsonLogs(content).join('\n'); +}; diff --git a/examples/express-server/tests/live-mode.spec.ts b/examples/express-server/tests/live-mode.spec.ts index 5b68f39..f12d848 100644 --- a/examples/express-server/tests/live-mode.spec.ts +++ b/examples/express-server/tests/live-mode.spec.ts @@ -3,7 +3,7 @@ import { test, expect } from '@playwright/test'; import { HOME_TITLE, BAN_TITLE, CAPTCHA_TITLE, E2E_ENDPOINT, LOG_PATH } from './constants'; import { getBouncedIp, getCaptchaPhrase } from './helpers/base'; import { addIpDecision, removeIpDecision } from './helpers/cscli'; -import { getFileContent, deleteFileContent } from './helpers/log'; +import { deleteFileContent, getLogMessages } from './helpers/log'; import { wait } from './helpers/time'; import { setupCommon, removeCscliDecisions } from './setup/common'; @@ -18,7 +18,7 @@ test('Should access Home Page', async ({ page }) => { await expect(page).toHaveTitle(HOME_TITLE); // Verify expected log messages await wait(1000, 'Wait for logs to be written'); - const logContent = await getFileContent(LOG_PATH); + const logContent = await getLogMessages(LOG_PATH); expect(logContent).toContain(`Cache found for IP ${bouncedIp}: []`); // No cache for this IP as we just cleared it expect(logContent).toMatch( new RegExp(`Stored decisions: \\[{"id":"clean-bypass-ip-${bouncedIp}","origin":"clean","expiresAt":\\d+,"value":"bypass"}\\]`), @@ -36,13 +36,13 @@ test('Should be banned', async ({ page }) => { await expect(page).toHaveTitle(BAN_TITLE); // Verify expected log messages await wait(1000, 'Wait for logs to be written'); - const logContent = await getFileContent(LOG_PATH); + const logContent = await getLogMessages(LOG_PATH); expect(logContent).toContain(`Cache found for IP ${bouncedIp}: []`); // No cache for this IP as cache is 1 second for clean IP (see configs/live-mode.json) expect(logContent).toMatch( new RegExp(`Stored decisions: \\[{"id":"cscli-ban-ip-${bouncedIp}","origin":"cscli","expiresAt":\\d+,"value":"ban"}\\]`), ); expect(logContent).toContain( - 'Updated origins count: [{"origin":"clean","remediation":{"bypass":1}},{"origin":"cscli","remediation":{"ban":1}}]\n', + 'Updated origins count: [{"origin":"clean","remediation":{"bypass":1}},{"origin":"cscli","remediation":{"ban":1}}]', ); }); @@ -57,7 +57,7 @@ test('Should be banned the time of cached decision', async ({ page }) => { await expect(page).toHaveTitle(BAN_TITLE); // Verify expected log messages await wait(1000, 'Wait for logs to be written'); - const logContent = await getFileContent(LOG_PATH); + const logContent = await getLogMessages(LOG_PATH); expect(logContent).toMatch( new RegExp( `Cache found for IP ${bouncedIp}: \\[{"id":"cscli-ban-ip-${bouncedIp}","origin":"cscli","expiresAt":\\d+,"value":"ban"}\\]`, @@ -86,7 +86,7 @@ test('Should retrieve the highest remediation', async ({ page }) => { // Remediation should be a ban because ban > captcha await expect(page).toHaveTitle(BAN_TITLE); await wait(1000, 'Wait for logs to be written'); - const logContent = await getFileContent(LOG_PATH); + const logContent = await getLogMessages(LOG_PATH); expect(logContent).toMatch( new RegExp( `Stored decisions: \\[{"id":"cscli-ban-ip-${bouncedIp}","origin":"cscli","expiresAt":\\d+,"value":"ban"},{"id":"cscli-captcha-ip-${bouncedIp}","origin":"cscli","expiresAt":\\d+,"value":"captcha"}\\]`, @@ -147,7 +147,7 @@ test('Should push usage metrics', async ({ page }) => { await expect(locator).toHaveText('Usage metrics pushed'); // Verify expected log messages await wait(1000, 'Wait for logs to be written'); - const logContent = await getFileContent(LOG_PATH); + const logContent = await getLogMessages(LOG_PATH); // Should push well formatted metrics expect(logContent).toMatch( new RegExp( @@ -175,7 +175,7 @@ test('Should fallback to default fallback in case of unknown ', async ({ page }) // Remediation should be a captcha (default) await expect(page).toHaveTitle(CAPTCHA_TITLE); await wait(1000, 'Wait for logs to be written'); - const logContent = await getFileContent(LOG_PATH); + const logContent = await getLogMessages(LOG_PATH); expect(logContent).toMatch( new RegExp(`Stored decisions: \\[{"id":"cscli-mfa-ip-${bouncedIp}","origin":"cscli","expiresAt":\\d+,"value":"mfa"}\\]`), ); diff --git a/examples/express-server/tests/stream-mode.spec.ts b/examples/express-server/tests/stream-mode.spec.ts index 3250f38..1f7232e 100644 --- a/examples/express-server/tests/stream-mode.spec.ts +++ b/examples/express-server/tests/stream-mode.spec.ts @@ -3,7 +3,7 @@ import { test, expect } from '@playwright/test'; import { BAN_TITLE, E2E_ENDPOINT, HOME_TITLE, LOG_PATH } from './constants'; import { getBouncedIp } from './helpers/base'; import { addIpDecision } from './helpers/cscli'; -import { getFileContent } from './helpers/log'; +import { getLogMessages } from './helpers/log'; import { wait } from './helpers/time'; import { setupCommon } from './setup/common'; @@ -19,7 +19,7 @@ test('Should access Home Page', async ({ page }) => { await expect(page).toHaveTitle(HOME_TITLE); // Verify expected log messages await wait(1000, 'Wait for logs to be written'); - const logContent = await getFileContent(LOG_PATH); + const logContent = await getLogMessages(LOG_PATH); expect(logContent).toContain(`Cache found for IP ${bouncedIp}: []`); // No cache for this IP as we just cleared it expect(logContent).not.toMatch( new RegExp(`Stored decisions: \\[{"id":"clean-bypass-ip-${bouncedIp}","origin":"clean","expiresAt":\\d+,"value":"bypass"}\\]`), @@ -37,7 +37,7 @@ test('Should not be banned before refresh', async ({ page }) => { await expect(page).toHaveTitle(HOME_TITLE); // Verify expected log messages await wait(1000, 'Wait for logs to be written'); - const logContent = await getFileContent(LOG_PATH); + const logContent = await getLogMessages(LOG_PATH); expect(logContent).toContain('Updated origins count: [{"origin":"clean","remediation":{"bypass":2}}]'); }); From a47f13f63cef111cb22c5e374ed0270b9d9a8599 Mon Sep 17 00:00:00 2001 From: Julien Loizelet Date: Fri, 25 Jul 2025 14:27:54 +0900 Subject: [PATCH 07/11] style(*): Pass through code format tools --- examples/express-server/tests/constants.ts | 2 +- examples/express-server/tests/helpers/log.ts | 4 ++-- src/lib/bouncer/index.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/express-server/tests/constants.ts b/examples/express-server/tests/constants.ts index 761790b..2845a8b 100644 --- a/examples/express-server/tests/constants.ts +++ b/examples/express-server/tests/constants.ts @@ -1,4 +1,4 @@ -import { dirname, join } from 'node:path'; +import { dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; const __filename = fileURLToPath(import.meta.url); diff --git a/examples/express-server/tests/helpers/log.ts b/examples/express-server/tests/helpers/log.ts index 1e9379e..74c1074 100644 --- a/examples/express-server/tests/helpers/log.ts +++ b/examples/express-server/tests/helpers/log.ts @@ -21,8 +21,8 @@ export const deleteFileContent = async (filePath: string) => { export const parseJsonLogs = (logContent: string): string[] => { return logContent .split('\n') - .filter(line => line.trim()) - .map(line => { + .filter((line) => line.trim()) + .map((line) => { try { const parsed = JSON.parse(line); return parsed.msg || ''; diff --git a/src/lib/bouncer/index.ts b/src/lib/bouncer/index.ts index 3c3a7f2..c751863 100644 --- a/src/lib/bouncer/index.ts +++ b/src/lib/bouncer/index.ts @@ -244,7 +244,7 @@ class CrowdSecBouncer { // Decrement the count of each origin/remediation for (const [origin, remediationCount] of Object.entries(origins)) { - for (const [remediation, delta] of Object.entries(remediationCount as Record)) { + for (const [remediation, delta] of Object.entries(remediationCount)) { await this.cacheStorage.upsertMetricsOriginsCount({ origin, remediation, delta }); } } @@ -307,7 +307,7 @@ class CrowdSecBouncer { const originsToUpdate: Record> = {}; for (const { origin, remediation } of originsCount) { - for (const [remediationType, count] of Object.entries(remediation) as [Remediation, number][]) { + for (const [remediationType, count] of Object.entries(remediation)) { if (count <= 0) { continue; } From a2b541f6427bb21c9705e1c8da43f4f2cd193bd9 Mon Sep 17 00:00:00 2001 From: Julien Loizelet Date: Fri, 25 Jul 2025 14:49:20 +0900 Subject: [PATCH 08/11] docs(*): Update doc for Nextjs --- docs/DEVELOPER.md | 2 +- docs/USER_GUIDE.md | 25 +++--- examples/express-server/README.md | 10 +-- examples/nextjs/README.md | 110 ++++++++++++++++---------- examples/nextjs/docs/ban-wall.png | Bin 0 -> 21030 bytes examples/nextjs/docs/bypass.png | Bin 0 -> 15957 bytes examples/nextjs/docs/captcha-wall.png | Bin 0 -> 27202 bytes package-lock.json | 92 ++------------------- package.json | 1 - 9 files changed, 95 insertions(+), 145 deletions(-) create mode 100644 examples/nextjs/docs/ban-wall.png create mode 100644 examples/nextjs/docs/bypass.png create mode 100644 examples/nextjs/docs/captcha-wall.png diff --git a/docs/DEVELOPER.md b/docs/DEVELOPER.md index 022bc41..2810c00 100644 --- a/docs/DEVELOPER.md +++ b/docs/DEVELOPER.md @@ -90,7 +90,7 @@ npm install -g doctoc Then, run it in the relevant folders: ```bash -doctoc docs/* --maxlevel 4 && doctoc examples/express-server/README.md --maxlevel 4 +doctoc docs/* --maxlevel 4 && doctoc examples/express-server/README.md --maxlevel 4 && doctoc examples/nextjs/README.md --maxlevel 4 ``` ## Release process diff --git a/docs/USER_GUIDE.md b/docs/USER_GUIDE.md index 762074f..6c39da4 100644 --- a/docs/USER_GUIDE.md +++ b/docs/USER_GUIDE.md @@ -13,20 +13,20 @@ - [Features](#features) - [Usage](#usage) - [Configurations](#configurations) - - [Bouncer behavior](#bouncer-behavior) - - [Local API Connection](#local-api-connection) - - [Cache](#cache) - - [Captcha and Ban walls settings](#captcha-and-ban-walls-settings) + - [Bouncer behavior](#bouncer-behavior) + - [Local API Connection](#local-api-connection) + - [Cache](#cache) + - [Captcha and Ban walls settings](#captcha-and-ban-walls-settings) - [Implement your own bouncer](#implement-your-own-bouncer) - - [Instantiation](#instantiation) - - [Apply a remediation](#apply-a-remediation) - - [Refresh decision cache](#refresh-decision-cache) - - [Push usage metrics](#push-usage-metrics) - - [Custom Captcha](#custom-captcha) - - [Custom Cache Adapter](#custom-cache-adapter) + - [Instantiation](#instantiation) + - [Apply a remediation](#apply-a-remediation) + - [Refresh decision cache](#refresh-decision-cache) + - [Push usage metrics](#push-usage-metrics) + - [Custom Captcha](#custom-captcha) + - [Custom Cache Adapter](#custom-cache-adapter) - [Examples](#examples) - - [Basics](#basics) - - [Express server](#express-server) + - [Basics](#basics) + - [Express server](#express-server) @@ -161,6 +161,7 @@ Below is the list of available settings (see also `CrowdSecBouncerConfigurations }, "captcha": { "captchaImageTag": "Generated with svg-captcha-fixed", + "captchaAction": "Optional action of the captcha form (e.g. '/crowdsec-captcha'). Empty by default.", "texts": { "tabTitle": "CrowdSec | Captcha Wall", "title": "Access Denied", diff --git a/examples/express-server/README.md b/examples/express-server/README.md index 55e9d5c..eb9d61f 100644 --- a/examples/express-server/README.md +++ b/examples/express-server/README.md @@ -12,11 +12,11 @@ It aims to help developers to understand how to integrate CrowdSec remediation i - [Technical overview](#technical-overview) - [Test the bouncer](#test-the-bouncer) - - [Pre-requisites](#pre-requisites) - - [Prepare the tests](#prepare-the-tests) - - [Test a "bypass" remediation](#test-a-bypass-remediation) - - [Test a "ban" remediation](#test-a-ban-remediation) - - [Test a "captcha" remediation](#test-a-captcha-remediation) + - [Pre-requisites](#pre-requisites) + - [Prepare the tests](#prepare-the-tests) + - [Test a "bypass" remediation](#test-a-bypass-remediation) + - [Test a "ban" remediation](#test-a-ban-remediation) + - [Test a "captcha" remediation](#test-a-captcha-remediation) diff --git a/examples/nextjs/README.md b/examples/nextjs/README.md index b46f474..2bd0818 100644 --- a/examples/nextjs/README.md +++ b/examples/nextjs/README.md @@ -1,9 +1,9 @@ -# Express server basic implementation +# NextJS basic implementation -The `express-server` folder contains a basic implementation of the CrowdSec NodeJs -remediation component. +The `nextjs` folder contains a basic implementation of the CrowdSec NodeJs +remediation component for Next.js applications. -It aims to help developers to understand how to integrate CrowdSec remediation in their NodeJs application. +It aims to help developers to understand how to integrate CrowdSec remediation in their Next.js application. **Table of Contents** @@ -11,51 +11,83 @@ It aims to help developers to understand how to integrate CrowdSec remediation i - [Technical overview](#technical-overview) + - [Middleware (`src/middleware.ts`)](#middleware-srcmiddlewarets) + - [API Route (`src/app/api/crowdsec/route.ts`)](#api-route-srcappapicrowdsecroutets) + - [Captcha Handler (`src/app/crowdsec-captcha/route.ts`)](#captcha-handler-srcappcrowdsec-captcharoutets) - [Test the bouncer](#test-the-bouncer) - - [Pre-requisites](#pre-requisites) - - [Prepare the tests](#prepare-the-tests) - - [Test a "bypass" remediation](#test-a-bypass-remediation) - - [Test a "ban" remediation](#test-a-ban-remediation) - - [Test a "captcha" remediation](#test-a-captcha-remediation) + - [Pre-requisites](#pre-requisites) + - [Prepare the tests](#prepare-the-tests) + - [Test a "bypass" remediation](#test-a-bypass-remediation) + - [Test a "ban" remediation](#test-a-ban-remediation) + - [Test a "captcha" remediation](#test-a-captcha-remediation) ## Technical overview -All the logic is done in the `src/middleware.ts` and `src/app/api/crowdsec` files: +The implementation uses Next.js App Router with middleware and API routes: -- we use a middleware to act before rendering the page +### Middleware (`src/middleware.ts`) -- We retrieve the remediation for the current tested IP: +The middleware intercepts all requests and calls the CrowdSec API: ```js -const remediationData = await bouncer.getIpRemediation(ip); -const { origin, remediation } = remediationData; +export async function middleware(req: NextRequest) { + // Skip CrowdSec check for captcha route and non-HTML requests + if (pathname === '/crowdsec-captcha' || !acceptHeader.includes('text/html')) { + return NextResponse.next(); + } + + // Call internal API to check IP remediation + const checkUrl = `${req.nextUrl.origin}/api/crowdsec`; + const res = await fetch(checkUrl, { method: 'POST' }); + + if (res.status !== 200) { + // Return ban/captcha wall HTML + const html = await res.text(); + return new NextResponse(html, { + status: res.status, + headers: { 'Content-Type': 'text/html; charset=utf-8' }, + }); + } + + return NextResponse.next(); +} ``` -- Depending on the value of the remediation, we apply it: +### API Route (`src/app/api/crowdsec/route.ts`) - - let the process continue if there is no remediation (bypass) +The API route handles the CrowdSec logic: - - block the user with a ban wall remediation: +```js +export async function POST(req: Request) { + const { remediation, origin } = await bouncer.getIpRemediation(ip); + const bouncerResponse = await bouncer.getResponse({ ip, origin, remediation }); - ```js - - // Display Ban wall - if (remediation === 'ban') { - const bouncerResponse = await bouncer.getResponse({ - ip, - origin, - remediation, - }); + if (remediation === 'ban' || remediation === 'captcha') { return new NextResponse(bouncerResponse.html, { - status: bouncerResponse.status, - headers: { - 'Content-Type': 'text/html; charset=utf-8', - }, - }); - } - ``` + status: bouncerResponse.status, + }); + } + + return new NextResponse(null, { status: 200 }); +} +``` + +### Captcha Handler (`src/app/crowdsec-captcha/route.ts`) + +Handles captcha form submissions: + +```js +export async function POST(req: Request) { + const form = await req.formData(); + const phrase = form.get('phrase')?.toString() || ''; + const refresh = form.get('crowdsec_captcha_refresh')?.toString() || '0'; + + await bouncer.handleCaptchaSubmission({ ip, userPhrase: phrase, refresh, origin }); + return NextResponse.redirect(new URL('/', req.url)); +} +``` ## Test the bouncer @@ -71,7 +103,7 @@ const { origin, remediation } = remediationData; - Install all dependencies using a local archive. - Run the following commands from the `express-server` folder: + Run the following commands from the `nextjs` folder: ```shell npm run pack-locally && npm install @@ -97,7 +129,7 @@ docker exec -ti nodejs-cs-nextjs-crowdsec sh -c 'cscli bouncers add NodeBouncer We are using here the `BOUNCER_KEY` variable defined in `crowdsec/.env` file. -3. Launch the Express Server +3. Launch the Next.js Server ```shell npm run start @@ -109,15 +141,13 @@ For development, you can use: npm run dev ``` -This will launch an Express server accessible on `http://localhost:3000` (aka "the home page") with -`tests/express-server/server.ts` file as entry point. +This will launch a Next.js server accessible on `http://localhost:3000` (aka "the home page"). You should see different log messages in your terminal when you access the home page. ### Test a "bypass" remediation -As you don't have yet any decisions, you can access the `http://localhost:3000` page and just see the normal content " -Welcome to the Test Page". +As you don't have yet any decisions, you can access the `http://localhost:3000` page and just see the normal Next.js content. ![](./docs/bypass.png) @@ -163,4 +193,4 @@ Denied" captcha wall. You should see `Final remediation for IP is captcha` in terminal. -For this basic implementation, we just redirect user to `/` after resolution. +When a user solves the captcha successfully, they are redirected to the home page (`/`). diff --git a/examples/nextjs/docs/ban-wall.png b/examples/nextjs/docs/ban-wall.png new file mode 100644 index 0000000000000000000000000000000000000000..4911dea7bdaa0fdc6c1a4209b41936ea50922cb1 GIT binary patch literal 21030 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

Dv=My^gc3qV5KKT~5`w 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" } }, - "node_modules/cache-manager": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-6.1.3.tgz", - "integrity": "sha512-IcBseSv1GquLxlTb1nH5KhOQQwwOjMC5hkBras+8zTYD/bRSCgT9bIah1DZ+4eKc3vcqqYtfUCI5pYvOHmDXtw==", - "license": "MIT", - "dependencies": { - "keyv": "^5.2.1" - } - }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -5138,11 +5127,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" - }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -5254,14 +5238,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", - "engines": { - "node": "*" - } - }, "node_modules/debug": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", @@ -5421,14 +5397,6 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/enhanced-resolve": { "version": "5.15.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz", @@ -6184,11 +6152,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/fast-copy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", - "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==" - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -6243,11 +6206,6 @@ "node": ">=6" } }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" - }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -6738,11 +6696,6 @@ "node": ">= 0.4" } }, - "node_modules/help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -10545,6 +10498,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, "engines": { "node": ">=10" } @@ -10835,6 +10789,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -11058,6 +11013,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "dependencies": { "wrappy": "1" } @@ -11296,30 +11252,6 @@ "split2": "^4.0.0" } }, - "node_modules/pino-pretty": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.2.2.tgz", - "integrity": "sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==", - "dependencies": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.2", - "fast-safe-stringify": "^2.1.1", - "help-me": "^5.0.0", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", - "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^4.0.1", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, "node_modules/pino-std-serializers": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", @@ -11549,15 +11481,6 @@ "node": ">= 8" } }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -11874,11 +11797,6 @@ "node": ">=10" } }, - "node_modules/secure-json-parse": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", - "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" - }, "node_modules/semver": { "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", @@ -12193,6 +12111,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, "engines": { "node": ">=8" }, @@ -13092,7 +13011,8 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/write-file-atomic": { "version": "4.0.2", diff --git a/package.json b/package.json index 0b77384..ed22dba 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,6 @@ }, "homepage": "https://github.com/crowdsecurity/nodejs-cs-bouncer#readme", "dependencies": { - "cache-manager": "^6.1.3", "ip-address": "^10.0.0", "keyv": "^5.3.4", "lodash": "^4.17.21", From e0cfb73d81806cf3a90552f970580a6ba638cb00 Mon Sep 17 00:00:00 2001 From: Julien Loizelet Date: Fri, 25 Jul 2025 14:55:43 +0900 Subject: [PATCH 09/11] docs(*): Add note on specific nextjs constraint for implementation --- examples/nextjs/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/nextjs/README.md b/examples/nextjs/README.md index 2bd0818..b48e8ca 100644 --- a/examples/nextjs/README.md +++ b/examples/nextjs/README.md @@ -25,7 +25,11 @@ It aims to help developers to understand how to integrate CrowdSec remediation i ## Technical overview -The implementation uses Next.js App Router with middleware and API routes: +The implementation uses Next.js App Router with middleware and API routes. + +**Important Note**: We cannot use the CrowdSec bouncer directly in the Next.js middleware because middleware runs on the Edge Runtime, which doesn't have access to Node.js APIs that the bouncer requires. While Next.js offers an experimental `nodeMiddleware` feature that would allow Node.js APIs in middleware, we prefer not to rely on experimental features for production use. Instead, we use a custom API route (`/api/crowdsec`) that runs in the Node.js runtime and can access the full bouncer functionality. + +**Additional Note**: We had to update the Next.js configuration (`next.config.ts`) to copy font files from the `svg-captcha-fixed` library to make them available at runtime. This is necessary because Next.js doesn't automatically include these assets in the build, and the captcha functionality requires access to these fonts to generate captcha images. ### Middleware (`src/middleware.ts`) From baf5f61088b6c1d1645e4ee2dc188a902fd7128f Mon Sep 17 00:00:00 2001 From: Roussange Alexandre Date: Thu, 28 Aug 2025 16:54:11 +0200 Subject: [PATCH 10/11] refactor(examples): update nextjs examples to better align with last documentation --- .gitignore | 5 +- examples/nextjs/.env.example | 3 + examples/nextjs/README.md | 82 ++- examples/nextjs/crowdsec/.env.example | 2 - examples/nextjs/docs/bypass.png | Bin 15957 -> 18442 bytes examples/nextjs/package.json | 16 +- examples/nextjs/postcss.config.mjs | 6 + .../crowdsec/captcha}/route.ts | 25 +- .../src/app/api/crowdsec/helpers/index.ts | 30 - .../crowdsec/{ => remediation/[ip]}/route.ts | 30 +- examples/nextjs/src/app/globals.css | 4 +- examples/nextjs/src/app/page.tsx | 9 +- examples/nextjs/src/helpers/crowdsec.ts | 40 + examples/nextjs/src/helpers/index.ts | 24 + examples/nextjs/src/helpers/ip.ts | 18 + examples/nextjs/src/middleware.ts | 40 +- examples/nextjs/tailwind.config.js | 8 + package-lock.json | 694 +++++++++++++++++- package.json | 5 +- 19 files changed, 867 insertions(+), 174 deletions(-) delete mode 100644 examples/nextjs/crowdsec/.env.example create mode 100644 examples/nextjs/postcss.config.mjs rename examples/nextjs/src/app/{crowdsec-captcha => api/crowdsec/captcha}/route.ts (51%) delete mode 100644 examples/nextjs/src/app/api/crowdsec/helpers/index.ts rename examples/nextjs/src/app/api/crowdsec/{ => remediation/[ip]}/route.ts (55%) create mode 100644 examples/nextjs/src/helpers/crowdsec.ts create mode 100644 examples/nextjs/src/helpers/index.ts create mode 100644 examples/nextjs/src/helpers/ip.ts create mode 100644 examples/nextjs/tailwind.config.js diff --git a/.gitignore b/.gitignore index 355c6ca..caec043 100644 --- a/.gitignore +++ b/.gitignore @@ -130,5 +130,8 @@ dist .yarn/install-state.gz .pnp.* -# CLaude +# Claude .claude + +# History +.history diff --git a/examples/nextjs/.env.example b/examples/nextjs/.env.example index 5a515bc..09f273d 100644 --- a/examples/nextjs/.env.example +++ b/examples/nextjs/.env.example @@ -1,3 +1,6 @@ LAPI_URL='http://localhost:8080' TEST_LOG_LEVEL='debug' +## CrowdSec +BOUNCER_KEY='1234' +BOUNCED_IP='172.19.0.1' \ No newline at end of file diff --git a/examples/nextjs/README.md b/examples/nextjs/README.md index b48e8ca..b0ad21c 100644 --- a/examples/nextjs/README.md +++ b/examples/nextjs/README.md @@ -10,16 +10,18 @@ It aims to help developers to understand how to integrate CrowdSec remediation i -- [Technical overview](#technical-overview) - - [Middleware (`src/middleware.ts`)](#middleware-srcmiddlewarets) - - [API Route (`src/app/api/crowdsec/route.ts`)](#api-route-srcappapicrowdsecroutets) - - [Captcha Handler (`src/app/crowdsec-captcha/route.ts`)](#captcha-handler-srcappcrowdsec-captcharoutets) -- [Test the bouncer](#test-the-bouncer) - - [Pre-requisites](#pre-requisites) - - [Prepare the tests](#prepare-the-tests) - - [Test a "bypass" remediation](#test-a-bypass-remediation) - - [Test a "ban" remediation](#test-a-ban-remediation) - - [Test a "captcha" remediation](#test-a-captcha-remediation) +- [NextJS basic implementation](#nextjs-basic-implementation) + - [Technical overview](#technical-overview) + - [Middleware (`src/middleware.ts`)](#middleware-srcmiddlewarets) + - [API Routes](#api-routes) + - [Remediation Check (`src/app/api/crowdsec/remediation/route.ts`)](#remediation-check-srcappapicrowdsecremediationroutets) + - [Captcha Handler (`src/app/api/crowdsec/captcha/route.ts`)](#captcha-handler-srcappapicrowdseccaptcharoutets) + - [Test the bouncer](#test-the-bouncer) + - [Pre-requisites](#pre-requisites) + - [Prepare the tests](#prepare-the-tests) + - [Test a "bypass" remediation](#test-a-bypass-remediation) + - [Test a "ban" remediation](#test-a-ban-remediation) + - [Test a "captcha" remediation](#test-a-captcha-remediation) @@ -27,9 +29,12 @@ It aims to help developers to understand how to integrate CrowdSec remediation i The implementation uses Next.js App Router with middleware and API routes. -**Important Note**: We cannot use the CrowdSec bouncer directly in the Next.js middleware because middleware runs on the Edge Runtime, which doesn't have access to Node.js APIs that the bouncer requires. While Next.js offers an experimental `nodeMiddleware` feature that would allow Node.js APIs in middleware, we prefer not to rely on experimental features for production use. Instead, we use a custom API route (`/api/crowdsec`) that runs in the Node.js runtime and can access the full bouncer functionality. +**Important Note**: Starting from Next.js 15.5, the middleware now supports the Node.js runtime, which is required for the CrowdSec bouncer to function properly. You will need Next.js version 15.5 or higher to use this implementation. The middleware configuration includes `runtime: 'nodejs'` to enable this feature. For compatibility reasons, we still use custom API routes (`/api/crowdsec/remediation` and `/api/crowdsec/captcha`) to handle the bouncer logic separately from the middleware. -**Additional Note**: We had to update the Next.js configuration (`next.config.ts`) to copy font files from the `svg-captcha-fixed` library to make them available at runtime. This is necessary because Next.js doesn't automatically include these assets in the build, and the captcha functionality requires access to these fonts to generate captcha images. +**Additional Notes**: +- The Next.js configuration (`next.config.ts`) includes a custom Webpack plugin to copy font files from the `svg-captcha-fixed` library, making them available at runtime for captcha generation. +- The project now includes Tailwind CSS v4 for styling the captcha page and other UI components. +- Environment variables are loaded from `.env` files in the `nextjs` directory using `dotenv` and `dotenv-safe` for validation. ### Middleware (`src/middleware.ts`) @@ -37,34 +42,35 @@ The middleware intercepts all requests and calls the CrowdSec API: ```js export async function middleware(req: NextRequest) { - // Skip CrowdSec check for captcha route and non-HTML requests - if (pathname === '/crowdsec-captcha' || !acceptHeader.includes('text/html')) { - return NextResponse.next(); - } - - // Call internal API to check IP remediation - const checkUrl = `${req.nextUrl.origin}/api/crowdsec`; - const res = await fetch(checkUrl, { method: 'POST' }); + // Check CrowdSec remediation using helper function + const res = await checkRequestRemediation(req); - if (res.status !== 200) { - // Return ban/captcha wall HTML - const html = await res.text(); - return new NextResponse(html, { - status: res.status, - headers: { 'Content-Type': 'text/html; charset=utf-8' }, - }); + if (res) { + // Return ban/captcha wall if remediation is required + return res; } return NextResponse.next(); } + +export const config = { + matcher: [ + // Match all routes except static files, APIs, and captcha page + '/((?!api|_next/static|_next/image|fonts/|favicon.ico|robots.txt|sitemap.*\.xml|opengraph-image|captcha|ban).*)' + ], + runtime: 'nodejs' +} ``` -### API Route (`src/app/api/crowdsec/route.ts`) +### API Routes + +#### Remediation Check (`src/app/api/crowdsec/remediation/route.ts`) -The API route handles the CrowdSec logic: +The remediation API route checks IP addresses and returns appropriate responses: ```js -export async function POST(req: Request) { +export async function GET(req: Request) { + const ip = getIpFromRequest(req); const { remediation, origin } = await bouncer.getIpRemediation(ip); const bouncerResponse = await bouncer.getResponse({ ip, origin, remediation }); @@ -78,15 +84,17 @@ export async function POST(req: Request) { } ``` -### Captcha Handler (`src/app/crowdsec-captcha/route.ts`) +#### Captcha Handler (`src/app/api/crowdsec/captcha/route.ts`) -Handles captcha form submissions: +Handles both captcha display and form submissions: ```js +// Handle captcha form submission export async function POST(req: Request) { const form = await req.formData(); const phrase = form.get('phrase')?.toString() || ''; const refresh = form.get('crowdsec_captcha_refresh')?.toString() || '0'; + const ip = getIpFromRequest(req); await bouncer.handleCaptchaSubmission({ ip, userPhrase: phrase, refresh, origin }); return NextResponse.redirect(new URL('/', req.url)); @@ -101,18 +109,20 @@ export async function POST(req: Request) { - You can run `nvm use` from the root folder to use the recommended NodeJS version for this project -- Copy the `.env.example` file to `.env` and fill in the required values +- Copy the `.env.example` file to `.env` in the `nextjs` folder and fill in the required values - Copy the `crowdsec/.env.example` file to `crowdsec/.env` and fill in the required values -- Install all dependencies using a local archive. +- Install all dependencies. - Run the following commands from the `nextjs` folder: + Run the following command from the `nextjs` folder: ```shell - npm run pack-locally && npm install + npm install ``` + **Note**: The `npm run dev` and `npm run start` commands will automatically build and pack the bouncer library before starting the server. + ### Prepare the tests 1. Launch the docker instance: diff --git a/examples/nextjs/crowdsec/.env.example b/examples/nextjs/crowdsec/.env.example deleted file mode 100644 index b04630d..0000000 --- a/examples/nextjs/crowdsec/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -BOUNCER_KEY='1234' -BOUNCED_IP='172.19.0.1' \ No newline at end of file diff --git a/examples/nextjs/docs/bypass.png b/examples/nextjs/docs/bypass.png index 00bd5420dc58ea8c254a45b737cf87e8d3531adf..74e4f863b43a02e20744f91dcc2b7d4d64287a9d 100644 GIT binary patch literal 18442 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 IZRG!d00dQz@Bjb+ literal 15957 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

Dv=My^gc3qV5KKT~5`w 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 { - dotenvSafe.config({ - path: resolve(__dirname, '../../../../../.env'), - example: resolve(__dirname, '../../../../../.env.example'), - }); - dotenv.config(); - // Load and validate the .env file in the crowdsec folder (will override any duplicate values from the main .env) - dotenvSafe.config({ - path: resolve(__dirname, '../../../../../crowdsec/.env'), - example: resolve(__dirname, '../../../../../crowdsec/.env.example'), - }); - dotenv.config({ path: resolve(__dirname, '../../../../../crowdsec/.env') }); -}; - -export const getLogger = () => { - return pino({ - level: process.env.TEST_LOG_LEVEL ?? 'debug', - }); -}; diff --git a/examples/nextjs/src/app/api/crowdsec/route.ts b/examples/nextjs/src/app/api/crowdsec/remediation/[ip]/route.ts similarity index 55% rename from examples/nextjs/src/app/api/crowdsec/route.ts rename to examples/nextjs/src/app/api/crowdsec/remediation/[ip]/route.ts index d4f11a8..9c93a19 100644 --- a/examples/nextjs/src/app/api/crowdsec/route.ts +++ b/examples/nextjs/src/app/api/crowdsec/remediation/[ip]/route.ts @@ -1,30 +1,20 @@ 'use server'; -import { CrowdSecBouncer, CrowdSecBouncerConfigurations } from '@crowdsec/nodejs-bouncer'; +import { getLogger } from '@/helpers'; +import { getCrowdSecBouncer } from '@/helpers/crowdsec'; import { NextResponse } from 'next/server'; -import { loadEnv, getLogger } from './helpers'; - -// Load and validate environment variables -loadEnv(); - -const config: CrowdSecBouncerConfigurations = { - url: process.env.LAPI_URL ?? 'http://localhost:8080', - bouncerApiToken: process.env.BOUNCER_KEY ?? '', - wallsOptions: { - captcha: { - captchaAction: '/crowdsec-captcha', - }, - }, -}; - -const bouncer = new CrowdSecBouncer(config); - // Set up the logger for this example const logger = getLogger(); -export async function POST(req: Request) { - const ip = process.env.BOUNCED_IP as string; // In a production scenario, the user's real IP should be retrieved. +export async function GET(_req: Request) { + const bouncer = await getCrowdSecBouncer(); + const ip = _req.url.split('/').pop(); // Get the IP from the request URL + + if (!ip) { + logger.warn('CrowdSec API route called without IP'); + return new NextResponse('IP not found', { status: 400 }); + } logger.info(`CrowdSec API route called with IP: ${ip}`); diff --git a/examples/nextjs/src/app/globals.css b/examples/nextjs/src/app/globals.css index 79a3e36..0f4baaf 100644 --- a/examples/nextjs/src/app/globals.css +++ b/examples/nextjs/src/app/globals.css @@ -1,3 +1,5 @@ +@import 'tailwindcss'; + :root { --background: #ffffff; --foreground: #171717; @@ -26,8 +28,6 @@ body { * { box-sizing: border-box; - padding: 0; - margin: 0; } a { diff --git a/examples/nextjs/src/app/page.tsx b/examples/nextjs/src/app/page.tsx index 768d8cb..c7365ad 100644 --- a/examples/nextjs/src/app/page.tsx +++ b/examples/nextjs/src/app/page.tsx @@ -1,17 +1,14 @@ -import Image from 'next/image'; import styles from './page.module.css'; export default function Home() { return (

- Next.js logo -
-

Welcome to the Test Page

-

If you see this, you're not banned.

+
+

Welcome to the Test Page

+

If you see this, you're not banned.

-
); } diff --git a/examples/nextjs/src/helpers/crowdsec.ts b/examples/nextjs/src/helpers/crowdsec.ts new file mode 100644 index 0000000..3fac15f --- /dev/null +++ b/examples/nextjs/src/helpers/crowdsec.ts @@ -0,0 +1,40 @@ +'use server'; + +import { CrowdSecBouncer, CrowdSecBouncerConfigurations } from '@crowdsec/nodejs-bouncer'; +import { NextRequest, NextResponse } from 'next/server'; +import { loadEnv } from '.'; +import { getIpFromRequest } from './ip'; + +// Load and validate environment variables +loadEnv(); + +const config: CrowdSecBouncerConfigurations = { + url: process.env.LAPI_URL ?? 'http://localhost:8080', + bouncerApiToken: process.env.BOUNCER_KEY ?? '', + wallsOptions: { + captcha: { + captchaAction: '/api/crowdsec/captcha', + }, + }, +}; + +export const getCrowdSecBouncer = async () => new CrowdSecBouncer(config); + +export const checkIpRemediation = async (req: NextRequest) => { + const ip = await getIpFromRequest(req); + + const checkUrl = `${req.nextUrl.origin}/api/crowdsec/remediation/${ip}`; + try { + const res = await fetch(checkUrl, { method: 'GET' }); + + if (res.status !== 200) { + const html = await res.text(); + return new NextResponse(html, { + status: res.status, + headers: { 'Content-Type': 'text/html; charset=utf-8' }, + }); + } + } catch (err) { + console.error('CrowdSec check failed in middleware:', err); + } +}; diff --git a/examples/nextjs/src/helpers/index.ts b/examples/nextjs/src/helpers/index.ts new file mode 100644 index 0000000..42dfc3d --- /dev/null +++ b/examples/nextjs/src/helpers/index.ts @@ -0,0 +1,24 @@ +import dotenv from 'dotenv'; +import dotenvSafe from 'dotenv-safe'; +import pino from 'pino'; + +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +// Load and validate environment variables from .env file +export const loadEnv = () => { + dotenvSafe.config({ + path: resolve(__dirname, '../../.env'), + example: resolve(__dirname, '../../.env.example'), + }); + dotenv.config({ path: resolve(__dirname, '../../.env') }); +}; + +export const getLogger = () => { + return pino({ + level: process.env.TEST_LOG_LEVEL ?? 'debug', + }); +}; diff --git a/examples/nextjs/src/helpers/ip.ts b/examples/nextjs/src/helpers/ip.ts new file mode 100644 index 0000000..ab402f0 --- /dev/null +++ b/examples/nextjs/src/helpers/ip.ts @@ -0,0 +1,18 @@ +'use server'; + +import { NextRequest } from 'next/server'; + +export const getIpFromRequest = async (req: NextRequest): Promise => { + if (process.env.BOUNCED_IP) { + return process.env.BOUNCED_IP; + } + + let ip = (req.headers.get('x-real-ip') || req.headers.get('x-forwarded-for'))?.split(',')[0].trim(); + + // Normalize localhost IP + if (ip === '::1') { + ip = '127.0.0.1'; + } + + return ip ?? '0.0.0.1'; +}; diff --git a/examples/nextjs/src/middleware.ts b/examples/nextjs/src/middleware.ts index 6943793..e0d026e 100644 --- a/examples/nextjs/src/middleware.ts +++ b/examples/nextjs/src/middleware.ts @@ -1,35 +1,19 @@ import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; +import { checkIpRemediation as checkRequestRemediation } from './helpers/crowdsec'; export async function middleware(req: NextRequest) { - const { pathname } = req.nextUrl; - if (pathname === '/crowdsec-captcha') { - return NextResponse.next(); - } - - const acceptHeader = req.headers.get('accept') || ''; - - // Only run middleware for full HTML page requests - if (!acceptHeader.includes('text/html')) { - return NextResponse.next(); - } - const checkUrl = `${req.nextUrl.origin}/api/crowdsec`; - - try { - const res = await fetch(checkUrl, { - method: 'POST', - }); - - if (res.status !== 200) { - const html = await res.text(); - return new NextResponse(html, { - status: res.status, - headers: { 'Content-Type': 'text/html; charset=utf-8' }, - }); - } - } catch (err) { - console.error('CrowdSec check failed in middleware:', err); - } + // Check CrowdSec remediation, and redirect if necessary using the given response + const res = await checkRequestRemediation(req); + if (res) return res; return NextResponse.next(); } + +export const config = { + matcher: [ + // match all routes except static files and APIs + '/((?!api|_next/static|_next/image|fonts/|favicon.ico).*)', + ], + runtime: 'nodejs', // Mandatory for CrowdSec to work properly +}; diff --git a/examples/nextjs/tailwind.config.js b/examples/nextjs/tailwind.config.js new file mode 100644 index 0000000..48738de --- /dev/null +++ b/examples/nextjs/tailwind.config.js @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ['./src/pages/**/*.{js,ts,jsx,tsx,mdx}', './src/components/**/*.{js,ts,jsx,tsx,mdx}', './src/app/**/*.{js,ts,jsx,tsx,mdx}'], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/package-lock.json b/package-lock.json index 5f2224f..cec8610 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,11 +9,14 @@ "version": "0.1.0", "license": "MIT", "dependencies": { + "@tailwindcss/postcss": "^4.1.12", "ip-address": "^10.0.0", "keyv": "^5.3.4", "lodash": "^4.17.21", "pino": "^9.4.0", - "svg-captcha-fixed": "^1.5.2" + "postcss": "^8.5.6", + "svg-captcha-fixed": "^1.5.2", + "tailwindcss": "^4.1.12" }, "devDependencies": { "@eslint/compat": "^1.2.0", @@ -58,6 +61,18 @@ "node": ">=0.10.0" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -600,7 +615,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.4.tgz", "integrity": "sha512-A9CnAbC6ARNMKcIcrQwq6HeHCjpcBZ5wSx4U01WXCqEKlrzB9F9315WDNHkrs2xbx7YjjSxbUYxuN6EQzpcY2g==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -612,7 +626,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.4.tgz", "integrity": "sha512-hHyapA4A3gPaDCNfiqyZUStTMqIkKRshqPIuDOXv1hcBnD4U3l8cP0T1HMCfGRxQ6V64TGCcoswChANyOAwbQg==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -623,7 +636,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.3.tgz", "integrity": "sha512-8K5IFFsQqF9wQNJptGbS6FNKgUTsSRYnTqNCG1vPP8jFdjSv18n2mQfJpkt2Oibo9iBEzcDnDxNwKTzC7svlJw==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -1379,6 +1391,18 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -2881,18 +2905,26 @@ "version": "0.3.12", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -2901,14 +2933,12 @@ "version": "1.5.4", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.29", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2928,7 +2958,6 @@ "version": "0.2.12", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -3315,6 +3344,267 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@tailwindcss/node": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.12.tgz", + "integrity": "sha512-3hm9brwvQkZFe++SBt+oLjo4OLDtkvlE8q2WalaD/7QWaeM7KEJbAiY/LJZUaCs7Xa8aUu4xy3uoyX4q54UVdQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.4", + "enhanced-resolve": "^5.18.3", + "jiti": "^2.5.1", + "lightningcss": "1.30.1", + "magic-string": "^0.30.17", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.12" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.12.tgz", + "integrity": "sha512-gM5EoKHW/ukmlEtphNwaGx45fGoEmP10v51t9unv55voWh6WrOL19hfuIdo2FjxIaZzw776/BUQg7Pck++cIVw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.4", + "tar": "^7.4.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.12", + "@tailwindcss/oxide-darwin-arm64": "4.1.12", + "@tailwindcss/oxide-darwin-x64": "4.1.12", + "@tailwindcss/oxide-freebsd-x64": "4.1.12", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.12", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.12", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.12", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.12", + "@tailwindcss/oxide-linux-x64-musl": "4.1.12", + "@tailwindcss/oxide-wasm32-wasi": "4.1.12", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.12", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.12" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.12.tgz", + "integrity": "sha512-oNY5pq+1gc4T6QVTsZKwZaGpBb2N1H1fsc1GD4o7yinFySqIuRZ2E4NvGasWc6PhYJwGK2+5YT1f9Tp80zUQZQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.12.tgz", + "integrity": "sha512-cq1qmq2HEtDV9HvZlTtrj671mCdGB93bVY6J29mwCyaMYCP/JaUBXxrQQQm7Qn33AXXASPUb2HFZlWiiHWFytw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.12.tgz", + "integrity": "sha512-6UCsIeFUcBfpangqlXay9Ffty9XhFH1QuUFn0WV83W8lGdX8cD5/+2ONLluALJD5+yJ7k8mVtwy3zMZmzEfbLg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.12.tgz", + "integrity": "sha512-JOH/f7j6+nYXIrHobRYCtoArJdMJh5zy5lr0FV0Qu47MID/vqJAY3r/OElPzx1C/wdT1uS7cPq+xdYYelny1ww==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.12.tgz", + "integrity": "sha512-v4Ghvi9AU1SYgGr3/j38PD8PEe6bRfTnNSUE3YCMIRrrNigCFtHZ2TCm8142X8fcSqHBZBceDx+JlFJEfNg5zQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.12.tgz", + "integrity": "sha512-YP5s1LmetL9UsvVAKusHSyPlzSRqYyRB0f+Kl/xcYQSPLEw/BvGfxzbH+ihUciePDjiXwHh+p+qbSP3SlJw+6g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.12.tgz", + "integrity": "sha512-V8pAM3s8gsrXcCv6kCHSuwyb/gPsd863iT+v1PGXC4fSL/OJqsKhfK//v8P+w9ThKIoqNbEnsZqNy+WDnwQqCA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.12.tgz", + "integrity": "sha512-xYfqYLjvm2UQ3TZggTGrwxjYaLB62b1Wiysw/YE3Yqbh86sOMoTn0feF98PonP7LtjsWOWcXEbGqDL7zv0uW8Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.12.tgz", + "integrity": "sha512-ha0pHPamN+fWZY7GCzz5rKunlv9L5R8kdh+YNvP5awe3LtuXb5nRi/H27GeL2U+TdhDOptU7T6Is7mdwh5Ar3A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.12.tgz", + "integrity": "sha512-4tSyu3dW+ktzdEpuk6g49KdEangu3eCYoqPhWNsZgUhyegEda3M9rG0/j1GV/JjVVsj+lG7jWAyrTlLzd/WEBg==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.5", + "@emnapi/runtime": "^1.4.5", + "@emnapi/wasi-threads": "^1.0.4", + "@napi-rs/wasm-runtime": "^0.2.12", + "@tybys/wasm-util": "^0.10.0", + "tslib": "^2.8.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.12.tgz", + "integrity": "sha512-iGLyD/cVP724+FGtMWslhcFyg4xyYyM+5F4hGvKA7eifPkXHRAUDFaimu53fpNg9X8dfP75pXx/zFt/jlNF+lg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.12.tgz", + "integrity": "sha512-NKIh5rzw6CpEodv/++r0hGLlfgT/gFN+5WNdZtvh6wpU2BpGNgdjvj6H2oFc8nCM839QM1YOhjpgbAONUb4IxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.12.tgz", + "integrity": "sha512-5PpLYhCAwf9SJEeIsSmCDLgyVfdBhdBpzX1OJ87anT9IVR0Z9pjM0FNixCAUAHGnMBGB8K99SwAheXrT0Kh6QQ==", + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.1.12", + "@tailwindcss/oxide": "4.1.12", + "postcss": "^8.4.41", + "tailwindcss": "4.1.12" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -3343,7 +3633,6 @@ "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": { @@ -5054,6 +5343,15 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -5321,6 +5619,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -5398,10 +5705,10 @@ "dev": true }, "node_modules/enhanced-resolve": { - "version": "5.15.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz", - "integrity": "sha512-3d3JRbwsCLJsYgvb6NuWEG44jjPSOMuS73L/6+7BZuoKm3W+qXnSoIYVHi8dG7Qcg4inAY4jbzkZ7MnskePeDg==", - "dev": true, + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -6606,8 +6913,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/graphemer": { "version": "1.4.0", @@ -10494,6 +10800,15 @@ "dev": true, "license": "MIT" }, + "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==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/joycon": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", @@ -10611,6 +10926,234 @@ "node": ">= 0.8.0" } }, + "node_modules/lightningcss": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/lilconfig": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", @@ -10693,7 +11236,6 @@ "version": "0.30.17", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" @@ -10798,12 +11340,38 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, + "node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/mlly": { "version": "1.7.4", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", @@ -10835,6 +11403,24 @@ "thenify-all": "^1.0.0" } }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/napi-postinstall": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.0.tgz", @@ -11207,7 +11793,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -11357,6 +11942,34 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/postcss-load-config": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", @@ -11914,6 +12527,15 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-support": { "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", @@ -12214,15 +12836,46 @@ "url": "https://opencollective.com/synckit" } }, + "node_modules/tailwindcss": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.12.tgz", + "integrity": "sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==", + "license": "MIT" + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, "engines": { "node": ">=6" } }, + "node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -12548,7 +13201,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, "license": "0BSD", "optional": true }, diff --git a/package.json b/package.json index ed22dba..0a02422 100644 --- a/package.json +++ b/package.json @@ -48,11 +48,14 @@ }, "homepage": "https://github.com/crowdsecurity/nodejs-cs-bouncer#readme", "dependencies": { + "@tailwindcss/postcss": "^4.1.12", "ip-address": "^10.0.0", "keyv": "^5.3.4", "lodash": "^4.17.21", "pino": "^9.4.0", - "svg-captcha-fixed": "^1.5.2" + "postcss": "^8.5.6", + "svg-captcha-fixed": "^1.5.2", + "tailwindcss": "^4.1.12" }, "devDependencies": { "@eslint/compat": "^1.2.0", From 1c1057aabbbcdea890cade8bb12f5483b32bf487 Mon Sep 17 00:00:00 2001 From: Julien Loizelet Date: Fri, 5 Sep 2025 09:48:54 +0900 Subject: [PATCH 11/11] test(*): Mount a volume for crowdsec docker as it is required since 1.7.0 --- examples/express-server/docker-compose.yml | 4 ++ examples/nextjs/README.md | 59 +++++++++++++--------- examples/nextjs/docker-compose.yml | 4 ++ 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/examples/express-server/docker-compose.yml b/examples/express-server/docker-compose.yml index e290c72..b1e66b4 100644 --- a/examples/express-server/docker-compose.yml +++ b/examples/express-server/docker-compose.yml @@ -8,3 +8,7 @@ services: - crowdsec/.env volumes: - ./crowdsec/custom-config.yaml:/etc/crowdsec/config.yaml.local + - crowdsec_data:/var/lib/crowdsec/data + +volumes: + crowdsec_data: \ No newline at end of file diff --git a/examples/nextjs/README.md b/examples/nextjs/README.md index b0ad21c..f35881b 100644 --- a/examples/nextjs/README.md +++ b/examples/nextjs/README.md @@ -11,17 +11,19 @@ It aims to help developers to understand how to integrate CrowdSec remediation i - [NextJS basic implementation](#nextjs-basic-implementation) - - [Technical overview](#technical-overview) - - [Middleware (`src/middleware.ts`)](#middleware-srcmiddlewarets) - - [API Routes](#api-routes) - - [Remediation Check (`src/app/api/crowdsec/remediation/route.ts`)](#remediation-check-srcappapicrowdsecremediationroutets) - - [Captcha Handler (`src/app/api/crowdsec/captcha/route.ts`)](#captcha-handler-srcappapicrowdseccaptcharoutets) - - [Test the bouncer](#test-the-bouncer) - - [Pre-requisites](#pre-requisites) - - [Prepare the tests](#prepare-the-tests) - - [Test a "bypass" remediation](#test-a-bypass-remediation) - - [Test a "ban" remediation](#test-a-ban-remediation) - - [Test a "captcha" remediation](#test-a-captcha-remediation) + - [Technical overview](#technical-overview) + - [Middleware (`src/middleware.ts`)](#middleware-srcmiddlewarets) + - [API Routes](#api-routes) + - [Remediation Check ( + `src/app/api/crowdsec/remediation/route.ts`)](#remediation-check-srcappapicrowdsecremediationroutets) + - [Captcha Handler ( + `src/app/api/crowdsec/captcha/route.ts`)](#captcha-handler-srcappapicrowdseccaptcharoutets) + - [Test the bouncer](#test-the-bouncer) + - [Pre-requisites](#pre-requisites) + - [Prepare the tests](#prepare-the-tests) + - [Test a "bypass" remediation](#test-a-bypass-remediation) + - [Test a "ban" remediation](#test-a-ban-remediation) + - [Test a "captcha" remediation](#test-a-captcha-remediation) @@ -29,12 +31,19 @@ It aims to help developers to understand how to integrate CrowdSec remediation i The implementation uses Next.js App Router with middleware and API routes. -**Important Note**: Starting from Next.js 15.5, the middleware now supports the Node.js runtime, which is required for the CrowdSec bouncer to function properly. You will need Next.js version 15.5 or higher to use this implementation. The middleware configuration includes `runtime: 'nodejs'` to enable this feature. For compatibility reasons, we still use custom API routes (`/api/crowdsec/remediation` and `/api/crowdsec/captcha`) to handle the bouncer logic separately from the middleware. +**Important Note**: Starting from Next.js 15.5, the middleware now supports the Node.js runtime, which is required for +the CrowdSec bouncer to function properly. You will need Next.js version 15.5 or higher to use this implementation. The +middleware configuration includes `runtime: 'nodejs'` to enable this feature. For compatibility reasons, we still use +custom API routes (`/api/crowdsec/remediation` and `/api/crowdsec/captcha`) to handle the bouncer logic separately from +the middleware. **Additional Notes**: -- The Next.js configuration (`next.config.ts`) includes a custom Webpack plugin to copy font files from the `svg-captcha-fixed` library, making them available at runtime for captcha generation. + +- The Next.js configuration (`next.config.ts`) includes a custom Webpack plugin to copy font files from the + `svg-captcha-fixed` library, making them available at runtime for captcha generation. - The project now includes Tailwind CSS v4 for styling the captcha page and other UI components. -- Environment variables are loaded from `.env` files in the `nextjs` directory using `dotenv` and `dotenv-safe` for validation. +- Environment variables are loaded from `.env` files in the `nextjs` directory using `dotenv` and `dotenv-safe` for + validation. ### Middleware (`src/middleware.ts`) @@ -44,12 +53,12 @@ The middleware intercepts all requests and calls the CrowdSec API: export async function middleware(req: NextRequest) { // Check CrowdSec remediation using helper function const res = await checkRequestRemediation(req); - + if (res) { // Return ban/captcha wall if remediation is required return res; } - + return NextResponse.next(); } @@ -95,7 +104,7 @@ export async function POST(req: Request) { const phrase = form.get('phrase')?.toString() || ''; const refresh = form.get('crowdsec_captcha_refresh')?.toString() || '0'; const ip = getIpFromRequest(req); - + await bouncer.handleCaptchaSubmission({ ip, userPhrase: phrase, refresh, origin }); return NextResponse.redirect(new URL('/', req.url)); } @@ -111,8 +120,6 @@ export async function POST(req: Request) { - Copy the `.env.example` file to `.env` in the `nextjs` folder and fill in the required values -- Copy the `crowdsec/.env.example` file to `crowdsec/.env` and fill in the required values - - Install all dependencies. Run the following command from the `nextjs` folder: @@ -121,7 +128,8 @@ export async function POST(req: Request) { npm install ``` - **Note**: The `npm run dev` and `npm run start` commands will automatically build and pack the bouncer library before starting the server. + **Note**: The `npm run dev` and `npm run start` commands will automatically build and pack the bouncer library before + starting the server. ### Prepare the tests @@ -141,7 +149,7 @@ In another terminal, create a bouncer if you haven't already: docker exec -ti nodejs-cs-nextjs-crowdsec sh -c 'cscli bouncers add NodeBouncer --key $BOUNCER_KEY' ``` -We are using here the `BOUNCER_KEY` variable defined in `crowdsec/.env` file. +We are using here the `BOUNCER_KEY` variable defined in `.env` file. 3. Launch the Next.js Server @@ -161,7 +169,8 @@ You should see different log messages in your terminal when you access the home ### Test a "bypass" remediation -As you don't have yet any decisions, you can access the `http://localhost:3000` page and just see the normal Next.js content. +As you don't have yet any decisions, you can access the `http://localhost:3000` page and just see the normal Next.js +content. ![](./docs/bypass.png) @@ -175,7 +184,7 @@ First, add a ban remediation for the IP that will be tested: docker exec -ti nodejs-cs-nextjs-crowdsec sh -c 'cscli decisions add --ip $BOUNCED_IP --duration 12m --type ban' ``` -We are using here the `BOUNCED_IP` variable defined in `crowdsec/.env` file. +We are using here the `BOUNCED_IP` variable defined in `.env` file. You should see the success message `Decision successfully added`. @@ -191,13 +200,13 @@ You should see `Final remediation for IP is ban` in terminal. First, remove your last decision: ```shell -docker exec -ti nodejs-cs-crowdsec sh -c 'cscli decisions delete --ip $BOUNCED_IP' +docker exec -ti nodejs-cs-nextjs-crowdsec sh -c 'cscli decisions delete --ip $BOUNCED_IP' ``` Then, add a captcha decision: ```shell -docker exec -ti nodejs-cs-crowdsec sh -c 'cscli decisions add --ip $BOUNCED_IP --duration 12m --type captcha' +docker exec -ti nodejs-cs-nextjs-crowdsec sh -c 'cscli decisions add --ip $BOUNCED_IP --duration 12m --type captcha' ``` If you try to access the home page (after two minutes as it is the default ttl for malicious IP), you should the "Access diff --git a/examples/nextjs/docker-compose.yml b/examples/nextjs/docker-compose.yml index d9969d1..4d5d353 100644 --- a/examples/nextjs/docker-compose.yml +++ b/examples/nextjs/docker-compose.yml @@ -8,3 +8,7 @@ services: - ../express-server/crowdsec/.env volumes: - ./crowdsec/custom-config.yaml:/etc/crowdsec/config.yaml.local + - crowdsec_data:/var/lib/crowdsec/data + +volumes: + crowdsec_data: \ No newline at end of file