diff --git a/.agents-docs/AGENTS-development-commands.md b/.agents-docs/AGENTS-development-commands.md index b3ac060..ed742b9 100644 --- a/.agents-docs/AGENTS-development-commands.md +++ b/.agents-docs/AGENTS-development-commands.md @@ -9,8 +9,17 @@ | `npm test` | Runs the full Vitest suite once (`vitest run`). | | `npm run test:watch` | Vitest in watch mode. | | `npm run test:coverage` | Vitest with v8 coverage (`text` + `lcov`). | -| `npm run lint` | ESLint over `src/`. | -| `npm run format` | Prettier write over `src/**/*.ts` and `tests/**/*.ts`. | +| `npm run lint` | ESLint over `src/`, `tests/` and `scripts/`. | +| `npm run format` | Prettier write over `src/**/*.ts`, `tests/**/*.ts` and `scripts/**/*.mjs`. | +| `npm run format:check` | Prettier check (no writes) — used in CI. | +| `npm run smoke` | Builds, then runs the live local-ONNX provider test (`scripts/smoke-test.mjs`). Downloads models from HuggingFace, so it is local-only and not run in CI. | +| `npm run engines:check` | Runs the built `dist/` (ESM + CJS) and asserts real behaviour, to verify the `engines.node` floor. See CI below. | + +Glob arguments in the `format` scripts must use **double** quotes. Single quotes are not stripped by `cmd`/PowerShell, so prettier receives the literal glob, matches nothing, and the script silently succeeds as a no-op on Windows. + +`eslint.config.mjs` relaxes two rules for `tests/**` only: `no-explicit-any` is off (mocking `fetch`/`setTimeout`/provider responses legitimately needs `any`) and `no-unused-vars` honours the `^_` prefix for intentionally unused arguments. Neither relaxation applies to `src/`. `scripts/**/*.mjs` is plain ESM parsed by the default parser, so only core rules apply there. + +`.gitattributes` pins the whole tree to `eol=lf` via `* text=auto eol=lf`. Files authored on Windows otherwise enter the index with CRLF, which produces a whole-file diff that buries the real change — this had already happened to three files. Prettier enforces LF too, but only for the extensions it covers, so the attribute is what protects `.yml`, `.json` and `.md`. ## Running a single test @@ -32,4 +41,48 @@ npx vitest tests/clustering # watch a directory - `dist/` is the published artifact; `files` in `package.json` ships `dist`, `README.md`, `LICENSE`. - `@huggingface/transformers` is an **optional peer dependency** — present in `devDependencies` for local-provider tests but never required for consumers who don't use the local ONNX provider. -- Engines: Node `>=18`. +- Engines: Node `>=18`. The dev toolchain itself needs `>=20`, so 18 is verified against the built artifact only — see CI below. +- `package-lock.json` **is tracked**. Use `npm ci` for reproducible installs; do not re-ignore it. + +## CI + +`.github/workflows/ci.yml` runs on pushes to `master`/`develop`, on every pull request, and weekly on a schedule. + +| Job | What it does | +|---|---| +| `verify` | `format:check`, `lint`, `typecheck`, `test`, `build` across Node 20, 22, 24. | +| `engines-floor` | Builds on Node 24, then runs `npm run engines:check` on Node 18. | +| `audit` | `npm audit --audit-level=high` against the committed lockfile. | + +Notes for anyone editing the workflow: + +- The `verify` matrix floor is **20, not 18**, because vitest 4 requires `^20 \|\| ^22 \|\| >=24` and eslint 10 requires `^20.19 \|\| ^22.13 \|\| >=24`. Node 18 cannot run the toolchain at all. `engines-floor` covers the `>=18` claim instead by exercising the built `dist/`, which has no runtime dependencies. If `engines.node` changes, update that job. +- Installs use `npm ci --ignore-scripts` to skip the `onnxruntime-node` and `sharp` postinstalls (hundreds of MB of native binaries). Nothing in CI needs them. If a future test does need real ONNX, drop `--ignore-scripts` for that job rather than adding it to `verify`. +- `audit` is gated at `high` so moderate findings in dev-only transitive dependencies don't block merges, and runs weekly so new advisories surface on their own schedule. + +## Dependency overrides + +`package.json` declares three `overrides`. All exist to escape advisories that the declaring package pins below the fixed version, with no upstream release available. **These are temporary and should be removed as soon as the condition in the last column is met** — each one forces a version outside a range some dependency declares, so none should outlive its reason. + +| Override | Declared range it escapes | Advisory | Remove when | +|---|---|---|---| +| `sharp: ^0.35.3` | `^0.34.5`, by `@huggingface/transformers` | libvips CVEs (GHSA-f88m-g3jw-g9cj) | transformers depends on `sharp >=0.35.0` | +| `adm-zip: ^0.6.0` | `0.5.x`, via `onnxruntime-node@1.24.3` | GHSA-xcpc-8h2w-3j85 | `onnxruntime-node` depends on `adm-zip >=0.6.0` **and** transformers takes that version | +| `esbuild: 0.27.2` | `^0.27.0`, by `tsup` | GHSA-g7r4-m6w7-qqqr (affects `0.27.3` – `0.28.0`) | tsup widens to `^0.28.1` or later | + +Two things to know before touching them: + +- **`sharp` and `adm-zip` are not covered by `npm test`.** The unit suite mocks providers, so it will stay green even if these break the local ONNX provider. `npm run smoke` is the only guard — it exercises `onnxruntime-node` end-to-end across three models. Re-run it after any change here. +- **`esbuild` must be an override, not just a lockfile entry.** `^0.27.0` has no safe version above `0.27.2`, so anything that re-resolves the range (a fresh `npm install`, `npm update`, a dependency bump) would pull a vulnerable version back in. The pin is what makes it stick. + +Check whether any of these can go with: + +```bash +npm view @huggingface/transformers dependencies +npm view tsup dependencies.esbuild +``` + +## TypeScript version constraints + +- The project is on **TypeScript 6.0.x**. Do not bump to TypeScript 7 yet: `@typescript-eslint/*` v8 declares `typescript: ">=4.8.4 <6.1.0"`, so `npm run lint` would run against an unsupported compiler. +- `tsconfig.json` sets `"ignoreDeprecations": "6.0"`. This is **required for `npm run build`**, not for our own config — tsup's dts pipeline hardcodes `baseUrl: compilerOptions.baseUrl || "."` (`node_modules/tsup/dist/rollup.js`), and TS 6 raises `TS5101` for deprecated `baseUrl`. Removing the flag breaks the DTS build. It can be dropped once tsup stops injecting `baseUrl`. diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..682208b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +# Normalize text files to LF in the repository regardless of the authoring +# platform. Without this, files written on Windows land in the index with CRLF +# while the rest of the tree is LF, producing whole-file diffs that hide the +# real change. Prettier already enforces LF, but only for the files it covers. +* text=auto eol=lf + +*.jpg binary diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..4f08a30 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,87 @@ +name: CI + +on: + push: + branches: [master, develop] + pull_request: + schedule: + # Weekly, so new advisories surface on their own schedule instead of + # failing an unrelated pull request. + - cron: '0 6 * * 1' + +permissions: + contents: read + +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + verify: + name: verify (node ${{ matrix.node }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # The floor is 20, not the `engines.node` floor of 18, because the dev + # toolchain requires it: vitest 4 needs ^20 || ^22 || >=24 and eslint 10 + # needs ^20.19 || ^22.13 || >=24. The `engines` claim is covered by the + # engines-floor job below instead. + node: ['20', '22', '24'] + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-node@v7 + with: + node-version: ${{ matrix.node }} + cache: npm + + # --ignore-scripts skips the onnxruntime-node and sharp postinstalls, + # which download hundreds of MB of native binaries. Nothing below needs + # them: the suite mocks providers, and the local ONNX provider is only + # exercised by `npm run smoke`, which is deliberately not run here since + # it downloads models from HuggingFace. + - run: npm ci --ignore-scripts + + - run: npm run format:check + - run: npm run lint + - run: npm run typecheck + - run: npm test + - run: npm run build + + engines-floor: + name: engines floor (node 18) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + # Build on a modern Node, since the toolchain cannot run on 18... + - uses: actions/setup-node@v7 + with: + node-version: '24' + cache: npm + - run: npm ci --ignore-scripts + - run: npm run build + + # ...then run the built artifact on the oldest Node that engines.node + # claims to support. The package has no runtime dependencies, so this + # needs nothing installed. Keep this in step with engines.node. + - uses: actions/setup-node@v7 + with: + node-version: '18' + - run: npm run engines:check + + audit: + name: audit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-node@v7 + with: + node-version: '24' + cache: npm + + # Audits the committed lockfile. Fails on high and critical only; moderate + # and below in dev-only transitive dependencies should not block a merge. + - run: npm audit --audit-level=high diff --git a/.gitignore b/.gitignore index 630bb95..fa04c29 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ -node_modules -package-lock.json -dist -coverage -specs -specs--completed +node_modules +dist +coverage +specs +specs--completed diff --git a/AGENTS.md b/AGENTS.md index e433178..5cae695 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,7 +14,9 @@ The sections below are brief summaries. Each links to a detail file in `.agents- ## Development Commands -`npm run build` (tsup → dual ESM/CJS + dts), `npm test` (vitest run), `npm run test:watch`, `npm run test:coverage`, `npm run lint` (eslint), `npm run format` (prettier). Tests live in `tests/` mirroring `src/`. +`npm run build` (tsup → dual ESM/CJS + dts), `npm test` (vitest run), `npm run test:watch`, `npm run test:coverage`, `npm run lint` (eslint over `src/` + `tests/`), `npm run format` / `npm run format:check` (prettier), `npm run smoke` (live ONNX, local-only), `npm run engines:check`. Tests live in `tests/` mirroring `src/`. CI (`.github/workflows/ci.yml`) enforces all of these except `smoke`; `package-lock.json` is tracked, so use `npm ci`. + +Three temporary `overrides` in `package.json` (`sharp`, `adm-zip`, `esbuild`) hold transitive dependencies at non-vulnerable versions, and TypeScript is held at 6.x. Both have removal conditions documented — read the detail file before changing either. Details: [Development Commands](./.agents-docs/AGENTS-development-commands.md) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28cbfdb..51ed2da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## [Unreleased] + +### Maintenance + +Tooling and dependency work only — **no changes to the public API or to runtime behavior**. Consumers are unaffected. + +- **TypeScript 6:** upgraded from 5.9 to 6.0.3, the highest major currently supported by `@typescript-eslint` v8 (`>=4.8.4 <6.1.0`). TypeScript 7 is deliberately deferred until typescript-eslint supports it. `tsconfig.json` now sets `"ignoreDeprecations": "6.0"`, which TS 6 requires because tsup's dts pipeline injects the now-deprecated `baseUrl`. +- **All npm audit advisories resolved (5 → 0).** Added `overrides` for `sharp` (libvips CVEs), `adm-zip`, and `esbuild`, each of which was pinned below its fixed version by a dependency with no upstream fix available. All three sat under `@huggingface/transformers`, the optional peer dependency, so consumers not using the local ONNX provider were never exposed. Every override is documented with a condition for its removal. +- **`package-lock.json` is now tracked.** It was previously gitignored, so installs were not reproducible and the `overrides` above had no recorded resolution. Use `npm ci`. +- **Fixed `npm run format`, which was a silent no-op on Windows.** Its globs were single-quoted, which `cmd`/PowerShell do not strip, so Prettier matched zero files and exited successfully. As a result 90 files had been formatted at Prettier's defaults rather than this project's `.prettierrc` (100 columns, `es5` trailing commas); the configured style is now applied throughout. Added `npm run format:check`. +- **`npm run lint` now covers `tests/` as well as `src/`.** `eslint.config.mjs` had always declared `tests/**`, but the script never passed it. Cleared the dead code this surfaced — unused imports, a vestigial `EmbeddingStore`, and an abandoned serialization buffer — and relaxed `no-explicit-any` for test files only. +- **Added CI** (`.github/workflows/ci.yml`): format, lint, typecheck, test and build across Node 20/22/24, plus an `engines-floor` job that runs the built `dist/` on Node 18 to verify the `engines.node` claim (the dev toolchain itself now requires Node >=20), and a weekly `npm audit`. +- **`scripts/` is now linted and formatted**, and `.gitattributes` pins the tree to LF line endings so files authored on Windows can no longer enter the index with CRLF. + ## [0.6.0] - 2026-08-12 ### New Features diff --git a/eslint.config.mjs b/eslint.config.mjs index 5f427b3..a66b82f 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -18,4 +18,26 @@ export default [ ...tseslint.configs.recommended.rules, }, }, + { + files: ['tests/**/*.ts'], + rules: { + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }, + ], + }, + }, + { + // Plain ESM, parsed by the default parser rather than the TypeScript one, + // so only core rules apply here. + files: ['scripts/**/*.mjs'], + languageOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + rules: { + 'no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], + }, + }, ]; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..504f69b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5040 @@ +{ + "name": "embedding-utils", + "version": "0.6.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "embedding-utils", + "version": "0.6.0", + "license": "Apache-2.0", + "devDependencies": { + "@huggingface/transformers": "^4.2.0", + "@types/node": "^25.9.5", + "@typescript-eslint/eslint-plugin": "^8.67.0", + "@typescript-eslint/parser": "^8.67.0", + "@vitest/coverage-v8": "^4.1.10", + "eslint": "^10.8.1", + "prettier": "^3.9.6", + "tsup": "^8.5.1", + "typescript": "^6.0.3", + "vitest": "^4.1.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@huggingface/transformers": "^4.2.0" + }, + "peerDependenciesMeta": { + "@huggingface/transformers": { + "optional": true + } + } + }, + "node_modules/@babel/helper-string-parser": { + "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.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz", + "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@huggingface/jinja": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.6.tgz", + "integrity": "sha512-MyMWyLnjqo+KRJYSH7oWNbsOn5onuIvfXYPcc0WOGxU0eHUV7oAYUoQTl2BMdu7ml+ea/bu11UM+EshbeHwtIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@huggingface/tokenizers": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@huggingface/tokenizers/-/tokenizers-0.1.3.tgz", + "integrity": "sha512-8rF/RRT10u+kn7YuUbUg0OF30K8rjTc78aHpxT+qJ1uWSqxT1MHi8+9ltwYfkFYJzT/oS+qw3JVfHtNMGAdqyA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@huggingface/transformers": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@huggingface/transformers/-/transformers-4.2.0.tgz", + "integrity": "sha512-8BRCoBMH0XsWaEIamuR0LrJGAfftgHAfb2Vrffy0VKlSAE/MnUJ5/h/zTfEP3fDIft+nk7TqB8xXEyABGitBjQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@huggingface/jinja": "^0.5.6", + "@huggingface/tokenizers": "^0.1.3", + "onnxruntime-node": "1.24.3", + "onnxruntime-web": "1.26.0-dev.20260416-b7804b056c", + "sharp": "^0.34.5" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz", + "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz", + "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz", + "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz", + "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz", + "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz", + "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz", + "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz", + "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz", + "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz", + "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz", + "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz", + "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz", + "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz", + "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz", + "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz", + "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz", + "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz", + "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz", + "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz", + "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz", + "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz", + "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz", + "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz", + "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz", + "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz", + "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@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, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.144.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.144.0.tgz", + "integrity": "sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.2.tgz", + "integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.4.tgz", + "integrity": "sha512-jHC2cnyKz5xU2fhECtFl8OZ83cYNt13GZQD+0uMJ/X3o+ijmd56okHhTUwxVSHPx1IRVIJEZ1/1pPzeLCU6XKA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-Dc5mPD8F5F/FS8i01syd7FTF6yB2fVthH/TRkjwJkzUK6EpoxHtqvZQP5Zwq80/5z19TWYHIg1KOHboCgVx/aQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.4.tgz", + "integrity": "sha512-fpDm4oBo6SqLvWUYCmFhdde3U9KH2fRNNMeAnAPAIwxRL345xutL0EtEUcuoxsoazdJGv/MuDBQHlCDrtbvqOg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.4.tgz", + "integrity": "sha512-rSJoreDE/HoIzoaib6MTp5jQtCTdMHKIvItAKT/ImS6Y6Ww76oUaeMyp4Vc/fAgd/ehji068IxetHXAnqUwN9A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.4.tgz", + "integrity": "sha512-/jm8OGHgn7oGaJu3i/qZI9spUGcJ+y/lk43ttQ/iO1tOd9NissG6o97bighBCiL+BKRngmcDuR6ikfwYdJmVuQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.4.tgz", + "integrity": "sha512-tIP06BeD9EqvECBrPZ+sqdPlYrT+aYaAiu1wYziVx5elRK/ftm33JxVDy2bXGbr6J0CrtirCkR87/X5a2euEng==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.4.tgz", + "integrity": "sha512-Ql1Q0EQqVThvn9VAVlwNzsUvbSFtCMGjLpRRi4pk5i7NZZ4n5ISiLMjHYtus4VQ2PvkSw24zyaCVsiS+sXPj1w==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.4.tgz", + "integrity": "sha512-GjbjXD4XXfN19D0LZNbmiCBUoDiRACsYHr0yaIbbn8aFsXjHZifcYqu/W5Er5X2X990WjHXFrxarn5chzItorQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.4.tgz", + "integrity": "sha512-p5WR0NOwaRmJ/B1b6IjEFLLivwEsf3PrdBIhRbhTCQisbo2SvHHpG4ELB/+FgQNnB88LTOF86upmJmbvZdQ2lw==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.4.tgz", + "integrity": "sha512-4/GyVjmhR+Tc6HLJvwc1sOhPqAZtySiSMesOZyX6JQ5XBxoTDEMKQzvo07NIK6nTon/SivlZqvhzvuVBNQhObQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.4.tgz", + "integrity": "sha512-l9eeLsCNvPpmSXUej0etw/J1eqV0Jj1D5G/xG6YTijmE6dkv6E2QezgWbTfQk63v952DPqrjOCoiqxq7Bw0YUQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.4.tgz", + "integrity": "sha512-e0F355MSTMm3+UOqtV3L24gFUp2N5m1f8L/7d56deik6va+AXdrt9F8LbzGpeWGWRbZEDq4m8NVnJDeBtf9DZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.4.tgz", + "integrity": "sha512-AWLi0uBRYh6QlE7OKhiz+phZC0qwtij2QZmhmOdsLdFn64m7oMpooE9ICE3lhm9xMb4SpDo2WbHcxX1iFLFtqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.4.tgz", + "integrity": "sha512-UwSDJOg3dqCAejWdxclJjCsh3Qq4vLYMDxmyHqo1btz3stK2VqgwNd3mm5tuIwzSlGIQ/1H9Hr+Zn09mrezNqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", + "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", + "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", + "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", + "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", + "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", + "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", + "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", + "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", + "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", + "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", + "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", + "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", + "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", + "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", + "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz", + "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", + "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", + "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", + "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", + "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", + "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", + "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", + "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, + "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/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.9.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.5.tgz", + "integrity": "sha512-OScDchr2fwuUmWdf4kZ9h7PcJiYDVInhJizG/biAq3cAvqwYktuy/TYGGdZNMtNTFUP7rnb0NU4TUdm82kt4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.67.0.tgz", + "integrity": "sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/type-utils": "8.67.0", + "@typescript-eslint/utils": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "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.67.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.67.0.tgz", + "integrity": "sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "debug": "^4.4.3" + }, + "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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.67.0.tgz", + "integrity": "sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.67.0", + "@typescript-eslint/types": "^8.67.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.67.0.tgz", + "integrity": "sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.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/tsconfig-utils": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.67.0.tgz", + "integrity": "sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.67.0.tgz", + "integrity": "sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/utils": "8.67.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.67.0.tgz", + "integrity": "sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==", + "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.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.67.0.tgz", + "integrity": "sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.67.0", + "@typescript-eslint/tsconfig-utils": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.67.0.tgz", + "integrity": "sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.67.0.tgz", + "integrity": "sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.67.0", + "eslint-visitor-keys": "^5.0.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": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@vitest/coverage-v8": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.10.tgz", + "integrity": "sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.1.10", + "ast-v8-to-istanbul": "^1.0.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.2", + "obug": "^2.1.1", + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "4.1.10", + "vitest": "4.1.10" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", + "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", + "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.10", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", + "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", + "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.10", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", + "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "@vitest/utils": "4.1.10", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", + "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", + "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "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, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/adm-zip": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.6.0.tgz", + "integrity": "sha512-XleryMhbuksdKtofnWZ9Sk+4CUTbms4Mb/EU32SZwToAyZ5RgVos/ki8n+yr0LWHOGKuakbXTuuYNHLQjhddgg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/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/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-v8-to-istanbul": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.0.tgz", + "integrity": "sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "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/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "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/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/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, + "license": "MIT" + }, + "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/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "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, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "10.8.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.1.tgz", + "integrity": "sha512-wqA7W2jbsC/BnV9Iv1UZpKVFkO1AdNoSmYW8NWG4HNOBbkAMvIqDZ27pI2f07dqn583NcIC44ckjAcOXDL1QbQ==", + "dev": true, + "license": "MIT", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.7.0", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.2", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.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", + "minimatch": "^10.2.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "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, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.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==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "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, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.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==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/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, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatbuffers": { + "version": "25.9.23", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz", + "integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/guid-typescript": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz", + "integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.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==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/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, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "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": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "dev": true, + "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-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "dev": true, + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], + "dev": true, + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], + "dev": true, + "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", + "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, + "license": "MIT" + }, + "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", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", + "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "source-map-js": "^1.2.1" + } + }, + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mlly": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", + "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.16.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.3" + } + }, + "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, + "license": "MIT" + }, + "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/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "dev": true, + "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/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/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-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/onnxruntime-common": { + "version": "1.24.3", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.24.3.tgz", + "integrity": "sha512-GeuPZO6U/LBJXvwdaqHbuUmoXiEdeCjWi/EG7Y1HNnDwJYuk6WUbNXpF6luSUY8yASul3cmUlLGrCCL1ZgVXqA==", + "dev": true, + "license": "MIT" + }, + "node_modules/onnxruntime-node": { + "version": "1.24.3", + "resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.24.3.tgz", + "integrity": "sha512-JH7+czbc8ALA819vlTgcV+Q214/+VjGeBHDjX81+ZCD0PCVCIFGFNtT0V4sXG/1JXypKPgScQcB3ij/hk3YnTg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "os": [ + "win32", + "darwin", + "linux" + ], + "dependencies": { + "adm-zip": "^0.5.16", + "global-agent": "^3.0.0", + "onnxruntime-common": "1.24.3" + } + }, + "node_modules/onnxruntime-web": { + "version": "1.26.0-dev.20260416-b7804b056c", + "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.26.0-dev.20260416-b7804b056c.tgz", + "integrity": "sha512-MD6Ss4GSpQBo6zqoJzyT9LRbKYs7x/JVN23FT24EcEvlqF4VuzPOeH6X38orZPKHQDbprn7K+SBpu0/mj2CQiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatbuffers": "^25.1.24", + "guid-typescript": "^1.0.9", + "long": "^5.2.3", + "onnxruntime-common": "1.24.0-dev.20251116-b39e144322", + "platform": "^1.3.6", + "protobufjs": "^7.2.4" + } + }, + "node_modules/onnxruntime-web/node_modules/onnxruntime-common": { + "version": "1.24.0-dev.20251116-b39e144322", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.24.0-dev.20251116-b39e144322.tgz", + "integrity": "sha512-BOoomdHYmNRL5r4iQ4bMvsl2t0/hzVQ3OM3PHD0gxeXu1PmggqBv3puZicEUVOA3AtHHYmqZtjMj9FOfGrATTw==", + "dev": true, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/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.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": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "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" + } + }, + "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/platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "dev": true, + "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.17", + "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", + "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", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz", + "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/protobufjs": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz", + "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", + "dev": true, + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/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/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/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/rolldown": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.4.tgz", + "integrity": "sha512-rSr7irW0K7QRWzjdJXqZowkcRdDtjRduh43rBltnVKd0VFq839l1lJoDvGJb6gl7+4rTTCrPWu+YfujUL8Ug7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.144.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.2.4", + "@rolldown/binding-darwin-arm64": "1.2.4", + "@rolldown/binding-darwin-x64": "1.2.4", + "@rolldown/binding-freebsd-x64": "1.2.4", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.4", + "@rolldown/binding-linux-arm64-gnu": "1.2.4", + "@rolldown/binding-linux-arm64-musl": "1.2.4", + "@rolldown/binding-linux-ppc64-gnu": "1.2.4", + "@rolldown/binding-linux-s390x-gnu": "1.2.4", + "@rolldown/binding-linux-x64-gnu": "1.2.4", + "@rolldown/binding-linux-x64-musl": "1.2.4", + "@rolldown/binding-openharmony-arm64": "1.2.4", + "@rolldown/binding-win32-arm64-msvc": "1.2.4", + "@rolldown/binding-win32-x64-msvc": "1.2.4" + } + }, + "node_modules/rollup": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", + "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", + "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.60.1", + "@rollup/rollup-android-arm64": "4.60.1", + "@rollup/rollup-darwin-arm64": "4.60.1", + "@rollup/rollup-darwin-x64": "4.60.1", + "@rollup/rollup-freebsd-arm64": "4.60.1", + "@rollup/rollup-freebsd-x64": "4.60.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", + "@rollup/rollup-linux-arm-musleabihf": "4.60.1", + "@rollup/rollup-linux-arm64-gnu": "4.60.1", + "@rollup/rollup-linux-arm64-musl": "4.60.1", + "@rollup/rollup-linux-loong64-gnu": "4.60.1", + "@rollup/rollup-linux-loong64-musl": "4.60.1", + "@rollup/rollup-linux-ppc64-gnu": "4.60.1", + "@rollup/rollup-linux-ppc64-musl": "4.60.1", + "@rollup/rollup-linux-riscv64-gnu": "4.60.1", + "@rollup/rollup-linux-riscv64-musl": "4.60.1", + "@rollup/rollup-linux-s390x-gnu": "4.60.1", + "@rollup/rollup-linux-x64-gnu": "4.60.1", + "@rollup/rollup-linux-x64-musl": "4.60.1", + "@rollup/rollup-openbsd-x64": "4.60.1", + "@rollup/rollup-openharmony-arm64": "4.60.1", + "@rollup/rollup-win32-arm64-msvc": "4.60.1", + "@rollup/rollup-win32-ia32-msvc": "4.60.1", + "@rollup/rollup-win32-x64-gnu": "4.60.1", + "@rollup/rollup-win32-x64-msvc": "4.60.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT" + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sharp": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz", + "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.3", + "@img/sharp-darwin-x64": "0.35.3", + "@img/sharp-freebsd-wasm32": "0.35.3", + "@img/sharp-libvips-darwin-arm64": "1.3.2", + "@img/sharp-libvips-darwin-x64": "1.3.2", + "@img/sharp-libvips-linux-arm": "1.3.2", + "@img/sharp-libvips-linux-arm64": "1.3.2", + "@img/sharp-libvips-linux-ppc64": "1.3.2", + "@img/sharp-libvips-linux-riscv64": "1.3.2", + "@img/sharp-libvips-linux-s390x": "1.3.2", + "@img/sharp-libvips-linux-x64": "1.3.2", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", + "@img/sharp-libvips-linuxmusl-x64": "1.3.2", + "@img/sharp-linux-arm": "0.35.3", + "@img/sharp-linux-arm64": "0.35.3", + "@img/sharp-linux-ppc64": "0.35.3", + "@img/sharp-linux-riscv64": "0.35.3", + "@img/sharp-linux-s390x": "0.35.3", + "@img/sharp-linux-x64": "0.35.3", + "@img/sharp-linuxmusl-arm64": "0.35.3", + "@img/sharp-linuxmusl-x64": "0.35.3", + "@img/sharp-webcontainers-wasm32": "0.35.3", + "@img/sharp-win32-arm64": "0.35.3", + "@img/sharp-win32-ia32": "0.35.3", + "@img/sharp-win32-x64": "0.35.3" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "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==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", + "dev": true, + "license": "MIT" + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "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.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", + "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.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.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "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/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.1", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.5.1.tgz", + "integrity": "sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==", + "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.27.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.7.6", + "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/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "dev": true, + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.1.tgz", + "integrity": "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.25", + "rolldown": "~1.2.1", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.4.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitest": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", + "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.10", + "@vitest/mocker": "4.1.10", + "@vitest/pretty-format": "4.1.10", + "@vitest/runner": "4.1.10", + "@vitest/snapshot": "4.1.10", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.10", + "@vitest/browser-preview": "4.1.10", + "@vitest/browser-webdriverio": "4.1.10", + "@vitest/coverage-istanbul": "4.1.10", + "@vitest/coverage-v8": "4.1.10", + "@vitest/ui": "4.1.10", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/vitest/node_modules/tinyexec": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json index b569506..ce16100 100644 --- a/package.json +++ b/package.json @@ -52,9 +52,11 @@ "test": "vitest run", "test:watch": "vitest", "test:coverage": "vitest run --coverage", - "lint": "eslint src/", - "format": "prettier --write 'src/**/*.ts' 'tests/**/*.ts'", - "smoke": "npm run build && node scripts/smoke-test.mjs" + "lint": "eslint src/ tests/ scripts/", + "format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\" \"scripts/**/*.mjs\"", + "format:check": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\" \"scripts/**/*.mjs\"", + "smoke": "npm run build && node scripts/smoke-test.mjs", + "engines:check": "node scripts/engines-check.mjs" }, "license": "Apache-2.0", "peerDependencies": { @@ -65,16 +67,21 @@ "optional": true } }, + "overrides": { + "sharp": "^0.35.3", + "adm-zip": "^0.6.0", + "esbuild": "0.27.2" + }, "devDependencies": { "@huggingface/transformers": "^4.2.0", - "@types/node": "^25.9.1", - "@typescript-eslint/eslint-plugin": "^8.60.0", - "@typescript-eslint/parser": "^8.60.0", - "@vitest/coverage-v8": "^4.1.7", - "eslint": "^10.4.0", - "prettier": "^3.8.3", + "@types/node": "^25.9.5", + "@typescript-eslint/eslint-plugin": "^8.67.0", + "@typescript-eslint/parser": "^8.67.0", + "@vitest/coverage-v8": "^4.1.10", + "eslint": "^10.8.1", + "prettier": "^3.9.6", "tsup": "^8.5.1", - "typescript": "^5.9.3", - "vitest": "^4.1.7" + "typescript": "^6.0.3", + "vitest": "^4.1.10" } } diff --git a/scripts/engines-check.mjs b/scripts/engines-check.mjs new file mode 100644 index 0000000..e0349e6 --- /dev/null +++ b/scripts/engines-check.mjs @@ -0,0 +1,42 @@ +// Verifies the built dist/ actually runs on the oldest Node major that +// package.json's `engines.node` claims to support. +// +// This exists because the dev toolchain (vitest, eslint) requires Node >=20, +// so the CI matrix cannot exercise Node 18 the normal way. Only the published +// artifact needs to work there, and it has no runtime dependencies - so this +// script imports dist/ directly and needs nothing installed. +// +// Run with: node scripts/engines-check.mjs + +import { createRequire } from 'node:module'; +import { readFileSync } from 'node:fs'; +import assert from 'node:assert/strict'; + +const require = createRequire(import.meta.url); +const { engines, version } = JSON.parse(readFileSync('./package.json', 'utf8')); + +const a = [1, 0, 0]; +const b = [0.6, 0.8, 0]; + +function check(label, mod) { + assert.equal(typeof mod.cosineSimilarity, 'function', `${label}: cosineSimilarity missing`); + assert.equal(typeof mod.dotProduct, 'function', `${label}: dotProduct missing`); + assert.equal(typeof mod.topK, 'function', `${label}: topK missing`); + + // 1*0.6 + 0*0.8 + 0*0 = 0.6, and both inputs are unit vectors. + assert.ok(Math.abs(mod.cosineSimilarity(a, b) - 0.6) < 1e-6, `${label}: cosineSimilarity wrong`); + assert.ok(Math.abs(mod.dotProduct(a, b) - 0.6) < 1e-6, `${label}: dotProduct wrong`); + + const ranked = mod.topK(a, [b, [1, 0, 0], [0, 1, 0]], 2); + assert.equal(ranked.length, 2, `${label}: topK returned ${ranked.length} results, expected 2`); + assert.equal(ranked[0].index, 1, `${label}: topK did not rank the identical vector first`); + + console.log(` ok ${label}`); +} + +console.log(`embedding-utils ${version} on Node ${process.version} (engines: ${engines.node})`); + +check('esm (dist/index.js)', await import('../dist/index.js')); +check('cjs (dist/index.cjs)', require('../dist/index.cjs')); + +console.log('All engines checks passed.'); diff --git a/scripts/smoke-test.mjs b/scripts/smoke-test.mjs index 8faefbd..f8a4057 100644 --- a/scripts/smoke-test.mjs +++ b/scripts/smoke-test.mjs @@ -63,20 +63,19 @@ for (const [modelId, precision] of models) { const info = getModelInfo(modelId); const expectedPooling = info?.pooling ?? 'mean'; const expectedDims = info?.dimensions; - const hasPrefixes = - !!info?.prefixes && info.prefixes.document !== info.prefixes.query; + const hasPrefixes = !!info?.prefixes && info.prefixes.document !== info.prefixes.query; console.log( `▶ ${modelId}` + (precision ? ` [${precision}]` : '') + ` (registry: ${expectedDims ?? '?'}d, pooling=${expectedPooling}` + (info ? '' : ', NOT in registry') + - `)`, + `)` ); try { const provider = createLocalProvider( - precision ? { model: modelId, precision } : { model: modelId }, + precision ? { model: modelId, precision } : { model: modelId } ); const docRes = await provider.embed(DOC, { inputType: 'document' }); @@ -87,9 +86,7 @@ for (const [modelId, precision] of models) { if (docRes.dimensions === expectedDims) { pass(`dimensions = ${docRes.dimensions}`); } else { - fail( - `dimensions mismatch: got ${docRes.dimensions}, registry says ${expectedDims}`, - ); + fail(`dimensions mismatch: got ${docRes.dimensions}, registry says ${expectedDims}`); } } else { console.log(` • dimensions = ${docRes.dimensions} (no registry value)`); @@ -108,14 +105,12 @@ for (const [modelId, precision] of models) { // bit-identical vectors for the same input. const reuseStart = Date.now(); const provider2 = createLocalProvider( - precision ? { model: modelId, precision } : { model: modelId }, + precision ? { model: modelId, precision } : { model: modelId } ); const docRes2 = await provider2.embed(DOC, { inputType: 'document' }); const reuseMs = Date.now() - reuseStart; const docVec2 = docRes2.embeddings[0]; - const identical = - docVec2.length === docVec.length && - docVec2.every((v, i) => v === docVec[i]); + const identical = docVec2.length === docVec.length && docVec2.every((v, i) => v === docVec[i]); if (identical) { pass(`shared-pipeline reuse: identical vectors (2nd provider embed took ${reuseMs}ms)`); } else { @@ -132,7 +127,7 @@ for (const [modelId, precision] of models) { const prefixDelta = 1 - cosine(queryRes.embeddings[0], queryAsDoc.embeddings[0]); if (prefixDelta > 1e-4) { pass( - `prefixes applied (query/doc encodings differ by ${prefixDelta.toExponential(2)}; query~doc sim=${sim.toFixed(3)})`, + `prefixes applied (query/doc encodings differ by ${prefixDelta.toExponential(2)}; query~doc sim=${sim.toFixed(3)})` ); } else { fail('prefixes do not appear to be applied (query == doc encoding)'); diff --git a/src/aggregation/average.ts b/src/aggregation/average.ts index 996bf81..7d4cdbd 100644 --- a/src/aggregation/average.ts +++ b/src/aggregation/average.ts @@ -74,7 +74,7 @@ export function weightedAverage(embeddings: Vector[], weights: number[]): Float3 validateEmbeddings(embeddings); if (embeddings.length !== weights.length) { throw new ValidationError( - `Embeddings length (${embeddings.length}) must match weights length (${weights.length})`, + `Embeddings length (${embeddings.length}) must match weights length (${weights.length})` ); } const dim = embeddings[0].length; @@ -117,12 +117,10 @@ export function weightedAverage(embeddings: Vector[], weights: number[]): Float3 export function incrementalAverage( currentAvg: Vector, newEmbedding: Vector, - count: number, + count: number ): Float32Array { if (currentAvg.length !== newEmbedding.length) { - throw new ValidationError( - `Dimension mismatch: ${currentAvg.length} vs ${newEmbedding.length}`, - ); + throw new ValidationError(`Dimension mismatch: ${currentAvg.length} vs ${newEmbedding.length}`); } const dim = currentAvg.length; const result = new Float32Array(dim); @@ -150,7 +148,7 @@ export function incrementalAverage( export function batchIncrementalAverage( currentAvg: Vector, newEmbeddings: Vector[], - count: number, + count: number ): Float32Array { if (newEmbeddings.length === 0) { throw new ValidationError('newEmbeddings array must be non-empty'); @@ -159,7 +157,7 @@ export function batchIncrementalAverage( for (let i = 0; i < newEmbeddings.length; i++) { if (newEmbeddings[i].length !== dim) { throw new ValidationError( - `Dimension mismatch: expected ${dim}, got ${newEmbeddings[i].length} at index ${i}`, + `Dimension mismatch: expected ${dim}, got ${newEmbeddings[i].length} at index ${i}` ); } } diff --git a/src/aggregation/combine.ts b/src/aggregation/combine.ts index def1a42..c1c9f65 100644 --- a/src/aggregation/combine.ts +++ b/src/aggregation/combine.ts @@ -23,7 +23,7 @@ export async function combineEmbeddings( options?: { aggregate?: (embeddings: Vector[]) => Float32Array; embedOptions?: EmbedOptions; - }, + } ): Promise { if (texts.length === 0) { throw new ValidationError('texts array must be non-empty'); diff --git a/src/aggregation/index.ts b/src/aggregation/index.ts index 1408bd8..83c2fe8 100644 --- a/src/aggregation/index.ts +++ b/src/aggregation/index.ts @@ -1,3 +1,9 @@ -export { averageEmbeddings, weightedAverage, incrementalAverage, batchIncrementalAverage, centroid } from './average'; +export { + averageEmbeddings, + weightedAverage, + incrementalAverage, + batchIncrementalAverage, + centroid, +} from './average'; export { maxPooling, minPooling } from './pooling'; export { combineEmbeddings } from './combine'; diff --git a/src/clustering/cluster.ts b/src/clustering/cluster.ts index 07478cd..ac750d3 100644 --- a/src/clustering/cluster.ts +++ b/src/clustering/cluster.ts @@ -15,10 +15,7 @@ const DEFAULT_CONFIG: Required = { shuffleSeed: 42, }; -function findMostSimilarPair( - clusters: Cluster[], - metric: SimilarityMetric, -): [number, number] { +function findMostSimilarPair(clusters: Cluster[], metric: SimilarityMetric): [number, number] { let bestI = 0; let bestJ = 1; let bestSim = -Infinity; @@ -37,9 +34,7 @@ function findMostSimilarPair( function mergeTwoClusters(a: Cluster, b: Cluster, metric: SimilarityMetric): Cluster { const members = [...a.members, ...b.members]; - const labels = a.labels || b.labels - ? [...(a.labels || []), ...(b.labels || [])] - : undefined; + const labels = a.labels || b.labels ? [...(a.labels || []), ...(b.labels || [])] : undefined; return { centroid: computeCentroid(members), members, @@ -60,13 +55,13 @@ function mergeTwoClusters(a: Cluster, b: Cluster, metric: SimilarityMetric): Clu export function clusterEmbeddings( embeddings: Vector[], config?: ClusteringConfig, - labels?: string[], + labels?: string[] ): Cluster[] { if (embeddings.length === 0) return []; if (labels && labels.length !== embeddings.length) { throw new ValidationError( - `Labels length (${labels.length}) must match embeddings length (${embeddings.length})`, + `Labels length (${labels.length}) must match embeddings length (${embeddings.length})` ); } @@ -78,7 +73,15 @@ export function clusterEmbeddings( if (cfg.minClusterSize < 0) { throw new ValidationError(`minClusterSize must be >= 0, got ${cfg.minClusterSize}`); } - const { similarityThreshold, minClusterSize, maxClusters, metric, assignmentStrategy, shuffle, shuffleSeed } = cfg; + const { + similarityThreshold, + minClusterSize, + maxClusters, + metric, + assignmentStrategy, + shuffle, + shuffleSeed, + } = cfg; // Convert all inputs to Float32Array up front const float32Embeddings = embeddings.map((e) => toFloat32(e)); @@ -192,13 +195,15 @@ export function clusterEmbeddings( allLabels.push(...cluster.labels); } } - result = [{ - centroid: computeCentroid(allMembers), - members: allMembers, - labels: hasLabels ? allLabels : undefined, - size: allMembers.length, - cohesion: 1.0, - }]; + result = [ + { + centroid: computeCentroid(allMembers), + members: allMembers, + labels: hasLabels ? allLabels : undefined, + size: allMembers.length, + cohesion: 1.0, + }, + ]; } else { result = []; } diff --git a/src/clustering/hdbscan.ts b/src/clustering/hdbscan.ts index 77bcc92..c7334ec 100644 --- a/src/clustering/hdbscan.ts +++ b/src/clustering/hdbscan.ts @@ -69,9 +69,9 @@ interface MSTEdge { /** An entry in the condensed tree. */ interface CondensedTreeEntry { - parent: number; // condensed cluster ID - child: number; // point index (if childSize===1) or condensed cluster ID - lambda: number; // 1/distance at which this separation happens + parent: number; // condensed cluster ID + child: number; // point index (if childSize===1) or condensed cluster ID + lambda: number; // 1/distance at which this separation happens childSize: number; // 1 for individual point, >1 for sub-cluster } @@ -107,7 +107,11 @@ function computeDistanceMatrix(embeddings: Vector[], distFn: DistanceFn): Float6 return matrix; } -function computeCoreDistances(distMatrix: Float64Array, n: number, minSamples: number): Float64Array { +function computeCoreDistances( + distMatrix: Float64Array, + n: number, + minSamples: number +): Float64Array { const coreDistances = new Float64Array(n); const k = Math.min(minSamples, n - 1); @@ -125,7 +129,7 @@ function computeCoreDistances(distMatrix: Float64Array, n: number, minSamples: n function computeMutualReachabilityMatrix( distMatrix: Float64Array, coreDistances: Float64Array, - n: number, + n: number ): Float64Array { const mrd = new Float64Array(n * n); for (let i = 0; i < n; i++) { @@ -231,7 +235,7 @@ class UnionFind { function buildCondensedTree( edges: MSTEdge[], n: number, - minClusterSize: number, + minClusterSize: number ): CondensedTreeEntry[] { // Step 1: Build single-linkage hierarchy const uf = new UnionFind(n); @@ -331,9 +335,7 @@ function buildCondensedTree( * * Returns the set of point indices for each selected cluster. */ -function extractClusters( - condensedTree: CondensedTreeEntry[], -): number[][] { +function extractClusters(condensedTree: CondensedTreeEntry[]): number[][] { if (condensedTree.length === 0) return []; // Identify all condensed cluster IDs @@ -508,7 +510,7 @@ export function hdbscan(embeddings: Vector[], options: HDBSCANOptions = {}): HDB // Validate labels length if (inputLabels && inputLabels.length !== embeddings.length) { throw new ValidationError( - `Labels length (${inputLabels.length}) must match embeddings length (${embeddings.length})`, + `Labels length (${inputLabels.length}) must match embeddings length (${embeddings.length})` ); } diff --git a/src/clustering/metrics.ts b/src/clustering/metrics.ts index 3d49a38..bc3a749 100644 --- a/src/clustering/metrics.ts +++ b/src/clustering/metrics.ts @@ -29,10 +29,7 @@ import { computePairwiseCohesion } from '../internal/clustering'; * const quality = cohesionScore(cluster); * if (quality < 0.7) console.warn('Cluster is loosely grouped'); */ -export function cohesionScore( - cluster: Cluster, - metric: SimilarityMetric = 'cosine', -): number { +export function cohesionScore(cluster: Cluster, metric: SimilarityMetric = 'cosine'): number { return computePairwiseCohesion(cluster.members, metric); } @@ -66,10 +63,7 @@ export function cohesionScore( * if (quality < 0.7) console.warn('Loose cluster detected'); * } */ -export function centroidCohesion( - cluster: Cluster, - metric: SimilarityMetric = 'cosine', -): number { +export function centroidCohesion(cluster: Cluster, metric: SimilarityMetric = 'cosine'): number { if (cluster.members.length <= 1) return 1.0; let totalSim = 0; @@ -115,10 +109,7 @@ export function centroidCohesion( * console.log(`threshold=${threshold}: silhouette=${silhouetteScore(clusters).toFixed(3)}`); * } */ -export function silhouetteScore( - clusters: Cluster[], - metric: SimilarityMetric = 'cosine', -): number { +export function silhouetteScore(clusters: Cluster[], metric: SimilarityMetric = 'cosine'): number { if (clusters.length <= 1) return 0; let totalSilhouette = 0; diff --git a/src/clustering/operations.ts b/src/clustering/operations.ts index d3090cc..f6d99cf 100644 --- a/src/clustering/operations.ts +++ b/src/clustering/operations.ts @@ -48,7 +48,7 @@ import { computeCentroid, computePairwiseCohesion } from '../internal/clustering export function assignToCluster( embedding: Vector, clusters: Cluster[], - options?: { metric?: SimilarityMetric; threshold?: number }, + options?: { metric?: SimilarityMetric; threshold?: number } ): { clusterIndex: number; similarity: number } { const metric = options?.metric ?? 'cosine'; const threshold = options?.threshold ?? 0; @@ -97,13 +97,10 @@ export function assignToCluster( export function mergeClusters( a: Cluster, b: Cluster, - metric: SimilarityMetric = 'cosine', + metric: SimilarityMetric = 'cosine' ): Cluster { const members = [...a.members, ...b.members]; - const labels = - a.labels || b.labels - ? [...(a.labels || []), ...(b.labels || [])] - : undefined; + const labels = a.labels || b.labels ? [...(a.labels || []), ...(b.labels || [])] : undefined; return { centroid: computeCentroid(members), diff --git a/src/clustering/optimal.ts b/src/clustering/optimal.ts index 3972ea4..b186e03 100644 --- a/src/clustering/optimal.ts +++ b/src/clustering/optimal.ts @@ -17,7 +17,7 @@ function meanSilhouette( embeddings: Vector[], assignments: number[], k: number, - metric: SimilarityMetric, + metric: SimilarityMetric ): number { if (k <= 1) return 0; @@ -71,7 +71,7 @@ function withinClusterSumOfDistances( embeddings: Vector[], assignments: number[], k: number, - metric: SimilarityMetric, + metric: SimilarityMetric ): number { // Compute centroid for each cluster const clusterMembers: Vector[][] = Array.from({ length: k }, () => []); @@ -93,19 +93,19 @@ function withinClusterSumOfDistances( /** * Runs clustering for a given k and returns flat assignment array. */ -function clusterAndAssign( - embeddings: Vector[], - k: number, - metric: SimilarityMetric, -): number[] { +function clusterAndAssign(embeddings: Vector[], k: number, metric: SimilarityMetric): number[] { // Use labels to track original indices through clustering const indexLabels = embeddings.map((_, i) => String(i)); - const clusters = clusterEmbeddings(embeddings, { - maxClusters: k, - minClusterSize: 1, - similarityThreshold: 0, - metric, - }, indexLabels); + const clusters = clusterEmbeddings( + embeddings, + { + maxClusters: k, + minClusterSize: 1, + similarityThreshold: 0, + metric, + }, + indexLabels + ); // Build assignment map using labels (original indices) const assignments = new Array(embeddings.length).fill(0); @@ -133,10 +133,7 @@ function clusterAndAssign( * @param options - Configuration: minK, maxK, metric, method * @returns The optimal k value */ -export function findOptimalK( - embeddings: Vector[], - options?: OptimalKOptions, -): number { +export function findOptimalK(embeddings: Vector[], options?: OptimalKOptions): number { const method = options?.method ?? 'silhouette'; const metric = options?.metric ?? 'cosine'; const minK = options?.minK ?? 2; @@ -196,7 +193,7 @@ export function findOptimalK( */ export function silhouetteByK( embeddings: Vector[], - options?: Omit, + options?: Omit ): Array<{ k: number; silhouette: number }> { const metric = options?.metric ?? 'cosine'; const minK = options?.minK ?? 2; diff --git a/src/clustering/presets.ts b/src/clustering/presets.ts index f72cbc2..9cada04 100644 --- a/src/clustering/presets.ts +++ b/src/clustering/presets.ts @@ -67,7 +67,7 @@ export const CLUSTERING_PRESETS = { * const clusters = clusterEmbeddings(embeddings, getPreset('legacy')); */ export function getPreset( - name: 'high-precision' | 'balanced' | 'performance' | 'legacy', + name: 'high-precision' | 'balanced' | 'performance' | 'legacy' ): ClusteringConfig { switch (name) { case 'high-precision': diff --git a/src/clustering/statistics.ts b/src/clustering/statistics.ts index 109db81..1bc884c 100644 --- a/src/clustering/statistics.ts +++ b/src/clustering/statistics.ts @@ -10,7 +10,7 @@ import { computeScore, computeDistance } from '../internal/metrics'; */ export function clusterStats( cluster: { centroid: Vector; members: Vector[] }, - metric: SimilarityMetric = 'cosine', + metric: SimilarityMetric = 'cosine' ): ClusterStats { const { centroid, members } = cluster; @@ -65,7 +65,7 @@ export function clusterStats( */ export function detectOutliers( cluster: { centroid: Vector; members: Vector[] }, - options?: { threshold?: number; metric?: SimilarityMetric }, + options?: { threshold?: number; metric?: SimilarityMetric } ): number[] { const metric = options?.metric ?? 'cosine'; const threshold = options?.threshold ?? 2; @@ -100,7 +100,7 @@ export function detectOutliers( export function centroidDrift( oldCentroid: Vector, newCentroid: Vector, - metric: SimilarityMetric = 'cosine', + metric: SimilarityMetric = 'cosine' ): number { return computeDistance(oldCentroid, newCentroid, metric); } diff --git a/src/eval/metrics.ts b/src/eval/metrics.ts index fbd4af5..86b6db5 100644 --- a/src/eval/metrics.ts +++ b/src/eval/metrics.ts @@ -16,7 +16,7 @@ export function recallAtK( retrieved: string[], relevant: Set | string[], - k?: number, + k?: number ): number { const relevantSet = relevant instanceof Set ? relevant : new Set(relevant); if (relevantSet.size === 0 || retrieved.length === 0) return 0; @@ -43,7 +43,7 @@ export function recallAtK( export function ndcg( retrieved: string[], relevanceScores: Map | Record, - k?: number, + k?: number ): number { if (retrieved.length === 0) return 0; @@ -87,10 +87,7 @@ export function ndcg( * @param relevant - Set or array of relevant item identifiers * @returns MRR score in [0, 1] */ -export function mrr( - retrieved: string[], - relevant: Set | string[], -): number { +export function mrr(retrieved: string[], relevant: Set | string[]): number { const relevantSet = relevant instanceof Set ? relevant : new Set(relevant); if (relevantSet.size === 0 || retrieved.length === 0) return 0; @@ -113,7 +110,7 @@ export function mrr( */ export function meanAveragePrecision( retrieved: string[], - relevant: Set | string[], + relevant: Set | string[] ): number { const relevantSet = relevant instanceof Set ? relevant : new Set(relevant); if (relevantSet.size === 0 || retrieved.length === 0) return 0; diff --git a/src/internal/clustering.ts b/src/internal/clustering.ts index fdcd37a..1f966f7 100644 --- a/src/internal/clustering.ts +++ b/src/internal/clustering.ts @@ -23,10 +23,7 @@ export function computeCentroid(members: Vector[]): Float32Array { * Computes the average pairwise similarity among members. * @internal */ -export function computePairwiseCohesion( - members: Vector[], - metric: SimilarityMetric, -): number { +export function computePairwiseCohesion(members: Vector[], metric: SimilarityMetric): number { if (members.length <= 1) return 1.0; let totalSim = 0; let pairs = 0; diff --git a/src/internal/concurrency.ts b/src/internal/concurrency.ts index 8474a80..a05d596 100644 --- a/src/internal/concurrency.ts +++ b/src/internal/concurrency.ts @@ -9,7 +9,7 @@ */ export async function promisePool( tasks: Array<() => Promise>, - maxConcurrency: number, + maxConcurrency: number ): Promise { const results = new Array(tasks.length); let nextIndex = 0; @@ -27,10 +27,7 @@ export async function promisePool( } } - const workers = Array.from( - { length: Math.min(maxConcurrency, tasks.length) }, - () => runNext(), - ); + const workers = Array.from({ length: Math.min(maxConcurrency, tasks.length) }, () => runNext()); await Promise.all(workers); return results; diff --git a/src/internal/metrics.ts b/src/internal/metrics.ts index 52ea1db..6f969ff 100644 --- a/src/internal/metrics.ts +++ b/src/internal/metrics.ts @@ -20,7 +20,7 @@ export function computeScore(a: Vector, b: Vector, metric: SimilarityMetric): nu case 'manhattan': return 1 / (1 + manhattanDistance(a, b)); default: - throw new ValidationError(`Unknown similarity metric: ${(metric as string)}`); + throw new ValidationError(`Unknown similarity metric: ${metric as string}`); } } @@ -41,6 +41,6 @@ export function computeDistance(a: Vector, b: Vector, metric: SimilarityMetric): case 'manhattan': return manhattanDistance(a, b); default: - throw new ValidationError(`Unknown similarity metric: ${(metric as string)}`); + throw new ValidationError(`Unknown similarity metric: ${metric as string}`); } } diff --git a/src/internal/validation.ts b/src/internal/validation.ts index 28c0382..a290ffb 100644 --- a/src/internal/validation.ts +++ b/src/internal/validation.ts @@ -41,14 +41,14 @@ export function validateVectorPair( a: Vector, b: Vector, nameA = 'Vector A', - nameB = 'Vector B', + nameB = 'Vector B' ): void { if (a.length === 0 || b.length === 0) { throw new ValidationError('Vectors must be non-empty'); } if (a.length !== b.length) { throw new DimensionMismatchError( - `Dimension mismatch: ${nameA} has ${a.length} dimensions, ${nameB} has ${b.length}`, + `Dimension mismatch: ${nameA} has ${a.length} dimensions, ${nameB} has ${b.length}` ); } } @@ -65,7 +65,7 @@ export function validateEmbeddings(embeddings: Vector[], name = 'Embeddings'): v for (let i = 1; i < embeddings.length; i++) { if (embeddings[i].length !== dim) { throw new DimensionMismatchError( - `Dimension mismatch: expected ${dim}, got ${embeddings[i].length} at index ${i}`, + `Dimension mismatch: expected ${dim}, got ${embeddings[i].length} at index ${i}` ); } } diff --git a/src/math/dimensions.ts b/src/math/dimensions.ts index 55fde75..ad9385d 100644 --- a/src/math/dimensions.ts +++ b/src/math/dimensions.ts @@ -52,7 +52,11 @@ export function truncateDimensions( } // Check if input is a batch (array of vectors) - if (Array.isArray(input) && input.length > 0 && (Array.isArray(input[0]) || input[0] instanceof Float32Array)) { + if ( + Array.isArray(input) && + input.length > 0 && + (Array.isArray(input[0]) || input[0] instanceof Float32Array) + ) { const batch = input as Vector[]; return batch.map((v) => truncateSingle(v, targetDims)); } @@ -62,9 +66,7 @@ export function truncateDimensions( function truncateSingle(v: Vector, targetDims: number): Float32Array { if (targetDims > v.length) { - throw new ValidationError( - `targetDims (${targetDims}) exceeds vector length (${v.length})` - ); + throw new ValidationError(`targetDims (${targetDims}) exceeds vector length (${v.length})`); } let result: Float32Array; if (v instanceof Float32Array) { @@ -92,7 +94,7 @@ function truncateSingle(v: Vector, targetDims: number): Float32Array { */ export function validateDimensions( embeddings: Vector[], - expectedDim?: number, + expectedDim?: number ): { valid: boolean; dimension: number; mismatches: number[] } { if (embeddings.length === 0) { return { valid: true, dimension: expectedDim ?? 0, mismatches: [] }; diff --git a/src/math/projection.ts b/src/math/projection.ts index 0b90640..97a30c0 100644 --- a/src/math/projection.ts +++ b/src/math/projection.ts @@ -52,11 +52,11 @@ function gaussianRandom(rng: () => number): number { export function createRandomProjection( sourceDims: number, targetDims: number, - options?: { seed?: number }, + options?: { seed?: number } ): RandomProjector { if (targetDims > sourceDims) { throw new ValidationError( - `targetDims (${targetDims}) must not exceed sourceDims (${sourceDims})`, + `targetDims (${targetDims}) must not exceed sourceDims (${sourceDims})` ); } if (sourceDims <= 0 || targetDims <= 0) { diff --git a/src/models/manager.ts b/src/models/manager.ts index f0acc22..addd14e 100644 --- a/src/models/manager.ts +++ b/src/models/manager.ts @@ -49,7 +49,7 @@ export function getModelInfo(modelId: string): ModelInfo | undefined { */ export async function downloadModel( modelId: string, - options?: { cacheDir?: string }, + options?: { cacheDir?: string } ): Promise { const transformers = await import('@huggingface/transformers'); const cacheDir = options?.cacheDir ?? getDefaultCacheDir(); @@ -108,10 +108,7 @@ export async function listModels(cacheDir?: string): Promise { * @example * await deleteModel('Xenova/all-MiniLM-L6-v2'); */ -export async function deleteModel( - modelId: string, - cacheDir?: string, -): Promise { +export async function deleteModel(modelId: string, cacheDir?: string): Promise { const fs = await import('node:fs/promises'); const path = await import('node:path'); const dir = cacheDir ?? getDefaultCacheDir(); diff --git a/src/models/registry.ts b/src/models/registry.ts index c911f9c..bd29196 100644 --- a/src/models/registry.ts +++ b/src/models/registry.ts @@ -102,8 +102,7 @@ export const MODEL_REGISTRY: Record = { id: 'onnx-community/gte-multilingual-base', dimensions: 768, maxTokens: 8192, - description: - 'GTE multilingual base (70+ languages), long-context, Matryoshka-truncatable', + description: 'GTE multilingual base (70+ languages), long-context, Matryoshka-truncatable', size: '305M', pooling: 'cls', }, @@ -298,10 +297,7 @@ export const MODEL_REGISTRY: Record = { * @example * registerModel({ id: 'my-org/custom-model', dimensions: 512, maxTokens: 1024, description: 'Custom model' }); */ -export function registerModel( - info: ModelInfo, - options?: { overwrite?: boolean }, -): void { +export function registerModel(info: ModelInfo, options?: { overwrite?: boolean }): void { if (!info.id || typeof info.id !== 'string') { throw new ValidationError('Model id must be a non-empty string'); } @@ -310,7 +306,7 @@ export function registerModel( } if (MODEL_REGISTRY[info.id] && !options?.overwrite) { throw new ValidationError( - `Model "${info.id}" is already registered. Pass { overwrite: true } to replace it.`, + `Model "${info.id}" is already registered. Pass { overwrite: true } to replace it.` ); } MODEL_REGISTRY[info.id] = info; @@ -326,7 +322,7 @@ export function registerModel( * getRecommendedModel('multilingual'); // multilingual-MiniLM-L12-v2 */ export function getRecommendedModel( - useCase: 'speed' | 'balanced' | 'quality' | 'multilingual', + useCase: 'speed' | 'balanced' | 'quality' | 'multilingual' ): ModelInfo { switch (useCase) { case 'speed': diff --git a/src/pipeline/pipeline.ts b/src/pipeline/pipeline.ts index dadfaa1..710397f 100644 --- a/src/pipeline/pipeline.ts +++ b/src/pipeline/pipeline.ts @@ -83,7 +83,7 @@ class Semaphore { */ export function createEmbeddingPipeline( provider: EmbeddingProvider, - options: PipelineOptions = {}, + options: PipelineOptions = {} ): EmbeddingPipeline { const { batchSize = 100, @@ -207,7 +207,7 @@ export function createEmbeddingPipeline( async function saveCheckpoint( checkpoint: CheckpointAdapter, completedIds: Set, - totalProcessed: number, + totalProcessed: number ): Promise { await checkpoint.save({ completedIds: [...completedIds], diff --git a/src/pipeline/rate-limiter.ts b/src/pipeline/rate-limiter.ts index b6474cc..d85cf19 100644 --- a/src/pipeline/rate-limiter.ts +++ b/src/pipeline/rate-limiter.ts @@ -52,12 +52,9 @@ export class TokenBucketRateLimiter { this.requestTokens = Math.min( this.maxRequests, - this.requestTokens + this.maxRequests * fraction, - ); - this.tokenBucket = Math.min( - this.maxTokens, - this.tokenBucket + this.maxTokens * fraction, + this.requestTokens + this.maxRequests * fraction ); + this.tokenBucket = Math.min(this.maxTokens, this.tokenBucket + this.maxTokens * fraction); this.lastRefill = now; } diff --git a/src/providers/cohere.ts b/src/providers/cohere.ts index 19cae1e..6be6862 100644 --- a/src/providers/cohere.ts +++ b/src/providers/cohere.ts @@ -1,9 +1,4 @@ -import type { - EmbeddingProvider, - EmbeddingResult, - EmbedOptions, - CohereConfig, -} from '../types'; +import type { EmbeddingProvider, EmbeddingResult, EmbedOptions, CohereConfig } from '../types'; import { ProviderError, ValidationError } from '../types'; import { toFloat32 } from '../internal/vector-utils'; import { retryWithBackoff, autoBatch, createTimeoutSignal, wrapTimeoutError } from './shared'; @@ -33,7 +28,7 @@ export function createCohereProvider(config: CohereConfig): EmbeddingProvider { async function embedBatch( batch: string[], inputType: string, - signal?: AbortSignal, + signal?: AbortSignal ): Promise<{ embeddings: number[][]; tokens: number }> { const fetchSignal = createTimeoutSignal(config.timeout, signal); const result = await retryWithBackoff( @@ -60,32 +55,21 @@ export function createCohereProvider(config: CohereConfig): EmbeddingProvider { } catch { body = response.statusText; } - throw new ProviderError( - `HTTP ${response.status}: ${body}`, - 'cohere', - response.status, - ); + throw new ProviderError(`HTTP ${response.status}: ${body}`, 'cohere', response.status); } try { - return await response.json() as CohereEmbeddingResponse; + return (await response.json()) as CohereEmbeddingResponse; } catch { - throw new ProviderError( - 'Failed to parse API response', - 'cohere', - response.status, - ); + throw new ProviderError('Failed to parse API response', 'cohere', response.status); } }, retryConfig, - signal, + signal ); if (!result.embeddings?.float || !Array.isArray(result.embeddings.float)) { - throw new ProviderError( - 'Unexpected API response structure from cohere', - 'cohere', - ); + throw new ProviderError('Unexpected API response structure from cohere', 'cohere'); } const embeddings = result.embeddings.float; @@ -97,10 +81,7 @@ export function createCohereProvider(config: CohereConfig): EmbeddingProvider { name: 'cohere', dimensions: config.dimensions ?? null, - async embed( - input: string | string[], - options?: EmbedOptions, - ): Promise { + async embed(input: string | string[], options?: EmbedOptions): Promise { const inputs = Array.isArray(input) ? input : [input]; for (const text of inputs) { if (text.trim().length === 0) { diff --git a/src/providers/factory.ts b/src/providers/factory.ts index eab2284..fd6c28a 100644 --- a/src/providers/factory.ts +++ b/src/providers/factory.ts @@ -32,7 +32,7 @@ const ALIAS_BASE_URLS: Record = { */ export function createProvider( type: T, - config: ProviderConfigMap[T], + config: ProviderConfigMap[T] ): EmbeddingProvider { switch (type) { case 'local': diff --git a/src/providers/google.ts b/src/providers/google.ts index 053acb7..decc75e 100644 --- a/src/providers/google.ts +++ b/src/providers/google.ts @@ -23,9 +23,7 @@ const MAX_BATCH_SIZE = 5; * }); * const result = await provider.embed('hello world'); */ -export function createGoogleVertexProvider( - config: GoogleVertexConfig, -): EmbeddingProvider { +export function createGoogleVertexProvider(config: GoogleVertexConfig): EmbeddingProvider { const location = config.location ?? DEFAULT_LOCATION; const model = config.model ?? DEFAULT_MODEL; const retryConfig = config.retry ?? { maxRetries: 3, baseDelay: 1000, maxDelay: 30000 }; @@ -41,7 +39,7 @@ export function createGoogleVertexProvider( async function embedBatch( batch: string[], - signal?: AbortSignal, + signal?: AbortSignal ): Promise<{ embeddings: number[][] }> { const token = await resolveToken(); const fetchSignal = createTimeoutSignal(config.timeout, signal); @@ -70,34 +68,28 @@ export function createGoogleVertexProvider( throw new ProviderError( `HTTP ${response.status}: ${body}`, 'google-vertex', - response.status, + response.status ); } try { - return await response.json() as GoogleVertexEmbeddingResponse; + return (await response.json()) as GoogleVertexEmbeddingResponse; } catch { - throw new ProviderError( - 'Failed to parse API response', - 'google-vertex', - response.status, - ); + throw new ProviderError('Failed to parse API response', 'google-vertex', response.status); } }, retryConfig, - signal, + signal ); if (!Array.isArray(result.predictions) || !result.predictions[0]?.embeddings?.values) { throw new ProviderError( 'Unexpected API response structure from google-vertex', - 'google-vertex', + 'google-vertex' ); } - const embeddings = result.predictions.map( - (p) => p.embeddings.values, - ); + const embeddings = result.predictions.map((p) => p.embeddings.values); return { embeddings }; } @@ -105,10 +97,7 @@ export function createGoogleVertexProvider( name: 'google-vertex', dimensions: config.retry ? null : null, - async embed( - input: string | string[], - options?: EmbedOptions, - ): Promise { + async embed(input: string | string[], options?: EmbedOptions): Promise { const inputs = Array.isArray(input) ? input : [input]; for (const text of inputs) { if (text.trim().length === 0) { diff --git a/src/providers/middleware.ts b/src/providers/middleware.ts index 7b68332..9ed24cd 100644 --- a/src/providers/middleware.ts +++ b/src/providers/middleware.ts @@ -8,10 +8,7 @@ import { createLRUCache } from '../storage/cache'; * @param options - Cache configuration (maxSize, ttl, hashFunction) * @returns A new EmbeddingProvider that caches results from the wrapped provider */ -export function withCache( - provider: EmbeddingProvider, - options?: CacheOptions, -): EmbeddingProvider { +export function withCache(provider: EmbeddingProvider, options?: CacheOptions): EmbeddingProvider { const cache = createLRUCache({ maxSize: options?.maxSize ?? 1000, ttl: options?.ttl, @@ -31,10 +28,7 @@ export function withCache( name: provider.name, dimensions: provider.dimensions, - async embed( - input: string | string[], - options?: EmbedOptions, - ): Promise { + async embed(input: string | string[], options?: EmbedOptions): Promise { const inputs = Array.isArray(input) ? input : [input]; const key = buildKey(inputs, options?.dimensions); diff --git a/src/providers/openai-compatible.ts b/src/providers/openai-compatible.ts index bc19d4e..8f7a17a 100644 --- a/src/providers/openai-compatible.ts +++ b/src/providers/openai-compatible.ts @@ -33,9 +33,7 @@ function extractProviderName(baseUrl: string): string { * }); * const result = await provider.embed(['hello', 'world']); */ -export function createOpenAICompatibleProvider( - config: OpenAICompatibleConfig, -): EmbeddingProvider { +export function createOpenAICompatibleProvider(config: OpenAICompatibleConfig): EmbeddingProvider { const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL; const maxBatchSize = config.maxBatchSize ?? DEFAULT_MAX_BATCH_SIZE; const retryConfig = config.retry ?? { maxRetries: 3, baseDelay: 1000, maxDelay: 30000 }; @@ -44,7 +42,7 @@ export function createOpenAICompatibleProvider( async function embedBatch( batch: string[], - signal?: AbortSignal, + signal?: AbortSignal ): Promise<{ embeddings: number[][]; tokens: number }> { const fetchSignal = createTimeoutSignal(config.timeout, signal); const result = await retryWithBackoff( @@ -77,28 +75,24 @@ export function createOpenAICompatibleProvider( throw new ProviderError( `HTTP ${response.status}: ${body}`, providerName, - response.status, + response.status ); } try { - return await response.json() as OpenAIEmbeddingResponse; + return (await response.json()) as OpenAIEmbeddingResponse; } catch { - throw new ProviderError( - 'Failed to parse API response', - providerName, - response.status, - ); + throw new ProviderError('Failed to parse API response', providerName, response.status); } }, retryConfig, - signal, + signal ); if (!Array.isArray(result.data) || !result.data[0]?.embedding) { throw new ProviderError( 'Unexpected API response structure from openai-compatible', - providerName, + providerName ); } @@ -111,10 +105,7 @@ export function createOpenAICompatibleProvider( name: providerName, dimensions: config.dimensions ?? null, - async embed( - input: string | string[], - options?: EmbedOptions, - ): Promise { + async embed(input: string | string[], options?: EmbedOptions): Promise { const inputs = Array.isArray(input) ? input : [input]; for (const text of inputs) { if (text.trim().length === 0) { diff --git a/src/providers/shared.ts b/src/providers/shared.ts index 39f8a5e..3dbe259 100644 --- a/src/providers/shared.ts +++ b/src/providers/shared.ts @@ -10,7 +10,7 @@ const DEFAULT_TIMEOUT = 30000; */ export function createTimeoutSignal( timeoutMs: number | undefined, - userSignal?: AbortSignal, + userSignal?: AbortSignal ): AbortSignal { const timeout = timeoutMs ?? DEFAULT_TIMEOUT; const timeoutSignal = AbortSignal.timeout(timeout); @@ -25,15 +25,11 @@ export function createTimeoutSignal( * Wraps a provider operation and converts timeout DOMException into ProviderError. * @internal */ -export function wrapTimeoutError( - error: unknown, - providerName: string, - timeoutMs?: number, -): never { +export function wrapTimeoutError(error: unknown, providerName: string, timeoutMs?: number): never { if (error instanceof DOMException && error.name === 'TimeoutError') { throw new ProviderError( `Request timed out after ${timeoutMs ?? DEFAULT_TIMEOUT}ms`, - providerName, + providerName ); } throw error; @@ -59,7 +55,7 @@ function isRetryable(error: unknown): boolean { export async function retryWithBackoff( fn: () => Promise, config: RetryConfig, - signal?: AbortSignal, + signal?: AbortSignal ): Promise { const maxRetries = config.maxRetries ?? 3; const baseDelay = config.baseDelay ?? 1000; @@ -114,7 +110,7 @@ export async function autoBatch( inputs: string[], batchSize: number, fn: (batch: string[]) => Promise, - config?: BatchConfig, + config?: BatchConfig ): Promise { if (inputs.length === 0) return []; diff --git a/src/quantization/calibration.ts b/src/quantization/calibration.ts index bf553bd..713c415 100644 --- a/src/quantization/calibration.ts +++ b/src/quantization/calibration.ts @@ -68,12 +68,12 @@ export function calibrate(embeddings: Vector[]): QuantizationCalibration { */ export function calibratedQuantize( embedding: Vector, - calibration: QuantizationCalibration, + calibration: QuantizationCalibration ): Uint8Array { const v = toFloat32(embedding); if (v.length !== calibration.dimensions) { throw new ValidationError( - `Embedding dimensions (${v.length}) do not match calibration dimensions (${calibration.dimensions})`, + `Embedding dimensions (${v.length}) do not match calibration dimensions (${calibration.dimensions})` ); } @@ -100,11 +100,11 @@ export function calibratedQuantize( */ export function calibratedDequantize( data: Uint8Array, - calibration: QuantizationCalibration, + calibration: QuantizationCalibration ): Float32Array { if (data.length !== calibration.dimensions) { throw new ValidationError( - `Data dimensions (${data.length}) do not match calibration dimensions (${calibration.dimensions})`, + `Data dimensions (${data.length}) do not match calibration dimensions (${calibration.dimensions})` ); } diff --git a/src/quantization/hamming.ts b/src/quantization/hamming.ts index 0c6c630..210819b 100644 --- a/src/quantization/hamming.ts +++ b/src/quantization/hamming.ts @@ -19,9 +19,7 @@ for (let i = 0; i < 256; i++) { */ export function hammingDistance(a: Uint8Array, b: Uint8Array): number { if (a.length !== b.length) { - throw new ValidationError( - `Vector length mismatch: ${a.length} vs ${b.length}`, - ); + throw new ValidationError(`Vector length mismatch: ${a.length} vs ${b.length}`); } let distance = 0; for (let i = 0; i < a.length; i++) { @@ -42,10 +40,6 @@ export function hammingDistance(a: Uint8Array, b: Uint8Array): number { * @returns Similarity in range [0, 1] * @throws {ValidationError} If vectors have different lengths */ -export function hammingSimilarity( - a: Uint8Array, - b: Uint8Array, - dimensions: number, -): number { +export function hammingSimilarity(a: Uint8Array, b: Uint8Array, dimensions: number): number { return 1 - hammingDistance(a, b) / dimensions; } diff --git a/src/quantization/info.ts b/src/quantization/info.ts index 5f28dff..ba714b9 100644 --- a/src/quantization/info.ts +++ b/src/quantization/info.ts @@ -14,7 +14,7 @@ type QuantizationType = 'fp16' | 'int8' | 'uint8' | 'binary'; export function estimateMemorySavings( dimensions: number, count: number, - quantizationType: QuantizationType, + quantizationType: QuantizationType ): { originalBytes: number; quantizedBytes: number; diff --git a/src/quantization/quantize.ts b/src/quantization/quantize.ts index 171c09d..c370d70 100644 --- a/src/quantization/quantize.ts +++ b/src/quantization/quantize.ts @@ -85,7 +85,7 @@ export function quantize(embedding: Vector, type: 'uint8'): Uint8Array; export function quantize(embedding: Vector, type: 'binary'): Uint8Array; export function quantize( embedding: Vector, - type: QuantizationType, + type: QuantizationType ): Float32Array | Int8Array | Uint8Array { switch (type) { case 'fp16': { @@ -138,14 +138,26 @@ export function quantize( * @example * dequantize(new Int8Array([64, -38, 102]), 'int8'); // [0.504, -0.299, 0.803] */ -export function dequantize(data: Float32Array, type: 'fp16', originalDimension?: number): Float32Array; +export function dequantize( + data: Float32Array, + type: 'fp16', + originalDimension?: number +): Float32Array; export function dequantize(data: Int8Array, type: 'int8', originalDimension?: number): Float32Array; -export function dequantize(data: Uint8Array, type: 'uint8', originalDimension?: number): Float32Array; -export function dequantize(data: Uint8Array, type: 'binary', originalDimension?: number): Float32Array; +export function dequantize( + data: Uint8Array, + type: 'uint8', + originalDimension?: number +): Float32Array; +export function dequantize( + data: Uint8Array, + type: 'binary', + originalDimension?: number +): Float32Array; export function dequantize( data: Float32Array | Int8Array | Uint8Array, type: QuantizationType, - originalDimension?: number, + originalDimension?: number ): Float32Array { switch (type) { case 'fp16': { diff --git a/src/search/fusion.ts b/src/search/fusion.ts index 0c40f1c..7c89b12 100644 --- a/src/search/fusion.ts +++ b/src/search/fusion.ts @@ -13,10 +13,7 @@ import { ValidationError } from '../types'; * @returns Merged list sorted by fused RRF score descending * @throws {ValidationError} If lists is empty array of non-arrays */ -export function fuseRankedLists( - lists: RankedItem[][], - options?: { k?: number }, -): RankedItem[] { +export function fuseRankedLists(lists: RankedItem[][], options?: { k?: number }): RankedItem[] { if (lists.length === 0) return []; const k = options?.k ?? 60; diff --git a/src/search/hnsw.ts b/src/search/hnsw.ts index 5fc3617..72a2837 100644 --- a/src/search/hnsw.ts +++ b/src/search/hnsw.ts @@ -226,10 +226,7 @@ export class HNSWIndex { } /** Search for the most similar items to a query vector. */ - search( - query: Vector, - options?: HNSWSearchOptions, - ): Array { + search(query: Vector, options?: HNSWSearchOptions): Array { const topK = options?.topK ?? 10; const efSearch = options?.efSearch ?? 50; const filter = options?.filter; @@ -353,11 +350,15 @@ export class HNSWIndex { } const nodeSize = - 4 + idBytes.length + // id - 4 + metaBytes.length + // metadata - 4 + vectorBytes + // vector + 4 + + idBytes.length + // id + 4 + + metaBytes.length + // metadata + 4 + + vectorBytes + // vector 4 + // level - 4 + layerByteLen; // layers + 4 + + layerByteLen; // layers const buf = new ArrayBuffer(nodeSize); const view = new DataView(buf); @@ -380,7 +381,9 @@ export class HNSWIndex { // Vector view.setUint32(offset, vectorBytes, true); offset += 4; - new Uint8Array(buf, offset, vectorBytes).set(new Uint8Array(node.vector.buffer, node.vector.byteOffset, vectorBytes)); + new Uint8Array(buf, offset, vectorBytes).set( + new Uint8Array(node.vector.buffer, node.vector.byteOffset, vectorBytes) + ); offset += vectorBytes; // Level @@ -591,7 +594,7 @@ export class HNSWIndex { query: Float32Array, entryPointIdx: number, ef: number, - layer: number, + layer: number ): ScoredIndex[] { const entryNode = this.nodes[entryPointIdx]; if (!entryNode || !entryNode.neighbors.has(layer)) { diff --git a/src/search/matrix.ts b/src/search/matrix.ts index 47f327a..b7b2b7a 100644 --- a/src/search/matrix.ts +++ b/src/search/matrix.ts @@ -18,10 +18,7 @@ import type { SearchOptions, Vector } from '../types'; * @returns A symmetric NxN matrix of similarity scores * @throws {ValidationError} If the embeddings array is empty */ -export function similarityMatrix( - embeddings: Vector[], - options?: SearchOptions, -): number[][] { +export function similarityMatrix(embeddings: Vector[], options?: SearchOptions): number[][] { if (embeddings.length === 0) { throw new ValidationError('Embeddings array must be non-empty'); } diff --git a/src/search/mmr.ts b/src/search/mmr.ts index b5473ec..f8393fa 100644 --- a/src/search/mmr.ts +++ b/src/search/mmr.ts @@ -14,7 +14,7 @@ export function mmrSearch( query: Vector, corpus: Vector[], k: number, - options?: MMROptions, + options?: MMROptions ): Array<{ index: number; score: number }> { const metric = options?.metric ?? 'cosine'; const lambda = options?.lambda ?? 0.5; diff --git a/src/search/pairwise.ts b/src/search/pairwise.ts index 274ffd4..a8fd721 100644 --- a/src/search/pairwise.ts +++ b/src/search/pairwise.ts @@ -13,11 +13,11 @@ import type { SimilarityMetric, Vector } from '../types'; export function pairwiseSimilarity( listA: Vector[], listB: Vector[], - metric: SimilarityMetric = 'cosine', + metric: SimilarityMetric = 'cosine' ): number[] { if (listA.length !== listB.length) { throw new ValidationError( - `Lists must have the same length, got ${listA.length} and ${listB.length}`, + `Lists must have the same length, got ${listA.length} and ${listB.length}` ); } @@ -25,7 +25,7 @@ export function pairwiseSimilarity( for (let i = 0; i < listA.length; i++) { if (listA[i].length !== listB[i].length) { throw new DimensionMismatchError( - `Dimension mismatch at index ${i}: ${listA[i].length} vs ${listB[i].length}`, + `Dimension mismatch at index ${i}: ${listA[i].length} vs ${listB[i].length}` ); } scores[i] = computeScore(listA[i], listB[i], metric); diff --git a/src/search/rank.ts b/src/search/rank.ts index eddb5a8..66f2ef5 100644 --- a/src/search/rank.ts +++ b/src/search/rank.ts @@ -12,7 +12,7 @@ import type { SearchOptions, SearchResult, Vector } from '../types'; export function rankBySimilarity( query: Vector, corpus: Vector[], - options?: SearchOptions, + options?: SearchOptions ): SearchResult[] { if (corpus.length === 0) return []; return topK(query, corpus, corpus.length, options); diff --git a/src/search/rerank.ts b/src/search/rerank.ts index 43e95b6..9e71fa3 100644 --- a/src/search/rerank.ts +++ b/src/search/rerank.ts @@ -15,7 +15,7 @@ export function rerankResults( options?: { metric?: SimilarityMetric; weights?: { original?: number; rerank?: number }; - }, + } ): Array<{ index: number; score: number }> { const metric = options?.metric ?? 'cosine'; const originalWeight = options?.weights?.original ?? 0.5; @@ -23,7 +23,8 @@ export function rerankResults( const reranked = results.map((result) => ({ index: result.index, - score: originalWeight * result.score + rerankWeight * computeScore(query, result.embedding, metric), + score: + originalWeight * result.score + rerankWeight * computeScore(query, result.embedding, metric), })); reranked.sort((a, b) => b.score - a.score); diff --git a/src/search/search-index.ts b/src/search/search-index.ts index 7733156..e6948ac 100644 --- a/src/search/search-index.ts +++ b/src/search/search-index.ts @@ -23,11 +23,17 @@ export class SearchIndex { /** Add a single item. Overwrites if ID already exists. */ add(id: string, embedding: Vector, metadata?: Record): void { - this.items.set(id, { id, embedding: toFloat32(embedding), ...(metadata !== undefined ? { metadata } : {}) }); + this.items.set(id, { + id, + embedding: toFloat32(embedding), + ...(metadata !== undefined ? { metadata } : {}), + }); } /** Add multiple items at once. */ - addBatch(items: Array<{ id: string; embedding: Vector; metadata?: Record }>): void { + addBatch( + items: Array<{ id: string; embedding: Vector; metadata?: Record }> + ): void { for (const item of items) { this.add(item.id, item.embedding, item.metadata); } @@ -45,7 +51,7 @@ export class SearchIndex { topK?: number; threshold?: number; filter?: (item: StoredItem) => boolean; - }, + } ): Array { const topK = options?.topK ?? 10; const threshold = options?.threshold; diff --git a/src/search/threshold.ts b/src/search/threshold.ts index 333deec..ad57a41 100644 --- a/src/search/threshold.ts +++ b/src/search/threshold.ts @@ -24,7 +24,7 @@ export function aboveThreshold( query: Vector, corpus: Vector[], threshold: number, - options?: SearchOptions, + options?: SearchOptions ): SearchResult[] { if (!Number.isFinite(threshold)) { throw new ValidationError(`threshold must be a finite number, got ${threshold}`); @@ -36,7 +36,7 @@ export function aboveThreshold( if (corpus.length > 0 && query.length !== corpus[0].length) { throw new DimensionMismatchError( - `Query dimension (${query.length}) does not match corpus dimension (${corpus[0].length})`, + `Query dimension (${query.length}) does not match corpus dimension (${corpus[0].length})` ); } @@ -70,7 +70,7 @@ export function aboveThreshold( export function deduplicate( embeddings: Vector[], threshold: number, - options?: SearchOptions, + options?: SearchOptions ): { embeddings: Float32Array[]; indices: number[]; labels?: string[] } { const metric = options?.metric ?? 'cosine'; const labels = options?.labels; diff --git a/src/search/topk.ts b/src/search/topk.ts index 107d53e..514aef0 100644 --- a/src/search/topk.ts +++ b/src/search/topk.ts @@ -24,7 +24,7 @@ export function topK( query: Vector, corpus: Vector[], k: number, - options?: SearchOptions, + options?: SearchOptions ): SearchResult[] { if (k < 1 || !Number.isInteger(k)) { throw new ValidationError(`k must be a positive integer, got ${k}`); @@ -36,7 +36,7 @@ export function topK( if (corpus.length > 0 && query.length !== corpus[0].length) { throw new DimensionMismatchError( - `Query dimension (${query.length}) does not match corpus dimension (${corpus[0].length})`, + `Query dimension (${query.length}) does not match corpus dimension (${corpus[0].length})` ); } @@ -104,7 +104,7 @@ export function topKMulti( queries: Vector[], corpus: Vector[], k: number, - options?: SearchOptions, + options?: SearchOptions ): SearchResult[][] { return queries.map((query) => topK(query, corpus, k, options)); } diff --git a/src/storage/cache.ts b/src/storage/cache.ts index 26f8ebe..056b035 100644 --- a/src/storage/cache.ts +++ b/src/storage/cache.ts @@ -99,7 +99,7 @@ export function createLRUCache(options?: CacheOptions): CacheProvider { */ export async function warmCache( cache: CacheProvider, - data: Array<{ key: string; value: Float32Array[] }>, + data: Array<{ key: string; value: Float32Array[] }> ): Promise { for (const entry of data) { await cache.set(entry.key, entry.value); diff --git a/src/storage/serialize.ts b/src/storage/serialize.ts index 678cbd9..2301dd7 100644 --- a/src/storage/serialize.ts +++ b/src/storage/serialize.ts @@ -135,7 +135,7 @@ function fromBinaryV2(data: Uint8Array): DeserializeResult { offset += 4; const decoder = new TextDecoder(); metadata = JSON.parse( - decoder.decode(new Uint8Array(data.buffer, data.byteOffset + offset, metadataLength)), + decoder.decode(new Uint8Array(data.buffer, data.byteOffset + offset, metadataLength)) ); offset += metadataLength; } @@ -169,16 +169,14 @@ function fromBinaryV2(data: Uint8Array): DeserializeResult { export function serialize( embeddings: Vector[], format: SerializeFormat, - metadata?: SerializationMetadata, + metadata?: SerializationMetadata ): string | Uint8Array { validateEmbeddings(embeddings); switch (format) { case 'json': // For JSON, convert Float32Array to regular arrays for proper JSON serialization - return JSON.stringify(embeddings.map((e) => - e instanceof Float32Array ? Array.from(e) : e, - )); + return JSON.stringify(embeddings.map((e) => (e instanceof Float32Array ? Array.from(e) : e))); case 'binary': return toBinaryV2(embeddings, metadata); @@ -200,10 +198,7 @@ export function serialize( * @param format - Input format: 'json', 'binary', or 'base64' * @returns Object with Float32Array[] embeddings and optional metadata (v2 only) */ -export function deserialize( - data: string | Uint8Array, - format: SerializeFormat, -): DeserializeResult { +export function deserialize(data: string | Uint8Array, format: SerializeFormat): DeserializeResult { switch (format) { case 'json': { const parsed: number[][] = JSON.parse(data as string); diff --git a/src/store/embedding-store.ts b/src/store/embedding-store.ts index 949e7cd..f2eaeac 100644 --- a/src/store/embedding-store.ts +++ b/src/store/embedding-store.ts @@ -1,8 +1,4 @@ -import type { - EmbeddingStoreConfig, - StoredItem, - Vector, -} from '../types'; +import type { EmbeddingStoreConfig, StoredItem, Vector } from '../types'; import { SearchIndex } from '../search/search-index'; import { withCache } from '../providers/middleware'; @@ -17,16 +13,18 @@ export interface EmbeddingStore { /** Embed text and store the result with an ID and optional metadata. */ add(id: string, text: string, metadata?: Record): Promise; /** Batch embed and store multiple items. */ - addBatch(items: Array<{ id: string; text: string; metadata?: Record }>): Promise; + addBatch( + items: Array<{ id: string; text: string; metadata?: Record }> + ): Promise; /** Embed query text and search for similar items. */ search( query: string, - options?: { topK?: number; threshold?: number; filter?: (item: StoredItem) => boolean }, + options?: { topK?: number; threshold?: number; filter?: (item: StoredItem) => boolean } ): Promise>; /** Search by a pre-computed embedding vector. */ searchByEmbedding( embedding: Vector, - options?: { topK?: number; threshold?: number; filter?: (item: StoredItem) => boolean }, + options?: { topK?: number; threshold?: number; filter?: (item: StoredItem) => boolean } ): Array; /** Remove an item by ID. */ remove(id: string): boolean; @@ -52,9 +50,7 @@ export interface EmbeddingStore { * const results = await store.search('greeting', { topK: 5 }); */ export function createEmbeddingStore(config: EmbeddingStoreConfig): EmbeddingStore { - const provider = config.cache - ? withCache(config.provider, config.cache) - : config.provider; + const provider = config.cache ? withCache(config.provider, config.cache) : config.provider; const index = new SearchIndex({ metric: config.metric }); @@ -65,7 +61,7 @@ export function createEmbeddingStore(config: EmbeddingStoreConfig): EmbeddingSto }, async addBatch( - items: Array<{ id: string; text: string; metadata?: Record }>, + items: Array<{ id: string; text: string; metadata?: Record }> ): Promise { const texts = items.map((item) => item.text); const result = await provider.embed(texts); @@ -76,7 +72,7 @@ export function createEmbeddingStore(config: EmbeddingStoreConfig): EmbeddingSto async search( query: string, - options?: { topK?: number; threshold?: number; filter?: (item: StoredItem) => boolean }, + options?: { topK?: number; threshold?: number; filter?: (item: StoredItem) => boolean } ): Promise> { const result = await provider.embed(query); return index.search(result.embeddings[0], options); @@ -84,7 +80,7 @@ export function createEmbeddingStore(config: EmbeddingStoreConfig): EmbeddingSto searchByEmbedding( embedding: Vector, - options?: { topK?: number; threshold?: number; filter?: (item: StoredItem) => boolean }, + options?: { topK?: number; threshold?: number; filter?: (item: StoredItem) => boolean } ): Array { return index.search(embedding, options); }, diff --git a/src/text/chunking.ts b/src/text/chunking.ts index fb27973..b863150 100644 --- a/src/text/chunking.ts +++ b/src/text/chunking.ts @@ -12,7 +12,7 @@ export function chunkByTokenCount( text: string, maxTokens: number, - options?: { overlap?: number; separator?: string }, + options?: { overlap?: number; separator?: string } ): string[] { if (!text) return []; @@ -51,19 +51,17 @@ export function chunkByTokenCount( */ export function chunkBySentence( text: string, - options?: { maxTokens?: number; overlap?: number }, + options?: { maxTokens?: number; overlap?: number } ): string[] { if (!text) return []; if (typeof Intl === 'undefined' || !('Segmenter' in Intl)) { - throw new Error( - 'chunkBySentence requires Intl.Segmenter (Node 16+ or modern browser)', - ); + throw new Error('chunkBySentence requires Intl.Segmenter (Node 16+ or modern browser)'); } const segmenter = new Intl.Segmenter(undefined, { granularity: 'sentence' }); const sentences = Array.from(segmenter.segment(text), (s) => s.segment).filter( - (s) => s.trim().length > 0, + (s) => s.trim().length > 0 ); if (sentences.length === 0) return []; diff --git a/src/text/markdown.ts b/src/text/markdown.ts index 88d08b5..7ac945f 100644 --- a/src/text/markdown.ts +++ b/src/text/markdown.ts @@ -192,7 +192,7 @@ function splitSentences(text: string): string[] { */ export function chunkByStructure( text: string, - options?: { maxTokens?: number; overlap?: number }, + options?: { maxTokens?: number; overlap?: number } ): StructuredChunk[] { if (!text || text.trim().length === 0) return []; @@ -278,7 +278,11 @@ export function chunkByStructure( if (estimateTokens(candidate) > overlap) break; overlapText = candidate; } - currentOffset = block.offset + text.indexOf(currentText, currentOffset - block.offset) + currentText.length - overlapText.length; + currentOffset = + block.offset + + text.indexOf(currentText, currentOffset - block.offset) + + currentText.length - + overlapText.length; currentText = overlapText; } else { currentOffset = block.offset + block.text.indexOf(sentence, currentText.length); diff --git a/tests/aggregation/average.test.ts b/tests/aggregation/average.test.ts index e574c05..d984cd2 100644 --- a/tests/aggregation/average.test.ts +++ b/tests/aggregation/average.test.ts @@ -39,7 +39,12 @@ describe('averageEmbeddings', () => { }); it('throws ValidationError for mixed dimensions', () => { - expect(() => averageEmbeddings([[1, 2], [1, 2, 3]])).toThrow(ValidationError); + expect(() => + averageEmbeddings([ + [1, 2], + [1, 2, 3], + ]) + ).toThrow(ValidationError); }); it('returns the vector itself for a single input', () => { @@ -78,7 +83,7 @@ describe('weightedAverage', () => { [10, 20], [1, 2], ], - [0, 1], + [0, 1] ); expect(result).toBeInstanceOf(Float32Array); expect(Array.from(result)).toEqual([1, 2]); @@ -90,7 +95,7 @@ describe('weightedAverage', () => { [0, 0], [10, 10], ], - [1, 3], + [1, 3] ); // (0*1 + 10*3) / (1+3) = 7.5 expect(result).toBeInstanceOf(Float32Array); diff --git a/tests/aggregation/batch-incremental.test.ts b/tests/aggregation/batch-incremental.test.ts index d78a4ed..9707529 100644 --- a/tests/aggregation/batch-incremental.test.ts +++ b/tests/aggregation/batch-incremental.test.ts @@ -1,17 +1,10 @@ import { describe, it, expect } from 'vitest'; -import { - batchIncrementalAverage, - averageEmbeddings, -} from '../../src/aggregation/average'; +import { batchIncrementalAverage, averageEmbeddings } from '../../src/aggregation/average'; import { ValidationError } from '../../src/types'; describe('batchIncrementalAverage', () => { it('produces result equivalent to full re-average for a batch of 10 vectors', () => { - const vectors = Array.from({ length: 10 }, (_, i) => [ - Math.sin(i), - Math.cos(i), - i * 0.1, - ]); + const vectors = Array.from({ length: 10 }, (_, i) => [Math.sin(i), Math.cos(i), i * 0.1]); const fullAvg = averageEmbeddings(vectors); // Incrementally: start with first vector, then batch the remaining 9 @@ -43,14 +36,19 @@ describe('batchIncrementalAverage', () => { it('throws ValidationError for dimension mismatch across batch items', () => { expect(() => - batchIncrementalAverage([1, 2, 3], [[4, 5, 6], [7, 8]], 1), + batchIncrementalAverage( + [1, 2, 3], + [ + [4, 5, 6], + [7, 8], + ], + 1 + ) ).toThrow(ValidationError); }); it('throws ValidationError when batch item dimension mismatches currentAvg', () => { - expect(() => - batchIncrementalAverage([1, 2], [[3, 4, 5]], 1), - ).toThrow(ValidationError); + expect(() => batchIncrementalAverage([1, 2], [[3, 4, 5]], 1)).toThrow(ValidationError); }); it('returns the blended value for a single-item batch', () => { diff --git a/tests/aggregation/combine.test.ts b/tests/aggregation/combine.test.ts index 04e32f7..98097e9 100644 --- a/tests/aggregation/combine.test.ts +++ b/tests/aggregation/combine.test.ts @@ -17,10 +17,7 @@ function createMockProvider(embeddings: Float32Array[]): EmbeddingProvider { describe('combineEmbeddings', () => { it('should combine multiple texts into single averaged embedding', async () => { - const provider = createMockProvider([ - new Float32Array([1, 2, 3]), - new Float32Array([3, 4, 5]), - ]); + const provider = createMockProvider([new Float32Array([1, 2, 3]), new Float32Array([3, 4, 5])]); const result = await combineEmbeddings(['hello', 'world'], provider); @@ -30,10 +27,7 @@ describe('combineEmbeddings', () => { }); it('should use custom aggregation function', async () => { - const provider = createMockProvider([ - new Float32Array([1, 2, 3]), - new Float32Array([4, 5, 6]), - ]); + const provider = createMockProvider([new Float32Array([1, 2, 3]), new Float32Array([4, 5, 6])]); // Use max pooling as custom aggregation const maxPool = (embeddings: (number[] | Float32Array)[]): Float32Array => { diff --git a/tests/aggregation/pooling.test.ts b/tests/aggregation/pooling.test.ts index 8b966cd..d39c19a 100644 --- a/tests/aggregation/pooling.test.ts +++ b/tests/aggregation/pooling.test.ts @@ -24,7 +24,12 @@ describe('maxPooling', () => { }); it('throws ValidationError for mixed dimensions', () => { - expect(() => maxPooling([[1, 2], [1, 2, 3]])).toThrow(ValidationError); + expect(() => + maxPooling([ + [1, 2], + [1, 2, 3], + ]) + ).toThrow(ValidationError); }); it('handles negative values correctly', () => { @@ -65,7 +70,12 @@ describe('minPooling', () => { }); it('throws ValidationError for mixed dimensions', () => { - expect(() => minPooling([[1, 2], [1, 2, 3]])).toThrow(ValidationError); + expect(() => + minPooling([ + [1, 2], + [1, 2, 3], + ]) + ).toThrow(ValidationError); }); it('handles negative values correctly', () => { diff --git a/tests/clustering/cluster.test.ts b/tests/clustering/cluster.test.ts index 372b5ee..cd43875 100644 --- a/tests/clustering/cluster.test.ts +++ b/tests/clustering/cluster.test.ts @@ -26,9 +26,15 @@ describe('clusterEmbeddings', () => { it('separates orthogonal embeddings into different clusters', () => { const embeddings = [ - [1, 0, 0], [1, 0, 0], [1, 0, 0], - [0, 1, 0], [0, 1, 0], [0, 1, 0], - [0, 0, 1], [0, 0, 1], [0, 0, 1], + [1, 0, 0], + [1, 0, 0], + [1, 0, 0], + [0, 1, 0], + [0, 1, 0], + [0, 1, 0], + [0, 0, 1], + [0, 0, 1], + [0, 0, 1], ]; const clusters = clusterEmbeddings(embeddings, { similarityThreshold: 0.5, @@ -40,8 +46,12 @@ describe('clusterEmbeddings', () => { it('high threshold creates more clusters', () => { // Slightly different vectors that are similar but not identical const embeddings = [ - [1, 0, 0], [0.99, 0.1, 0], [0.98, 0.15, 0], - [0, 1, 0], [0.1, 0.99, 0], [0.05, 0.98, 0], + [1, 0, 0], + [0.99, 0.1, 0], + [0.98, 0.15, 0], + [0, 1, 0], + [0.1, 0.99, 0], + [0.05, 0.98, 0], ]; const looseThreshold = clusterEmbeddings(embeddings, { similarityThreshold: 0.5, @@ -56,7 +66,11 @@ describe('clusterEmbeddings', () => { it('redistributes small clusters into nearest valid cluster', () => { const embeddings = [ - [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], + [1, 0, 0], + [1, 0, 0], + [1, 0, 0], + [1, 0, 0], + [1, 0, 0], [0, 1, 0], // only 1 member — too small, redistributed to nearest valid cluster ]; const clusters = clusterEmbeddings(embeddings, { @@ -70,10 +84,14 @@ describe('clusterEmbeddings', () => { it('caps clusters at maxClusters by merging most similar', () => { const embeddings = [ - [1, 0, 0], [1, 0, 0], - [0, 1, 0], [0, 1, 0], - [0, 0, 1], [0, 0, 1], - [0.7, 0.7, 0], [0.7, 0.7, 0], + [1, 0, 0], + [1, 0, 0], + [0, 1, 0], + [0, 1, 0], + [0, 0, 1], + [0, 0, 1], + [0.7, 0.7, 0], + [0.7, 0.7, 0], ]; const clusters = clusterEmbeddings(embeddings, { similarityThreshold: 0.5, @@ -85,8 +103,12 @@ describe('clusterEmbeddings', () => { it('supports custom metric option', () => { const embeddings = [ - [1, 0, 0], [1, 0, 0], [1, 0, 0], - [0, 1, 0], [0, 1, 0], [0, 1, 0], + [1, 0, 0], + [1, 0, 0], + [1, 0, 0], + [0, 1, 0], + [0, 1, 0], + [0, 1, 0], ]; const clusters = clusterEmbeddings(embeddings, { similarityThreshold: 0.5, @@ -118,8 +140,12 @@ describe('clusterEmbeddings', () => { it('populates cohesion field on each cluster', () => { const embeddings = [ - [1, 0, 0], [1, 0, 0], [1, 0, 0], - [0, 1, 0], [0, 1, 0], [0, 1, 0], + [1, 0, 0], + [1, 0, 0], + [1, 0, 0], + [0, 1, 0], + [0, 1, 0], + [0, 1, 0], ]; const clusters = clusterEmbeddings(embeddings, { similarityThreshold: 0.5, diff --git a/tests/clustering/cohesion.test.ts b/tests/clustering/cohesion.test.ts index f73cb2b..b6e2b69 100644 --- a/tests/clustering/cohesion.test.ts +++ b/tests/clustering/cohesion.test.ts @@ -1,12 +1,14 @@ import { describe, it, expect } from 'vitest'; import { centroidCohesion } from '../../src/clustering/metrics'; -import type { Cluster, SimilarityMetric } from '../../src/types'; +import type { Cluster } from '../../src/types'; function makeCluster(members: number[][], centroid?: number[]): Cluster { - const c = centroid ?? members.reduce( - (acc, m) => acc.map((v, i) => v + m[i] / members.length), - new Array(members[0].length).fill(0), - ); + const c = + centroid ?? + members.reduce( + (acc, m) => acc.map((v, i) => v + m[i] / members.length), + new Array(members[0].length).fill(0) + ); return { centroid: c, members, size: members.length, cohesion: 0 }; } @@ -38,7 +40,10 @@ describe('centroidCohesion', () => { }); it('works with euclidean metric', () => { - const members = [[1, 0], [1.1, 0.1]]; + const members = [ + [1, 0], + [1.1, 0.1], + ]; const cluster = makeCluster(members); const score = centroidCohesion(cluster, 'euclidean'); expect(typeof score).toBe('number'); @@ -46,7 +51,10 @@ describe('centroidCohesion', () => { }); it('works with dot metric', () => { - const members = [[1, 0], [0.9, 0.1]]; + const members = [ + [1, 0], + [0.9, 0.1], + ]; const cluster = makeCluster(members); const score = centroidCohesion(cluster, 'dot'); expect(typeof score).toBe('number'); @@ -54,7 +62,10 @@ describe('centroidCohesion', () => { }); it('works with manhattan metric', () => { - const members = [[1, 0], [0.9, 0.1]]; + const members = [ + [1, 0], + [0.9, 0.1], + ]; const cluster = makeCluster(members); const score = centroidCohesion(cluster, 'manhattan'); expect(typeof score).toBe('number'); @@ -62,7 +73,11 @@ describe('centroidCohesion', () => { }); it('returns 1.0 for all identical members (cosine)', () => { - const members = [[0.5, 0.5], [0.5, 0.5], [0.5, 0.5]]; + const members = [ + [0.5, 0.5], + [0.5, 0.5], + [0.5, 0.5], + ]; const cluster = makeCluster(members); expect(centroidCohesion(cluster, 'cosine')).toBeCloseTo(1.0, 5); }); diff --git a/tests/clustering/hdbscan.test.ts b/tests/clustering/hdbscan.test.ts index 31754f6..985c49f 100644 --- a/tests/clustering/hdbscan.test.ts +++ b/tests/clustering/hdbscan.test.ts @@ -10,7 +10,7 @@ function makeCluster2D( cy: number, count: number, spread: number, - seed: number, + seed: number ): number[][] { const pts: number[][] = []; let s = seed; @@ -32,7 +32,7 @@ function makeRing2D( radius: number, count: number, noise: number, - seed: number, + seed: number ): number[][] { const pts: number[][] = []; let s = seed; @@ -106,7 +106,10 @@ describe('hdbscan — noise detection', () => { // Use multiple clusters + outliers so the outliers don't get absorbed const cluster1 = makeCluster2D(0, 0, 15, 0.3, 1); const cluster2 = makeCluster2D(10, 0, 15, 0.3, 2); - const outliers: number[][] = [[100, 100], [-100, -100]]; + const outliers: number[][] = [ + [100, 100], + [-100, -100], + ]; const embeddings = [...cluster1, ...cluster2, ...outliers]; const result = hdbscan(embeddings, { minClusterSize: 5 }); @@ -117,7 +120,10 @@ describe('hdbscan — noise detection', () => { it('noise points are NOT in any cluster members', () => { const cluster = makeCluster2D(0, 0, 20, 0.3, 1); - const outliers: number[][] = [[100, 100], [-100, -100]]; + const outliers: number[][] = [ + [100, 100], + [-100, -100], + ]; const embeddings = [...cluster, ...outliers]; const result = hdbscan(embeddings, { minClusterSize: 5 }); @@ -178,10 +184,7 @@ describe('hdbscan — edge cases', () => { }); it('minSamples affects core distance computation', () => { - const embeddings = [ - ...makeCluster2D(0, 0, 20, 0.5, 1), - ...makeCluster2D(10, 0, 20, 0.5, 2), - ]; + const embeddings = [...makeCluster2D(0, 0, 20, 0.5, 1), ...makeCluster2D(10, 0, 20, 0.5, 2)]; const result1 = hdbscan(embeddings, { minClusterSize: 5, minSamples: 3 }); const result2 = hdbscan(embeddings, { minClusterSize: 5, minSamples: 15 }); // Different minSamples should potentially produce different results @@ -195,10 +198,7 @@ describe('hdbscan — edge cases', () => { describe('hdbscan — label preservation', () => { it('preserves string labels in cluster members', () => { - const embeddings = [ - ...makeCluster2D(0, 0, 10, 0.3, 1), - ...makeCluster2D(10, 0, 10, 0.3, 2), - ]; + const embeddings = [...makeCluster2D(0, 0, 10, 0.3, 1), ...makeCluster2D(10, 0, 10, 0.3, 2)]; const labels = embeddings.map((_, i) => `point-${i}`); const result = hdbscan(embeddings, { minClusterSize: 5, labels }); @@ -230,7 +230,7 @@ describe('hdbscan — label preservation', () => { it('throws ValidationError for labels length mismatch', () => { const embeddings = makeCluster2D(0, 0, 10, 0.3, 1); expect(() => hdbscan(embeddings, { minClusterSize: 5, labels: ['a', 'b'] })).toThrow( - ValidationError, + ValidationError ); }); }); @@ -239,10 +239,7 @@ describe('hdbscan — label preservation', () => { describe('hdbscan — metric support', () => { it('default metric is euclidean', () => { - const embeddings = [ - ...makeCluster2D(0, 0, 15, 0.3, 1), - ...makeCluster2D(10, 0, 15, 0.3, 2), - ]; + const embeddings = [...makeCluster2D(0, 0, 15, 0.3, 1), ...makeCluster2D(10, 0, 15, 0.3, 2)]; const defaultResult = hdbscan(embeddings, { minClusterSize: 5 }); const euclideanResult = hdbscan(embeddings, { minClusterSize: 5, metric: 'euclidean' }); expect(defaultResult.labels).toEqual(euclideanResult.labels); diff --git a/tests/clustering/incremental.test.ts b/tests/clustering/incremental.test.ts index 12f6cbe..e7ae995 100644 --- a/tests/clustering/incremental.test.ts +++ b/tests/clustering/incremental.test.ts @@ -51,6 +51,11 @@ describe('IncrementalClusterer', () => { // Should still have reasonable clusters after rebalance expect(afterRebalance.length).toBeGreaterThanOrEqual(1); expect(afterRebalance.length).toBeLessThanOrEqual(2); + + // Rebalance redistributes members without dropping any + const membersBefore = beforeRebalance.reduce((sum, c) => sum + c.size, 0); + const membersAfter = afterRebalance.reduce((sum, c) => sum + c.size, 0); + expect(membersAfter).toBe(membersBefore); }); it('getStats returns per-cluster statistics', () => { @@ -71,8 +76,12 @@ describe('IncrementalClusterer', () => { it('addBatch adds multiple embeddings', () => { const clusterer = new IncrementalClusterer({ similarityThreshold: 0.8 }); clusterer.addBatch( - [[1, 0, 0], [0.99, 0.01, 0], [0, 1, 0]], - ['a', 'b', 'c'], + [ + [1, 0, 0], + [0.99, 0.01, 0], + [0, 1, 0], + ], + ['a', 'b', 'c'] ); expect(clusterer.size).toBe(3); const clusters = clusterer.getClusters(); diff --git a/tests/clustering/metrics.test.ts b/tests/clustering/metrics.test.ts index 4984e86..f928148 100644 --- a/tests/clustering/metrics.test.ts +++ b/tests/clustering/metrics.test.ts @@ -122,9 +122,7 @@ describe('silhouetteScore', () => { [0.45, 0.55, 0], ]), ]; - expect(silhouetteScore(overlapping)).toBeLessThan( - silhouetteScore(wellSeparated), - ); + expect(silhouetteScore(overlapping)).toBeLessThan(silhouetteScore(wellSeparated)); }); it('works with euclidean metric', () => { diff --git a/tests/clustering/operations.test.ts b/tests/clustering/operations.test.ts index b276a78..a87f343 100644 --- a/tests/clustering/operations.test.ts +++ b/tests/clustering/operations.test.ts @@ -2,10 +2,7 @@ import { describe, it, expect } from 'vitest'; import { assignToCluster, mergeClusters } from '../../src/clustering/operations'; import type { Cluster } from '../../src/types'; -function makeCluster( - members: number[][], - labels?: string[], -): Cluster { +function makeCluster(members: number[][], labels?: string[]): Cluster { const dims = members[0].length; const centroid = new Array(dims).fill(0); for (const m of members) { @@ -17,8 +14,14 @@ function makeCluster( describe('assignToCluster', () => { const clusters: Cluster[] = [ - makeCluster([[1, 0, 0], [0.95, 0.05, 0]]), - makeCluster([[0, 1, 0], [0.05, 0.95, 0]]), + makeCluster([ + [1, 0, 0], + [0.95, 0.05, 0], + ]), + makeCluster([ + [0, 1, 0], + [0.05, 0.95, 0], + ]), ]; it('assigns embedding to most similar cluster', () => { @@ -54,7 +57,10 @@ describe('assignToCluster', () => { describe('mergeClusters', () => { it('combines members from both clusters', () => { - const a = makeCluster([[1, 0, 0], [0.9, 0.1, 0]]); + const a = makeCluster([ + [1, 0, 0], + [0.9, 0.1, 0], + ]); const b = makeCluster([[0.8, 0.2, 0]]); const merged = mergeClusters(a, b); expect(merged.members).toHaveLength(3); @@ -71,8 +77,14 @@ describe('mergeClusters', () => { }); it('updates cohesion', () => { - const a = makeCluster([[1, 0, 0], [0.99, 0.01, 0]]); - const b = makeCluster([[0, 1, 0], [0.01, 0.99, 0]]); + const a = makeCluster([ + [1, 0, 0], + [0.99, 0.01, 0], + ]); + const b = makeCluster([ + [0, 1, 0], + [0.01, 0.99, 0], + ]); const merged = mergeClusters(a, b); expect(typeof merged.cohesion).toBe('number'); // Merged disparate clusters should have lower cohesion diff --git a/tests/clustering/presets.test.ts b/tests/clustering/presets.test.ts index 5170a23..f60f586 100644 --- a/tests/clustering/presets.test.ts +++ b/tests/clustering/presets.test.ts @@ -46,8 +46,16 @@ describe('getPreset', () => { it('presets work with clusterEmbeddings', () => { const embeddings = [ - [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], - [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], + [1, 0, 0], + [1, 0, 0], + [1, 0, 0], + [1, 0, 0], + [1, 0, 0], + [0, 1, 0], + [0, 1, 0], + [0, 1, 0], + [0, 1, 0], + [0, 1, 0], ]; const preset = getPreset('balanced'); const clusters = clusterEmbeddings(embeddings, preset); diff --git a/tests/clustering/redistribution.test.ts b/tests/clustering/redistribution.test.ts index cdad627..a78db99 100644 --- a/tests/clustering/redistribution.test.ts +++ b/tests/clustering/redistribution.test.ts @@ -14,8 +14,8 @@ describe('cluster redistribution edge cases', () => { ]; const clusters = clusterEmbeddings(embeddings, { - similarityThreshold: 0.95, // very high so each gets its own cluster initially - minClusterSize: 10, // larger than total count, forcing all-small path + similarityThreshold: 0.95, // very high so each gets its own cluster initially + minClusterSize: 10, // larger than total count, forcing all-small path maxClusters: 5, }); @@ -27,9 +27,9 @@ describe('cluster redistribution edge cases', () => { it('preserves all members after redistribution', () => { const embeddings = [ [1, 0, 0], - [0.99, 0.01, 0], // close to first - [0.98, 0.02, 0], // close to first - [0, 1, 0], // outlier, will be in small cluster + [0.99, 0.01, 0], // close to first + [0.98, 0.02, 0], // close to first + [0, 1, 0], // outlier, will be in small cluster ]; const clusters = clusterEmbeddings(embeddings, { @@ -52,7 +52,7 @@ describe('cluster redistribution edge cases', () => { const clusters = clusterEmbeddings(embeddings, { similarityThreshold: 0.99, // very high — likely one per cluster - minClusterSize: 1, // no redistribution needed + minClusterSize: 1, // no redistribution needed maxClusters: 10, }); @@ -68,7 +68,7 @@ describe('cluster redistribution edge cases', () => { [1, 0, 0], [0.98, 0.02, 0], [0.97, 0.03, 0], - [0, 0, 1], // outlier + [0, 0, 1], // outlier ]; const clusters = clusterEmbeddings(embeddings, { diff --git a/tests/edge-cases.test.ts b/tests/edge-cases.test.ts index 4448ceb..57e25d5 100644 --- a/tests/edge-cases.test.ts +++ b/tests/edge-cases.test.ts @@ -1,11 +1,5 @@ import { describe, it, expect } from 'vitest'; -import { - cosineSimilarity, - topK, - aboveThreshold, - normalize, - ValidationError, -} from '../src'; +import { cosineSimilarity, topK, aboveThreshold, normalize, ValidationError } from '../src'; import { validateVector } from '../src/internal/validation'; describe('edge cases', () => { @@ -87,7 +81,10 @@ describe('edge cases', () => { }); it('k equal to corpus.length returns all items', () => { - const corpus = [[1, 0], [0, 1]]; + const corpus = [ + [1, 0], + [0, 1], + ]; const results = topK([1, 0], corpus, 2); expect(results).toHaveLength(2); }); diff --git a/tests/eval/metrics.test.ts b/tests/eval/metrics.test.ts index 698735c..8310f89 100644 --- a/tests/eval/metrics.test.ts +++ b/tests/eval/metrics.test.ts @@ -47,8 +47,16 @@ describe('ndcg', () => { // = 0/1 + 1/1.585 + 3/2 + 7/2.322 = 0 + 0.6309 + 1.5 + 3.0145 = 5.1454 // IDCG (perfect): (2^3-1)/log2(2) + (2^2-1)/log2(3) + (2^1-1)/log2(4) + (2^0-1)/log2(5) // = 7/1 + 3/1.585 + 1/2 + 0/2.322 = 7 + 1.8928 + 0.5 + 0 = 9.3928 - const dcg = 0 / Math.log2(2) + (Math.pow(2, 1) - 1) / Math.log2(3) + (Math.pow(2, 2) - 1) / Math.log2(4) + (Math.pow(2, 3) - 1) / Math.log2(5); - const idcg = (Math.pow(2, 3) - 1) / Math.log2(2) + (Math.pow(2, 2) - 1) / Math.log2(3) + (Math.pow(2, 1) - 1) / Math.log2(4) + 0; + const dcg = + 0 / Math.log2(2) + + (Math.pow(2, 1) - 1) / Math.log2(3) + + (Math.pow(2, 2) - 1) / Math.log2(4) + + (Math.pow(2, 3) - 1) / Math.log2(5); + const idcg = + (Math.pow(2, 3) - 1) / Math.log2(2) + + (Math.pow(2, 2) - 1) / Math.log2(3) + + (Math.pow(2, 1) - 1) / Math.log2(4) + + 0; const expected = dcg / idcg; const result = ndcg(retrieved, scores); expect(result).toBeCloseTo(expected); diff --git a/tests/integration/embed-cluster-search.test.ts b/tests/integration/embed-cluster-search.test.ts index 42381b5..d52540b 100644 --- a/tests/integration/embed-cluster-search.test.ts +++ b/tests/integration/embed-cluster-search.test.ts @@ -21,7 +21,12 @@ function createMockProvider(): EmbeddingProvider { if (text.startsWith('food')) return [0.1, 0.0, 0.0, 0.9]; // Default: hash-based const hash = text.split('').reduce((acc, c) => acc + c.charCodeAt(0), 0); - return [(hash % 10) / 10, ((hash * 3) % 10) / 10, ((hash * 7) % 10) / 10, ((hash * 13) % 10) / 10]; + return [ + (hash % 10) / 10, + ((hash * 3) % 10) / 10, + ((hash * 7) % 10) / 10, + ((hash * 13) % 10) / 10, + ]; }); return { embeddings, model: 'mock', dimensions: 4 }; }, diff --git a/tests/integration/incremental-pipeline.test.ts b/tests/integration/incremental-pipeline.test.ts index d9edb36..0a52a2d 100644 --- a/tests/integration/incremental-pipeline.test.ts +++ b/tests/integration/incremental-pipeline.test.ts @@ -12,7 +12,7 @@ describe('integration: IncrementalClusterer pipeline', () => { // Group A: near [1, 0, 0] const groupA = [ [0.95, 0.05, 0.0], - [0.90, 0.10, 0.0], + [0.9, 0.1, 0.0], [0.92, 0.08, 0.0], [0.88, 0.12, 0.0], [0.93, 0.07, 0.0], @@ -21,7 +21,7 @@ describe('integration: IncrementalClusterer pipeline', () => { // Group B: near [0, 1, 0] const groupB = [ [0.05, 0.95, 0.0], - [0.10, 0.90, 0.0], + [0.1, 0.9, 0.0], [0.08, 0.92, 0.0], [0.12, 0.88, 0.0], [0.07, 0.93, 0.0], @@ -38,9 +38,6 @@ describe('integration: IncrementalClusterer pipeline', () => { const beforeRebalance = clusterer.getClusters(); expect(beforeRebalance.length).toBeGreaterThanOrEqual(2); - // Record cohesion before rebalance - const cohesionBefore = beforeRebalance.map((c) => c.cohesion); - // Rebalance clusterer.rebalance(); diff --git a/tests/integration/v03-features.test.ts b/tests/integration/v03-features.test.ts index 30b0fa5..9eaa4ca 100644 --- a/tests/integration/v03-features.test.ts +++ b/tests/integration/v03-features.test.ts @@ -3,7 +3,6 @@ import { HNSWIndex } from '../../src/search/hnsw'; import { hdbscan } from '../../src/clustering/hdbscan'; import { recallAtK, ndcg } from '../../src/eval/metrics'; import { topK } from '../../src/search/topk'; -import { createEmbeddingStore } from '../../src/store/embedding-store'; import { createEmbeddingPipeline } from '../../src/pipeline/pipeline'; import { chunkByStructure } from '../../src/text/markdown'; import { SearchIndex } from '../../src/search/search-index'; @@ -22,12 +21,26 @@ function createMockProvider(dims = 8): EmbeddingProvider { const vec = new Float32Array(dims); // Create separable embeddings based on topic prefixes const lower = text.toLowerCase(); - if (lower.includes('machine learning') || lower.includes('neural') || lower.includes('ai')) { - vec[0] = 0.9; vec[1] = 0.3; vec[2] = 0.1; - } else if (lower.includes('cooking') || lower.includes('recipe') || lower.includes('pasta')) { - vec[3] = 0.9; vec[4] = 0.3; vec[5] = 0.1; + if ( + lower.includes('machine learning') || + lower.includes('neural') || + lower.includes('ai') + ) { + vec[0] = 0.9; + vec[1] = 0.3; + vec[2] = 0.1; + } else if ( + lower.includes('cooking') || + lower.includes('recipe') || + lower.includes('pasta') + ) { + vec[3] = 0.9; + vec[4] = 0.3; + vec[5] = 0.1; } else if (lower.includes('space') || lower.includes('planet') || lower.includes('nasa')) { - vec[0] = 0.1; vec[1] = 0.9; vec[6] = 0.3; + vec[0] = 0.1; + vec[1] = 0.9; + vec[6] = 0.3; } else { // Hash-based fallback let h = 0; @@ -78,7 +91,9 @@ describe('integration: embed → HNSW → search → evaluate', () => { expect(hnsw.size).toBe(texts.length); // Query for AI-related content - const { embeddings: [queryVec] } = await provider.embed('ai and machine learning'); + const { + embeddings: [queryVec], + } = await provider.embed('ai and machine learning'); // HNSW search const hnswResults = hnsw.search(queryVec, { topK: 3 }); @@ -192,9 +207,6 @@ describe('integration: pipeline → store → search', () => { expect(emb).toBeInstanceOf(Float32Array); } - // Store the pipeline output in an EmbeddingStore (using searchByEmbedding) - const store = createEmbeddingStore({ provider, metric: 'cosine' }); - // Add items using their pre-computed embeddings via the underlying SearchIndex // (EmbeddingStore.add calls the provider, so we use a direct approach) const index = new SearchIndex({ metric: 'cosine' }); @@ -203,7 +215,9 @@ describe('integration: pipeline → store → search', () => { } // Search - const { embeddings: [queryVec] } = await provider.embed('ai and machine learning'); + const { + embeddings: [queryVec], + } = await provider.embed('ai and machine learning'); const results = index.search(queryVec, { topK: 2 }); expect(results.length).toBe(2); @@ -258,7 +272,9 @@ A recipe for making delicious Italian pasta from scratch. } // Search for AI-related content - const { embeddings: [queryVec] } = await provider.embed('neural network ai learning'); + const { + embeddings: [queryVec], + } = await provider.embed('neural network ai learning'); const results = index.search(queryVec, { topK: 3 }); expect(results.length).toBeGreaterThan(0); diff --git a/tests/internal/clustering.test.ts b/tests/internal/clustering.test.ts index 767eb55..9e6b46f 100644 --- a/tests/internal/clustering.test.ts +++ b/tests/internal/clustering.test.ts @@ -3,7 +3,10 @@ import { computeCentroid, computePairwiseCohesion } from '../../src/internal/clu describe('computeCentroid', () => { it('computes mean of known vectors', () => { - const centroid = computeCentroid([[1, 0], [0, 1]]); + const centroid = computeCentroid([ + [1, 0], + [0, 1], + ]); expect(centroid).toBeInstanceOf(Float32Array); expect(Array.from(centroid)).toEqual([0.5, 0.5]); }); @@ -15,7 +18,11 @@ describe('computeCentroid', () => { }); it('computes centroid of three vectors', () => { - const centroid = computeCentroid([[1, 2, 3], [4, 5, 6], [7, 8, 9]]); + const centroid = computeCentroid([ + [1, 2, 3], + [4, 5, 6], + [7, 8, 9], + ]); expect(centroid).toBeInstanceOf(Float32Array); expect(Array.from(centroid)).toEqual([4, 5, 6]); }); @@ -23,12 +30,25 @@ describe('computeCentroid', () => { describe('computePairwiseCohesion', () => { it('returns 1.0 for identical vectors with cosine metric', () => { - const cohesion = computePairwiseCohesion([[1, 0], [1, 0], [1, 0]], 'cosine'); + const cohesion = computePairwiseCohesion( + [ + [1, 0], + [1, 0], + [1, 0], + ], + 'cosine' + ); expect(cohesion).toBeCloseTo(1.0); }); it('returns 0.0 for orthogonal vectors with cosine metric', () => { - const cohesion = computePairwiseCohesion([[1, 0], [0, 1]], 'cosine'); + const cohesion = computePairwiseCohesion( + [ + [1, 0], + [0, 1], + ], + 'cosine' + ); expect(cohesion).toBeCloseTo(0.0); }); diff --git a/tests/internal/validation.test.ts b/tests/internal/validation.test.ts index aaced77..18ffb45 100644 --- a/tests/internal/validation.test.ts +++ b/tests/internal/validation.test.ts @@ -1,5 +1,9 @@ import { describe, it, expect } from 'vitest'; -import { validateVector, validateVectorPair, validateEmbeddings } from '../../src/internal/validation'; +import { + validateVector, + validateVectorPair, + validateEmbeddings, +} from '../../src/internal/validation'; import { ValidationError, DimensionMismatchError } from '../../src/types'; describe('validateVector', () => { @@ -57,7 +61,12 @@ describe('validateVectorPair', () => { describe('validateEmbeddings', () => { it('passes for valid embeddings', () => { - expect(() => validateEmbeddings([[1, 2], [3, 4]])).not.toThrow(); + expect(() => + validateEmbeddings([ + [1, 2], + [3, 4], + ]) + ).not.toThrow(); }); it('throws for empty array', () => { @@ -65,6 +74,11 @@ describe('validateEmbeddings', () => { }); it('throws DimensionMismatchError for mixed dimensions', () => { - expect(() => validateEmbeddings([[1, 2], [1, 2, 3]])).toThrow(DimensionMismatchError); + expect(() => + validateEmbeddings([ + [1, 2], + [1, 2, 3], + ]) + ).toThrow(DimensionMismatchError); }); }); diff --git a/tests/math/dimensions.test.ts b/tests/math/dimensions.test.ts index db3049d..66e6617 100644 --- a/tests/math/dimensions.test.ts +++ b/tests/math/dimensions.test.ts @@ -75,10 +75,7 @@ describe('truncateDimensions (batch)', () => { }); it('accepts Float32Array batch', () => { - const batch = [ - new Float32Array([1, 2, 3]), - new Float32Array([4, 5, 6]), - ]; + const batch = [new Float32Array([1, 2, 3]), new Float32Array([4, 5, 6])]; const result = truncateDimensions(batch, 2); expect(result).toHaveLength(2); expect(result[0]).toHaveLength(2); @@ -139,21 +136,35 @@ describe('truncateDimensions auto-normalize', () => { describe('validateDimensions', () => { it('returns valid for consistent dimensions', () => { - const result = validateDimensions([[1, 2], [3, 4], [5, 6]]); + const result = validateDimensions([ + [1, 2], + [3, 4], + [5, 6], + ]); expect(result.valid).toBe(true); expect(result.dimension).toBe(2); expect(result.mismatches).toEqual([]); }); it('returns invalid with correct mismatch indices', () => { - const result = validateDimensions([[1, 2], [3, 4, 5], [6, 7]]); + const result = validateDimensions([ + [1, 2], + [3, 4, 5], + [6, 7], + ]); expect(result.valid).toBe(false); expect(result.dimension).toBe(2); expect(result.mismatches).toEqual([1]); }); it('validates against expectedDim', () => { - const result = validateDimensions([[1, 2], [3, 4]], 3); + const result = validateDimensions( + [ + [1, 2], + [3, 4], + ], + 3 + ); expect(result.valid).toBe(false); expect(result.dimension).toBe(3); expect(result.mismatches).toEqual([0, 1]); diff --git a/tests/models/manager.test.ts b/tests/models/manager.test.ts index 92193ee..f99e7b8 100644 --- a/tests/models/manager.test.ts +++ b/tests/models/manager.test.ts @@ -47,7 +47,7 @@ describe('model manager', () => { expect(mockPipeline).toHaveBeenCalledWith( 'feature-extraction', 'Xenova/all-MiniLM-L12-v2', - expect.any(Object), + expect.any(Object) ); expect(typeof result).toBe('string'); }); @@ -60,7 +60,7 @@ describe('model manager', () => { expect(mockPipeline).toHaveBeenCalledWith( 'feature-extraction', 'Xenova/all-MiniLM-L6-v2', - expect.objectContaining({ cache_dir: '/custom/cache' }), + expect.objectContaining({ cache_dir: '/custom/cache' }) ); }); }); @@ -95,10 +95,10 @@ describe('model manager', () => { await deleteModel('Xenova/all-MiniLM-L12-v2', '/cache/dir'); - expect(mockRm).toHaveBeenCalledWith( - expect.stringContaining('Xenova--all-MiniLM-L12-v2'), - { recursive: true, force: true }, - ); + expect(mockRm).toHaveBeenCalledWith(expect.stringContaining('Xenova--all-MiniLM-L12-v2'), { + recursive: true, + force: true, + }); }); }); @@ -110,10 +110,7 @@ describe('model manager', () => { await listModels(); - expect(mockReaddir).toHaveBeenCalledWith( - '/my/custom/path', - expect.any(Object), - ); + expect(mockReaddir).toHaveBeenCalledWith('/my/custom/path', expect.any(Object)); // Reset for other tests setModelPath(''); diff --git a/tests/models/registry.test.ts b/tests/models/registry.test.ts index c282aee..e1e892c 100644 --- a/tests/models/registry.test.ts +++ b/tests/models/registry.test.ts @@ -36,22 +36,37 @@ describe('registerModel', () => { it('rejects empty model ID', () => { expect(() => - registerModel({ id: '', dimensions: 128, maxTokens: 256, description: 'bad' }), + registerModel({ id: '', dimensions: 128, maxTokens: 256, description: 'bad' }) ).toThrow(ValidationError); }); it('rejects non-positive dimensions', () => { expect(() => - registerModel({ id: 'test-org/another-model', dimensions: 0, maxTokens: 256, description: 'bad' }), + registerModel({ + id: 'test-org/another-model', + dimensions: 0, + maxTokens: 256, + description: 'bad', + }) ).toThrow(ValidationError); expect(() => - registerModel({ id: 'test-org/another-model', dimensions: -1, maxTokens: 256, description: 'bad' }), + registerModel({ + id: 'test-org/another-model', + dimensions: -1, + maxTokens: 256, + description: 'bad', + }) ).toThrow(ValidationError); }); it('rejects non-integer dimensions', () => { expect(() => - registerModel({ id: 'test-org/another-model', dimensions: 3.5, maxTokens: 256, description: 'bad' }), + registerModel({ + id: 'test-org/another-model', + dimensions: 3.5, + maxTokens: 256, + description: 'bad', + }) ).toThrow(ValidationError); }); }); diff --git a/tests/pipeline/checkpoint.test.ts b/tests/pipeline/checkpoint.test.ts index 18b3828..8eb0483 100644 --- a/tests/pipeline/checkpoint.test.ts +++ b/tests/pipeline/checkpoint.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import { describe, it, expect } from 'vitest'; import { createEmbeddingPipeline } from '../../src/pipeline/pipeline'; import type { CheckpointAdapter, CheckpointState } from '../../src/pipeline/checkpoint'; import type { EmbeddingProvider, EmbeddingResult } from '../../src/types'; @@ -23,7 +23,7 @@ function createMockProvider(dims: number = 3): EmbeddingProvider & { callLog: st } function createInMemoryCheckpoint( - initialState: CheckpointState | null = null, + initialState: CheckpointState | null = null ): CheckpointAdapter & { saved: CheckpointState[]; loadCalls: number } { const adapter = { state: initialState, diff --git a/tests/pipeline/pipeline.test.ts b/tests/pipeline/pipeline.test.ts index 02bf2d4..75c2756 100644 --- a/tests/pipeline/pipeline.test.ts +++ b/tests/pipeline/pipeline.test.ts @@ -44,7 +44,9 @@ describe('batchIterator', () => { // ── Task 7.5: Pipeline End-to-End ─────────────────────────────────────────── -function createMockProvider(dims: number = 3): EmbeddingProvider & { callCount: number; concurrentCalls: number; maxConcurrent: number } { +function createMockProvider( + dims: number = 3 +): EmbeddingProvider & { callCount: number; concurrentCalls: number; maxConcurrent: number } { const provider = { name: 'mock', dimensions: dims, diff --git a/tests/providers/cohere.test.ts b/tests/providers/cohere.test.ts index 5a7ca51..36ad2e4 100644 --- a/tests/providers/cohere.test.ts +++ b/tests/providers/cohere.test.ts @@ -107,7 +107,10 @@ describe('createCohereProvider', () => { it('should parse embeddings.float response', async () => { const response = { embeddings: { - float: [[0.1, 0.2], [0.3, 0.4]], + float: [ + [0.1, 0.2], + [0.3, 0.4], + ], }, meta: { billed_units: { input_tokens: 8 } }, }; diff --git a/tests/providers/factory.test.ts b/tests/providers/factory.test.ts index f9e3adf..caa84c4 100644 --- a/tests/providers/factory.test.ts +++ b/tests/providers/factory.test.ts @@ -55,7 +55,7 @@ describe('createProvider', () => { mockFetchResponse({ data: [{ embedding: [0.1], index: 0 }], usage: { total_tokens: 1 }, - }), + }) ); const provider = createProvider('voyage', { @@ -74,7 +74,7 @@ describe('createProvider', () => { mockFetchResponse({ data: [{ embedding: [0.1], index: 0 }], usage: { total_tokens: 1 }, - }), + }) ); const provider = createProvider('mistral', { @@ -93,7 +93,7 @@ describe('createProvider', () => { mockFetchResponse({ data: [{ embedding: [0.1], index: 0 }], usage: { total_tokens: 1 }, - }), + }) ); const provider = createProvider('jina', { @@ -112,7 +112,7 @@ describe('createProvider', () => { mockFetchResponse({ data: [{ embedding: [0.1], index: 0 }], usage: { total_tokens: 1 }, - }), + }) ); const provider = createProvider('openrouter', { @@ -131,7 +131,7 @@ describe('createProvider', () => { mockFetchResponse({ data: [{ embedding: [0.1], index: 0 }], usage: { total_tokens: 1 }, - }), + }) ); const provider = createProvider('together', { @@ -150,7 +150,7 @@ describe('createProvider', () => { mockFetchResponse({ data: [{ embedding: [0.1], index: 0 }], usage: { total_tokens: 1 }, - }), + }) ); const provider = createProvider('fireworks', { @@ -169,7 +169,7 @@ describe('createProvider', () => { mockFetchResponse({ data: [{ embedding: [0.1], index: 0 }], usage: { total_tokens: 1 }, - }), + }) ); const provider = createProvider('nomic', { @@ -188,7 +188,7 @@ describe('createProvider', () => { mockFetchResponse({ data: [{ embedding: [0.1], index: 0 }], usage: { total_tokens: 1 }, - }), + }) ); const provider = createProvider('mixedbread', { diff --git a/tests/providers/google.test.ts b/tests/providers/google.test.ts index 1f96d7d..69a7346 100644 --- a/tests/providers/google.test.ts +++ b/tests/providers/google.test.ts @@ -29,9 +29,7 @@ describe('createGoogleVertexProvider', () => { }; const successResponse = { - predictions: [ - { embeddings: { values: [0.1, 0.2, 0.3] } }, - ], + predictions: [{ embeddings: { values: [0.1, 0.2, 0.3] } }], }; it('should have correct provider name and dimensions', () => { @@ -48,7 +46,7 @@ describe('createGoogleVertexProvider', () => { const [url] = fetchSpy.mock.calls[0]; expect(url).toBe( - 'https://us-central1-aiplatform.googleapis.com/v1/projects/my-project/locations/us-central1/publishers/google/models/text-embedding-005:predict', + 'https://us-central1-aiplatform.googleapis.com/v1/projects/my-project/locations/us-central1/publishers/google/models/text-embedding-005:predict' ); }); @@ -105,14 +103,10 @@ describe('createGoogleVertexProvider', () => { }); await provider.embed('first'); - expect(fetchSpy.mock.calls[0][1].headers['Authorization']).toBe( - 'Bearer dynamic-token-1', - ); + expect(fetchSpy.mock.calls[0][1].headers['Authorization']).toBe('Bearer dynamic-token-1'); await provider.embed('second'); - expect(fetchSpy.mock.calls[1][1].headers['Authorization']).toBe( - 'Bearer dynamic-token-2', - ); + expect(fetchSpy.mock.calls[1][1].headers['Authorization']).toBe('Bearer dynamic-token-2'); expect(tokenFn).toHaveBeenCalledTimes(2); }); @@ -129,10 +123,7 @@ describe('createGoogleVertexProvider', () => { it('should handle batch input', async () => { const batchResponse = { - predictions: [ - { embeddings: { values: [0.1, 0.2] } }, - { embeddings: { values: [0.3, 0.4] } }, - ], + predictions: [{ embeddings: { values: [0.1, 0.2] } }, { embeddings: { values: [0.3, 0.4] } }], }; fetchSpy.mockResolvedValue(mockFetchResponse(batchResponse)); diff --git a/tests/providers/middleware.test.ts b/tests/providers/middleware.test.ts index 323756d..6bf8a97 100644 --- a/tests/providers/middleware.test.ts +++ b/tests/providers/middleware.test.ts @@ -2,12 +2,14 @@ import { describe, it, expect, vi } from 'vitest'; import { withCache } from '../../src/providers/middleware'; import type { EmbeddingProvider, EmbeddingResult } from '../../src/types'; -function createMockProvider(embeddings: number[][] = [[0.1, 0.2, 0.3]]): EmbeddingProvider & { embedCalls: number } { +function createMockProvider( + embeddings: number[][] = [[0.1, 0.2, 0.3]] +): EmbeddingProvider & { embedCalls: number } { const mock = { name: 'mock', dimensions: 3, embedCalls: 0, - async embed(input: string | string[]): Promise { + async embed(_input: string | string[]): Promise { mock.embedCalls++; return { embeddings, @@ -91,7 +93,7 @@ describe('withCache', () => { it('supports custom hashFunction', async () => { const provider = createMockProvider(); - const hashFn = vi.fn((key: string) => 'fixed-hash'); + const hashFn = vi.fn((_key: string) => 'fixed-hash'); const cached = withCache(provider, { hashFunction: hashFn }); await cached.embed('hello'); @@ -102,7 +104,10 @@ describe('withCache', () => { }); it('handles array input', async () => { - const provider = createMockProvider([[0.1, 0.2], [0.3, 0.4]]); + const provider = createMockProvider([ + [0.1, 0.2], + [0.3, 0.4], + ]); const cached = withCache(provider); await cached.embed(['hello', 'world']); diff --git a/tests/providers/shared.test.ts b/tests/providers/shared.test.ts index 6390034..8f3fa3a 100644 --- a/tests/providers/shared.test.ts +++ b/tests/providers/shared.test.ts @@ -42,32 +42,26 @@ describe('retryWithBackoff', () => { }); it('should NOT retry on 4xx (except 429)', async () => { - const fn = vi - .fn() - .mockRejectedValue(new ProviderError('bad request', 'test', 400)); + const fn = vi.fn().mockRejectedValue(new ProviderError('bad request', 'test', 400)); - await expect( - retryWithBackoff(fn, { maxRetries: 3, baseDelay: 1 }), - ).rejects.toThrow('bad request'); + await expect(retryWithBackoff(fn, { maxRetries: 3, baseDelay: 1 })).rejects.toThrow( + 'bad request' + ); expect(fn).toHaveBeenCalledTimes(1); }); it('should NOT retry on non-ProviderError', async () => { const fn = vi.fn().mockRejectedValue(new Error('unknown')); - await expect( - retryWithBackoff(fn, { maxRetries: 3, baseDelay: 1 }), - ).rejects.toThrow('unknown'); + await expect(retryWithBackoff(fn, { maxRetries: 3, baseDelay: 1 })).rejects.toThrow('unknown'); expect(fn).toHaveBeenCalledTimes(1); }); it('should respect maxRetries', async () => { - const fn = vi - .fn() - .mockRejectedValue(new ProviderError('server error', 'test', 500)); + const fn = vi.fn().mockRejectedValue(new ProviderError('server error', 'test', 500)); await expect( - retryWithBackoff(fn, { maxRetries: 2, baseDelay: 1, maxDelay: 10 }), + retryWithBackoff(fn, { maxRetries: 2, baseDelay: 1, maxDelay: 10 }) ).rejects.toThrow('server error'); // Initial call + 2 retries = 3 total expect(fn).toHaveBeenCalledTimes(3); @@ -75,7 +69,6 @@ describe('retryWithBackoff', () => { it('should increase delays exponentially', async () => { const delays: number[] = []; - const originalSetTimeout = globalThis.setTimeout; vi.spyOn(globalThis, 'setTimeout').mockImplementation((fn: any, delay?: number) => { if (delay !== undefined && delay > 0) delays.push(delay); // Execute immediately @@ -121,7 +114,7 @@ describe('retryWithBackoff', () => { }); await expect( - retryWithBackoff(fn, { maxRetries: 3, baseDelay: 1 }, controller.signal), + retryWithBackoff(fn, { maxRetries: 3, baseDelay: 1 }, controller.signal) ).rejects.toThrow(/abort/i); vi.restoreAllMocks(); @@ -171,7 +164,10 @@ describe('autoBatch', () => { }); const result = await autoBatch(['a', 'b'], 10, fn); - expect(result).toEqual([[1, 2], [1, 2]]); + expect(result).toEqual([ + [1, 2], + [1, 2], + ]); expect(fn).toHaveBeenCalledTimes(1); }); diff --git a/tests/providers/timeout.test.ts b/tests/providers/timeout.test.ts index 06903f7..0ccc48f 100644 --- a/tests/providers/timeout.test.ts +++ b/tests/providers/timeout.test.ts @@ -21,7 +21,7 @@ describe('provider timeouts', () => { init?.signal?.addEventListener('abort', () => { reject(init.signal!.reason); }); - }), + }) ); vi.stubGlobal('fetch', hangingFetch); } diff --git a/tests/quantization/calibration.test.ts b/tests/quantization/calibration.test.ts index a011c0e..b061b86 100644 --- a/tests/quantization/calibration.test.ts +++ b/tests/quantization/calibration.test.ts @@ -1,5 +1,9 @@ import { describe, it, expect } from 'vitest'; -import { calibrate, calibratedQuantize, calibratedDequantize } from '../../src/quantization/calibration'; +import { + calibrate, + calibratedQuantize, + calibratedDequantize, +} from '../../src/quantization/calibration'; import { quantize, dequantize } from '../../src/quantization/quantize'; import { ValidationError } from '../../src/types'; diff --git a/tests/search/filter.test.ts b/tests/search/filter.test.ts index dd977eb..216dcd0 100644 --- a/tests/search/filter.test.ts +++ b/tests/search/filter.test.ts @@ -5,7 +5,7 @@ import { aboveThreshold } from '../../src/search/threshold'; describe('topK with filter', () => { const query = [1, 0, 0]; const corpus = [ - [1, 0, 0], // index 0 (even) + [1, 0, 0], // index 0 (even) [0.9, 0.1, 0], // index 1 (odd) [0.8, 0.2, 0], // index 2 (even) [0.7, 0.3, 0], // index 3 (odd) @@ -48,10 +48,10 @@ describe('topK with filter', () => { describe('aboveThreshold with filter', () => { const query = [1, 0, 0]; const corpus = [ - [1, 0, 0], // index 0, very high score + [1, 0, 0], // index 0, very high score [0.95, 0.05, 0], // index 1, high score - [0.9, 0.1, 0], // index 2, high score - [0, 1, 0], // index 3, low score + [0.9, 0.1, 0], // index 2, high score + [0, 1, 0], // index 3, low score ]; it('filters out even indices', () => { diff --git a/tests/search/hnsw.test.ts b/tests/search/hnsw.test.ts index e577e4e..fcf01ba 100644 --- a/tests/search/hnsw.test.ts +++ b/tests/search/hnsw.test.ts @@ -170,7 +170,7 @@ describe('HNSWIndex — search accuracy', () => { const bfIds = bfResults.map((r) => r.id); const overlap = bfIds.filter((id) => hnswIds.has(id)).length; expect(overlap).toBeGreaterThanOrEqual(3); - }, + } ); it('filter option restricts results', () => { diff --git a/tests/search/mmr.test.ts b/tests/search/mmr.test.ts index abb5ed1..c777e22 100644 --- a/tests/search/mmr.test.ts +++ b/tests/search/mmr.test.ts @@ -4,11 +4,11 @@ import { mmrSearch } from '../../src/search/mmr'; describe('mmrSearch', () => { const query = [1, 0, 0]; const corpus = [ - [1, 0, 0], // index 0: identical to query + [1, 0, 0], // index 0: identical to query [0.99, 0.01, 0], // index 1: very similar to query and index 0 - [0, 1, 0], // index 2: orthogonal/diverse - [0, 0, 1], // index 3: orthogonal/diverse - [-1, 0, 0], // index 4: opposite + [0, 1, 0], // index 2: orthogonal/diverse + [0, 0, 1], // index 3: orthogonal/diverse + [-1, 0, 0], // index 4: opposite ]; it('with lambda=1.0 matches topK ordering (pure relevance)', () => { diff --git a/tests/search/pairwise.test.ts b/tests/search/pairwise.test.ts index e3ee753..52bc15e 100644 --- a/tests/search/pairwise.test.ts +++ b/tests/search/pairwise.test.ts @@ -17,8 +17,14 @@ describe('pairwiseSimilarity', () => { }); it('computes element-wise similarity', () => { - const listA = [[1, 0, 0], [0, 1, 0]]; - const listB = [[0, 1, 0], [0, 1, 0]]; + const listA = [ + [1, 0, 0], + [0, 1, 0], + ]; + const listB = [ + [0, 1, 0], + [0, 1, 0], + ]; const scores = pairwiseSimilarity(listA, listB); expect(scores).toHaveLength(2); expect(scores[0]).toBeCloseTo(0); // orthogonal @@ -26,7 +32,10 @@ describe('pairwiseSimilarity', () => { }); it('throws ValidationError for different lengths', () => { - const listA = [[1, 0], [0, 1]]; + const listA = [ + [1, 0], + [0, 1], + ]; const listB = [[1, 0]]; expect(() => pairwiseSimilarity(listA, listB)).toThrow(ValidationError); }); diff --git a/tests/search/rank.test.ts b/tests/search/rank.test.ts index 488268a..ffe8465 100644 --- a/tests/search/rank.test.ts +++ b/tests/search/rank.test.ts @@ -4,10 +4,10 @@ import { rankBySimilarity } from '../../src/search/rank'; describe('rankBySimilarity', () => { const query = [1, 0, 0]; const corpus = [ - [0, 1, 0], // orthogonal - [1, 0, 0], // identical + [0, 1, 0], // orthogonal + [1, 0, 0], // identical [0.9, 0.1, 0], // very similar - [-1, 0, 0], // opposite + [-1, 0, 0], // opposite ]; it('ranks corpus by similarity descending', () => { diff --git a/tests/search/rerank.test.ts b/tests/search/rerank.test.ts index 361a7e1..8c5bb32 100644 --- a/tests/search/rerank.test.ts +++ b/tests/search/rerank.test.ts @@ -8,8 +8,8 @@ describe('rerankResults', () => { // Result at index 1 has high original score but low actual similarity // Result at index 0 has low original score but high actual similarity const results = [ - { index: 0, score: 0.1, embedding: [1, 0, 0] }, // low original, high cosine sim (1.0) - { index: 1, score: 0.9, embedding: [0, 1, 0] }, // high original, low cosine sim (0.0) + { index: 0, score: 0.1, embedding: [1, 0, 0] }, // low original, high cosine sim (1.0) + { index: 1, score: 0.9, embedding: [0, 1, 0] }, // high original, low cosine sim (0.0) ]; const reranked = rerankResults(results, query); @@ -34,9 +34,7 @@ describe('rerankResults', () => { }); it('default weights are 0.5/0.5', () => { - const results = [ - { index: 0, score: 0.6, embedding: [1, 0, 0] }, - ]; + const results = [{ index: 0, score: 0.6, embedding: [1, 0, 0] }]; const reranked = rerankResults(results, query); // 0.5 * 0.6 + 0.5 * 1.0 = 0.8 expect(reranked[0].score).toBeCloseTo(0.8); diff --git a/tests/search/threshold.test.ts b/tests/search/threshold.test.ts index 78728fa..9544102 100644 --- a/tests/search/threshold.test.ts +++ b/tests/search/threshold.test.ts @@ -4,10 +4,10 @@ import { aboveThreshold, deduplicate } from '../../src/search/threshold'; describe('aboveThreshold', () => { const query = [1, 0, 0]; const corpus = [ - [1, 0, 0], // similarity = 1.0 + [1, 0, 0], // similarity = 1.0 [0.9, 0.1, 0], // high similarity - [0, 1, 0], // similarity = 0.0 - [-1, 0, 0], // similarity = -1.0 + [0, 1, 0], // similarity = 0.0 + [-1, 0, 0], // similarity = -1.0 ]; it('returns embeddings with similarity >= threshold', () => { @@ -51,8 +51,8 @@ describe('deduplicate', () => { it('removes near-duplicate embeddings (keeps first)', () => { const embeddings = [ [1, 0, 0], - [1, 0, 0], // exact duplicate - [0, 1, 0], // unique + [1, 0, 0], // exact duplicate + [0, 1, 0], // unique ]; const result = deduplicate(embeddings, 0.99); expect(result.embeddings).toHaveLength(2); diff --git a/tests/search/topk.test.ts b/tests/search/topk.test.ts index 5493592..dad45c6 100644 --- a/tests/search/topk.test.ts +++ b/tests/search/topk.test.ts @@ -5,10 +5,10 @@ import { ValidationError } from '../../src/types'; describe('topK', () => { const query = [1, 0, 0]; const corpus = [ - [1, 0, 0], // identical to query - [0, 1, 0], // orthogonal + [1, 0, 0], // identical to query + [0, 1, 0], // orthogonal [0.9, 0.1, 0], // very similar - [-1, 0, 0], // opposite + [-1, 0, 0], // opposite ]; it('returns k most similar embeddings in descending order', () => { diff --git a/tests/search/validation.test.ts b/tests/search/validation.test.ts index 01cc0a0..6dce589 100644 --- a/tests/search/validation.test.ts +++ b/tests/search/validation.test.ts @@ -6,20 +6,30 @@ import { DimensionMismatchError, ValidationError } from '../../src/types'; describe('Search dimension validation', () => { const query3d = [1, 0, 0]; - const corpus2d = [[1, 0], [0, 1]]; + const corpus2d = [ + [1, 0], + [0, 1], + ]; it('topK throws DimensionMismatchError for mismatched query/corpus', () => { expect(() => topK(query3d, corpus2d, 1)).toThrow(DimensionMismatchError); - expect(() => topK(query3d, corpus2d, 1)).toThrow(/Query dimension \(3\) does not match corpus dimension \(2\)/); + expect(() => topK(query3d, corpus2d, 1)).toThrow( + /Query dimension \(3\) does not match corpus dimension \(2\)/ + ); }); it('aboveThreshold throws DimensionMismatchError for mismatched query/corpus', () => { expect(() => aboveThreshold(query3d, corpus2d, 0.5)).toThrow(DimensionMismatchError); - expect(() => aboveThreshold(query3d, corpus2d, 0.5)).toThrow(/Query dimension \(3\) does not match corpus dimension \(2\)/); + expect(() => aboveThreshold(query3d, corpus2d, 0.5)).toThrow( + /Query dimension \(3\) does not match corpus dimension \(2\)/ + ); }); it('similarityMatrix throws DimensionMismatchError for mixed dimensions', () => { - const mixed = [[1, 0, 0], [1, 0]]; + const mixed = [ + [1, 0, 0], + [1, 0], + ]; expect(() => similarityMatrix(mixed)).toThrow(DimensionMismatchError); }); @@ -36,7 +46,10 @@ describe('Search dimension validation', () => { describe('Search parameter validation', () => { const query = [1, 0, 0]; - const corpus = [[1, 0, 0], [0, 1, 0]]; + const corpus = [ + [1, 0, 0], + [0, 1, 0], + ]; it('topK throws ValidationError for k = 0', () => { expect(() => topK(query, corpus, 0)).toThrow(ValidationError); @@ -58,7 +71,9 @@ describe('Search parameter validation', () => { it('aboveThreshold throws ValidationError for Infinity threshold', () => { expect(() => aboveThreshold(query, corpus, Infinity)).toThrow(ValidationError); - expect(() => aboveThreshold(query, corpus, Infinity)).toThrow(/threshold must be a finite number/); + expect(() => aboveThreshold(query, corpus, Infinity)).toThrow( + /threshold must be a finite number/ + ); }); it('aboveThreshold throws ValidationError for NaN threshold', () => { diff --git a/tests/storage/serialize-v2.test.ts b/tests/storage/serialize-v2.test.ts index 80e6b60..61a02ca 100644 --- a/tests/storage/serialize-v2.test.ts +++ b/tests/storage/serialize-v2.test.ts @@ -66,25 +66,6 @@ describe('binary format v2', () => { describe('v1 backward compatibility', () => { it('deserializes v1 binary data (no version byte)', () => { // Manually craft v1 binary: [count:u32LE][dims:u32LE][float32LE * dims] per embedding - const embs = [[1.0, 2.0], [3.0, 4.0]]; - const totalBytes = 4 + embs.length * (4 + embs[0].length * 4); - const buffer = new ArrayBuffer(totalBytes); - const view = new DataView(buffer); - let offset = 0; - - view.setUint32(offset, embs.length, true); // count = 2 - offset += 4; - - for (const emb of embs) { - view.setUint32(offset, emb.length, true); // dims = 2 - offset += 4; - for (const val of emb) { - view.setFloat32(offset, val, true); - offset += 4; - } - } - - const v1Data = new Uint8Array(buffer); // First byte of v1 data is part of count (uint32LE for 2 = [2, 0, 0, 0]) // which is also 2 — same as V2_VERSION. But that's only when count=2. // For v1 with count != 2, the first byte differs. diff --git a/tests/store/embedding-store.test.ts b/tests/store/embedding-store.test.ts index 5a98f9a..17a1fef 100644 --- a/tests/store/embedding-store.test.ts +++ b/tests/store/embedding-store.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi } from 'vitest'; +import { describe, it, expect } from 'vitest'; import { createEmbeddingStore } from '../../src/store/embedding-store'; import type { EmbeddingProvider, EmbeddingResult } from '../../src/types'; @@ -16,7 +16,7 @@ function createMockProvider(): EmbeddingProvider & { embedCalls: number } { // Produce deterministic embeddings based on text hash const embeddings = inputs.map((text) => { const hash = text.split('').reduce((acc, c) => acc + c.charCodeAt(0), 0); - return [hash % 10 / 10, (hash * 7) % 10 / 10, (hash * 13) % 10 / 10]; + return [(hash % 10) / 10, ((hash * 7) % 10) / 10, ((hash * 13) % 10) / 10]; }); return { embeddings, model: 'mock', dimensions: 3 }; }, diff --git a/tests/text/create-tokenizer.test.ts b/tests/text/create-tokenizer.test.ts index 3811866..ca6cd71 100644 --- a/tests/text/create-tokenizer.test.ts +++ b/tests/text/create-tokenizer.test.ts @@ -34,7 +34,9 @@ describe('createTokenizer (real load)', () => { beforeAll(async () => { const { AutoTokenizer } = await import('@huggingface/transformers'); const autoTok = await AutoTokenizer.from_pretrained(MODEL); - reference = FIXED_STRINGS.map((s) => (autoTok(s) as { input_ids: { size: number } }).input_ids.size); + reference = FIXED_STRINGS.map( + (s) => (autoTok(s) as { input_ids: { size: number } }).input_ids.size + ); tok = createTokenizer(MODEL); await tok.load(); diff --git a/tests/text/markdown.test.ts b/tests/text/markdown.test.ts index 2a01077..70a83ff 100644 --- a/tests/text/markdown.test.ts +++ b/tests/text/markdown.test.ts @@ -225,8 +225,10 @@ Content another.`; describe('chunkByStructure — maxTokens and overlap', () => { it('respects maxTokens limit (no chunk exceeds it except code blocks)', () => { - const paragraphs = Array.from({ length: 10 }, (_, i) => - `Paragraph ${i} has several words that add up to a meaningful amount of content here.`, + const paragraphs = Array.from( + { length: 10 }, + (_, i) => + `Paragraph ${i} has several words that add up to a meaningful amount of content here.` ).join('\n\n'); const md = `# Section\n\n${paragraphs}`; const chunks = chunkByStructure(md, { maxTokens: 20 }); @@ -241,8 +243,9 @@ describe('chunkByStructure — maxTokens and overlap', () => { }); it('produces overlapping text when overlap option is set', () => { - const sentences = Array.from({ length: 20 }, (_, i) => - `Sentence number ${i} contains some words.`, + const sentences = Array.from( + { length: 20 }, + (_, i) => `Sentence number ${i} contains some words.` ).join(' '); const md = `# Section\n\n${sentences}`; const chunks = chunkByStructure(md, { maxTokens: 30, overlap: 10 }); diff --git a/tsconfig.json b/tsconfig.json index 0935853..e592dec 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,8 @@ "rootDir": "src", "esModuleInterop": true, "skipLibCheck": true, - "forceConsistentCasingInFileNames": true + "forceConsistentCasingInFileNames": true, + "ignoreDeprecations": "6.0" }, "include": ["src"] }