From b360f65f8b3e47e2e0797bb2d92add100b931fc8 Mon Sep 17 00:00:00 2001 From: Espen Hovlandsdal Date: Thu, 13 Aug 2026 13:49:30 -0700 Subject: [PATCH 1/4] test: replace waffletest with vitest across six environments --- .github/workflows/test.yml | 41 +- CONTRIBUTING.md | 19 + bun.lock | 343 +- deno.lock | 997 +++- package-lock.json | 4907 ++++++++++++++---- package.json | 27 +- test/browser/browser-test.html | 45 - test/browser/browser-test.ts | 39 - test/browser/client.browser.test.ts | 189 - test/bun/client.bun.test.ts | 26 - test/client.test.ts | 887 ++++ test/deno/client.deno.test.ts | 32 - test/fixtures.ts | 4 - test/helpers.ts | 232 - test/helpers/callCounter.ts | 96 + test/helpers/env.ts | 68 + test/helpers/fixtures.ts | 5 + test/helpers/globalSetup.ts | 32 + test/helpers/routes.ts | 27 + test/{ => helpers}/server.ts | 100 +- test/helpers/ssePlugin.ts | 33 + test/node/client.node.test.ts | 35 - test/tests.ts | 922 ---- test/waffletest/index.ts | 2 - test/waffletest/reporters/defaultReporter.ts | 32 - test/waffletest/reporters/helpers.ts | 25 - test/waffletest/reporters/nodeReporter.ts | 70 - test/waffletest/runner.ts | 156 - test/waffletest/types.ts | 58 - tsconfig.test.json | 16 + vitest.browser.config.ts | 27 + vitest.config.ts | 34 + vitest.happy-dom.config.ts | 27 + vitest.workerd.config.ts | 33 + 34 files changed, 6446 insertions(+), 3140 deletions(-) delete mode 100644 test/browser/browser-test.html delete mode 100644 test/browser/browser-test.ts delete mode 100644 test/browser/client.browser.test.ts delete mode 100644 test/bun/client.bun.test.ts create mode 100644 test/client.test.ts delete mode 100644 test/deno/client.deno.test.ts delete mode 100644 test/fixtures.ts delete mode 100644 test/helpers.ts create mode 100644 test/helpers/callCounter.ts create mode 100644 test/helpers/env.ts create mode 100644 test/helpers/fixtures.ts create mode 100644 test/helpers/globalSetup.ts create mode 100644 test/helpers/routes.ts rename test/{ => helpers}/server.ts (85%) create mode 100644 test/helpers/ssePlugin.ts delete mode 100644 test/node/client.node.test.ts delete mode 100644 test/tests.ts delete mode 100644 test/waffletest/index.ts delete mode 100644 test/waffletest/reporters/defaultReporter.ts delete mode 100644 test/waffletest/reporters/helpers.ts delete mode 100644 test/waffletest/reporters/nodeReporter.ts delete mode 100644 test/waffletest/runner.ts delete mode 100644 test/waffletest/types.ts create mode 100644 tsconfig.test.json create mode 100644 vitest.browser.config.ts create mode 100644 vitest.config.ts create mode 100644 vitest.happy-dom.config.ts create mode 100644 vitest.workerd.config.ts diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 530e8f34..40587c0c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,9 +27,9 @@ jobs: ${{ runner.os }}- - name: Install dependencies if: steps.cache-node-modules.outputs.cache-hit != 'true' - run: npx playwright install && npm ci + run: npm ci - name: Install Playwright Browsers - run: npx playwright install --with-deps + run: npx playwright install --with-deps chromium firefox webkit - name: Run browser tests run: npm run test:browser @@ -62,7 +62,7 @@ jobs: if: steps.cache-node-modules.outputs.cache-hit != 'true' run: npm ci - name: Run tests - run: npm run test:node + run: npm test testTypes: name: 'Test: Types' @@ -105,3 +105,38 @@ jobs: run: bun install --frozen-lockfile - name: Run tests run: npm run test:bun + + # Known-failing environments. These run so the failures stay visible, but they do not gate the + # rest of the matrix: happy-dom reports the test server's requests as cross-origin and blocks + # them, and workerd has its own set of issues (a null `MessageEvent.origin`, on-handlers firing + # twice, and handler ordering that differs from every other runtime). Both are being worked + # through separately - drop `continue-on-error` once they are green. + testHappyDom: + name: 'Test: happy-dom (allowed to fail)' + timeout-minutes: 15 + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-node@v7 + with: + node-version: 24 + - name: Install dependencies + run: npm ci + - name: Run tests + run: npm run test:happy-dom + + testWorkerd: + name: 'Test: Cloudflare Workers (allowed to fail)' + timeout-minutes: 15 + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-node@v7 + with: + node-version: 24 + - name: Install dependencies + run: npm ci + - name: Run tests + run: npm run test:workerd diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0ebc9dbd..7fd534f0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,6 +20,25 @@ npm run build npm test ``` +## Running the tests + +The suite in `test/client.test.ts` runs against a real HTTP server in every supported environment - there are no mocks and no simulated DOM. Each environment gets its own Vitest config, and `npm test` covers Node only: + +- `npm test` - Node.js +- `npm run test:browser` - Chromium, Firefox and WebKit, via Playwright +- `npm run test:bun` - Bun +- `npm run test:deno` - Deno +- `npm run test:happy-dom` - happy-dom +- `npm run test:workerd` - workerd (Cloudflare Workers), via miniflare +- `npm run test:types` - type compatibility with the WhatWG `EventSource` +- `npm run test:all` - all of the above, in sequence + +The browser tests need Playwright's browsers installed once, with `npx playwright install chromium firefox webkit`. + +The happy-dom and workerd suites are expected to fail today and do not gate CI: happy-dom reports the test server's requests as cross-origin and blocks them, and workerd returns a null `MessageEvent.origin`, fires the `on*` handlers twice, and orders handlers differently from every other runtime. + +The browser suite is the one place where the endpoints are not served by a standalone server. Vitest serves the test page from its own Vite server, so the endpoints are mounted onto that same server (`test/helpers/ssePlugin.ts`) to keep the page and the endpoints same-origin. Serving them separately would make every request cross-origin and silently change what the CORS, cookie and redirect tests actually assert. + # Workflow guidelines - Anything in the `main` branch is scheduled for the next release and should generally be ready to released, although there are exceptions when there are multiple features that are dependent on each other. diff --git a/bun.lock b/bun.lock index 3df35952..bb6a0f3f 100644 --- a/bun.lock +++ b/bun.lock @@ -10,21 +10,24 @@ "devDependencies": { "@changesets/changelog-github": "^1.0.0", "@changesets/cli": "^3.0.0", + "@cloudflare/vitest-pool-workers": "^0.21.3", "@tsconfig/strictest": "^2.0.8", "@types/node": "^22.19.19", - "@types/sinon": "^21.0.1", - "esbuild": "^0.28.0", + "@vitest/browser": "^4.1.10", + "@vitest/browser-playwright": "^4.1.10", "eventsource-encoder": "^1.0.2", + "happy-dom": "^20.11.2", "oxfmt": "^0.52.0", "oxlint": "^1.67.0", "playwright": "^1.60.0", - "sinon": "^22.0.0", "typescript": "^7.0.0", - "undici": "^7.0.0", + "vitest": "^4.1.10", }, }, }, "packages": { + "@blazediff/core": ["@blazediff/core@1.9.1", "", {}, "sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA=="], + "@changesets/apply-release-plan": ["@changesets/apply-release-plan@8.0.0", "", { "dependencies": { "@changesets/config": "^4.0.0", "@changesets/format": "^0.1.1", "@changesets/git": "^4.0.0", "@changesets/should-skip-package": "^1.0.0", "@changesets/types": "^7.0.0", "import-meta-resolve": "^4.2.0", "jsonc-parser": "^3.3.1", "semver": "^7.8.1" } }, "sha512-kUd2pbf1w5/AYmBMb0Tt+rkIPCjFJdT0SZMrkOjJT/WV/QbtmvkyB5jkV0oaNPheavprZk+SfUiozUti7TIL2w=="], "@changesets/assemble-release-plan": ["@changesets/assemble-release-plan@7.0.0", "", { "dependencies": { "@changesets/errors": "^1.0.0", "@changesets/get-dependents-graph": "^3.0.0", "@changesets/should-skip-package": "^1.0.0", "@changesets/types": "^7.0.0", "semver": "^7.8.1" } }, "sha512-oEW8BxdA604kGGtDSCiHr5w9Tv4UWe9I2k61IBNZzCOE1kbYaJj4v+lFQNgcEZFkUc2pV/+hASErGDvpJOZCTg=="], @@ -63,57 +66,137 @@ "@clack/prompts": ["@clack/prompts@1.7.0", "", { "dependencies": { "@clack/core": "1.4.3", "fast-string-width": "^3.0.2", "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ=="], + "@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.5.0", "", {}, "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg=="], + + "@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.16.1", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": ">1.20260305.0 <2.0.0-0" }, "optionalPeers": ["workerd"] }, "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw=="], + + "@cloudflare/vitest-pool-workers": ["@cloudflare/vitest-pool-workers@0.21.3", "", { "dependencies": { "cjs-module-lexer": "1.2.3", "esbuild": "0.28.1", "miniflare": "5.20260811.1-alpha", "wrangler": "4.123.0", "zod": "4.4.3" }, "peerDependencies": { "@vitest/runner": "^4.1.0", "@vitest/snapshot": "^4.1.0", "vitest": "^4.1.0" } }, "sha512-jCoGRQ6FlsP5adp1GJISvITOGdTHTpsWOq3KkSGIfeDY/5RKjTUagDwaXjpqBXY5gAk6id/QbgnGuCTAg6lSTQ=="], + + "@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260811.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-i5jqz+ywtOefr0AJbiAc8qxBLfSim/B0WJG7aW3B+pWnoVfMJdUQvi+BWcFKZJ0MoCci3KadTx6g31VfuEEqpQ=="], + + "@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260811.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-NoOUM/nvaDdm2Onlnz33FikWjtatzulNtvwvy4xs0IrHaTCHwC0c8NwIt6s+AI13FkDs02/vm2I3GTPLCT9+hQ=="], + + "@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260811.1", "", { "os": "linux", "cpu": "x64" }, "sha512-sdYq2jL1AD1supa3fsi5O4zTB28wSjvTHj7Migh6/ts8EROPdvrSwv+rdGHhv8HJNAz/wbIAY3wZsi1Rw4uUIg=="], + + "@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260811.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-RIRv4shbu1kg05sD+DHTpSFCNnb5Dl2SkPDMUykqZa508tkPqe7VVw7gO0Q5msTBGyL0FfFrLuRxwwfA8u5Sow=="], + + "@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260811.1", "", { "os": "win32", "cpu": "x64" }, "sha512-g6VquwjASlYAibcNW/0E6Zszht4qLkmnXOGwIjjRHl2A0Qz48kVeMcGvyH6eA0G9U3OzZojjYFpP+YeyQmmdjw=="], + + "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.11.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.28.1", "", { "os": "android", "cpu": "arm" }, "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.1", "", { "os": "android", "cpu": "arm64" }, "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.28.1", "", { "os": "android", "cpu": "x64" }, "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.1", "", { "os": "linux", "cpu": "arm" }, "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.1", "", { "os": "linux", "cpu": "x64" }, "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.1", "", { "os": "none", "cpu": "x64" }, "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ=="], - "@esbuild/android-arm": ["@esbuild/android-arm@0.28.2", "", { "os": "android", "cpu": "arm" }, "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg=="], + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA=="], - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.2", "", { "os": "android", "cpu": "arm64" }, "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A=="], + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg=="], - "@esbuild/android-x64": ["@esbuild/android-x64@0.28.2", "", { "os": "android", "cpu": "x64" }, "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q=="], + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="], - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw=="], + "@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="], - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw=="], + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.3.1" }, "os": "darwin", "cpu": "arm64" }, "sha512-eEieHsMksAW4IiO5NzauESRl2D2qz3J/kwUxUrSfV06A93eEaRfMpHXyUb1mAqrR7i8U9A0GRqE9pjn6u1Jjpg=="], - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw=="], + "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.3.1" }, "os": "darwin", "cpu": "x64" }, "sha512-BaktuGPCeHJMARpodR8jK4uKiZrPAy9WrfQW0sdI37clracq8Bp01AYS3SZgi5FS/y5twa9t4+LIuuxQjqRrWw=="], - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg=="], + "@img/sharp-freebsd-wasm32": ["@img/sharp-freebsd-wasm32@0.35.2", "", { "dependencies": { "@img/sharp-wasm32": "0.35.2" }, "os": "freebsd" }, "sha512-YoAxdnd8hPUkvLHd3bWY+YA8nw3xM/RyRopYucNsWHVSan8NLVM3X2volsfoRDcXdUJPg6tXahSd7HXPK7lRnw=="], - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.2", "", { "os": "linux", "cpu": "arm" }, "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w=="], + "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.3.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4V/M3roRMTYjiwZY9IOVQOE8OyeCxFAkYmyZDrZl51uOKjibm3oeEJ4WAmLxutAfzFbC9jqUiPs2gbnGflH+7g=="], - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug=="], + "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.3.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-c0/DxItpJv2+dGhgycJBBgotdqruGYDvA79drdh0MD1dFpy7JzJ/PlXwi1H4rFf0eTy8tgbI91aHDnZIceY3jQ=="], - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ=="], + "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.3.1", "", { "os": "linux", "cpu": "arm" }, "sha512-aGGy9aWzXgHBG7HNyQPWorZthlp7+x6fDRoPAQbGO3ThcttuTyKIx3NuSHb6zb4gBNq6/yNn9f1cy9nFKS/Vmg=="], - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.2", "", { "os": "linux", "cpu": "none" }, "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ=="], + "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-JznefmcK9j1JKPz8AkQDh89kjojubyfOasWBPKfzMIhPwsgDy9evpE/naJTXXXmghS1iFwR8u/kTwh/I2/+GCw=="], - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.2", "", { "os": "linux", "cpu": "none" }, "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA=="], + "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.3.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1EkwGNCZk6iWNCMWqrvdJ+r1j0PT1zIz60CNPhYnJlK/zyeWqlsPZIe+ocBVqPF8k/Ssee/NCk+tE9Ryrko6ng=="], - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ=="], + "@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.3.1", "", { "os": "linux", "cpu": "none" }, "sha512-Ilays+w2bXdnxzxtQdmXR62u8o8GYa3eL4+Gr+1KiE4xperMZUslRaVPJwwPkzlHEjGfXAfRVAa/7CYCtSqsBw=="], - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.2", "", { "os": "linux", "cpu": "none" }, "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA=="], + "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.3.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-VfBwVHQTbRoj4XlpA/KLZ7ltgMpz+4WSejFzQ+GnoImjo1PtEJ59QB2qR1xQEeRPYIkNrPIm2L4cICMvz4C2ew=="], - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg=="], + "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-+c8ukgwU62DS54nCAjw7keOfHUkmr0B5QHEdcOqRnodF/MNXJbVI8Eopoj4B/0H8Asr65I+A4Amrn7a85/md6A=="], - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.2", "", { "os": "linux", "cpu": "x64" }, "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ=="], + "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-qlKb/pwbkAi1WMsJrYHk7CuDrd12s27U2QnRhFYUoJNrRCmkosMTttuRFat/DDB3IlDm5qE1TJgZ4JDnHX8Ldw=="], - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.2", "", { "os": "none", "cpu": "arm64" }, "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw=="], + "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-yO21HwoUVLN8Qa+/SBjQLMYwBWAVJjeGPNe+hc0OUeMeifEtJqu5a1c4HayE1nNpDih9y3/KkoltfkDodmKAlg=="], - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.2", "", { "os": "none", "cpu": "x64" }, "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw=="], + "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.3.1" }, "os": "linux", "cpu": "arm" }, "sha512-SE4kzF2mepn6z+6E7L6lsV8FzuLL6IPQdyX8ZiwROAG/G8td+hP/m7FsFPwidtrF19gvajuC9l6TxAVcsA4S7A=="], - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ=="], + "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.3.1" }, "os": "linux", "cpu": "arm64" }, "sha512-af12Pnd0ZGu2HfP8NayB0kk6eC/lrfbQE6HlR4jD+34wdJ1Vw9TF6TMn6ZvffT+WgqVsl0hRbmNvz2u/23VmwA=="], - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw=="], + "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.3.1" }, "os": "linux", "cpu": "ppc64" }, "sha512-hYSBm7zcNtDCozCxQHYZJiu63b/bXsgRZuOxCIBZsStMM9Vap47iFHdbX4kCvQsblPB/k+clhELpdQJHQLSHvg=="], - "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.2", "", { "os": "none", "cpu": "arm64" }, "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q=="], + "@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.3.1" }, "os": "linux", "cpu": "none" }, "sha512-qQt0Kc13+Hoan/Awq/qMSQw3L+RI1NCRPgD5cUJ/1WSSmIoysLOc72jlRM3E0OHN9Yr313jgeQ2T+zW+F03QFA=="], - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g=="], + "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.3.1" }, "os": "linux", "cpu": "s390x" }, "sha512-E4fLLfRPzDLlEeDaTzI98OFLcv++WL5ChLLMwPoVd0CIoZQqupBSNbOisPL5am9XsbQ9T84+iiMpUvbFtkunbA=="], - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ=="], + "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.3.1" }, "os": "linux", "cpu": "x64" }, "sha512-gi0zFJJRLswfCZmHtJdikXPOc5u7qamSOS3NHedLqLd4W8Q0NqjdBr6TTRIgsfFjqfTsHFgdfvJ9LwqSgcHiAA=="], - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA=="], + "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.3.1" }, "os": "linux", "cpu": "arm64" }, "sha512-siWbOW1u6HFnFLrp0waKyW7VEf7jYvcDWdrXEFa8AkdAQgEvuu5Fz8/Y70w9EeqAdwDtfU012BhEHHaDqvQNzg=="], - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g=="], + "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.3.1" }, "os": "linux", "cpu": "x64" }, "sha512-YBqMMcjDi4QGYiSn4vNOYBhmlC4z5AXqkOUUqI2e0AFA4urNv4ESgOgwNl3K+4etQhha0twXlzeF20bbULm9Yg=="], + + "@img/sharp-wasm32": ["@img/sharp-wasm32@0.35.2", "", { "dependencies": { "@emnapi/runtime": "^1.11.1" } }, "sha512-Mrv4JQNYVQ94xH+jzZ9r+gowleN8mv2FTgKT+PI6bx5C0G8TdNYndu161pg2i7uoBwxy2ImPMHrJOM2LZef7Bw=="], + + "@img/sharp-webcontainers-wasm32": ["@img/sharp-webcontainers-wasm32@0.35.2", "", { "dependencies": { "@img/sharp-wasm32": "0.35.2" }, "cpu": "none" }, "sha512-QNV27pxs9wpApEiCfvHM1RDoP1w1+2KrUWWDPEhEwg+latvOrfuhWrHWZKwdSFwU6jh3myjw/yOCRsUIuOft3g=="], + + "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.35.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-BiVRYc/t6/Vl3e1hBx0hugG4oN9Pydf4fgMSpxTQJmwGUg/YoXTWHiFeRymHfCZzifxu4F4rpk/I67D0LQ20wQ=="], + + "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.35.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-YYEhx9PImCC7T0tI8JDMi4DB9LwLCXCU5OWNYEXAxh5Q1ShKkyC6byxzoBJ3gEFDnH2lQckWuDe70G7mB2XJog=="], + + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.35.2", "", { "os": "win32", "cpu": "x64" }, "sha512-imoOyBcoM/iiUr4J6VPpCNjPnjvP/Gks95898yB8YqoGGYmHYbOyCuNv9FMhFgtaiHFGbHW8bxKqRV6VjtXThQ=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], "@manypkg/find-root": ["@manypkg/find-root@3.1.0", "", { "dependencies": { "@manypkg/tools": "^2.1.0" } }, "sha512-BcSqCyKhBVZ5YkSzOiheMCV41kqAFptW6xGqYSTjkVTl9XQpr+pqHhwgGCOHQtjDCv7Is6EFyA14Sm5GVbVABA=="], @@ -121,6 +204,8 @@ "@manypkg/tools": ["@manypkg/tools@2.1.2", "", { "dependencies": { "jju": "^1.4.0", "tinyglobby": "^0.2.13", "yaml": "^2.9.0" } }, "sha512-6QEf6yqFbETdwGITKq57aYoPfX/3K8XFNwsAlx0C1M7o8cb79sv1M3w+tWuWvIcSbNqrLF7OD7YpZMVVz335hQ=="], + "@oxc-project/types": ["@oxc-project/types@0.144.0", "", {}, "sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg=="], + "@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.52.0", "", { "os": "android", "cpu": "arm" }, "sha512-17EMSJnQ9g+upVHrAUYDMfH5lvRKQ9Nvg8WtEoH72oDr1VpWz+7/o3tD97U1EToen2YAQ/68JmtDYkQUi20dfQ=="], "@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.52.0", "", { "os": "android", "cpu": "arm64" }, "sha512-A2G1IdwGEW2lLJkIxcvuirRH1CzSl/e0NX11zTlW1gvxJThfwbI/BEoaKrTNpm7M2FchvIf6guvIQU7d5iz+OQ=="], @@ -199,19 +284,63 @@ "@pnpm/deps.graph-sequencer": ["@pnpm/deps.graph-sequencer@1100.0.1", "", {}, "sha512-pOr5+q1fLYKwFN3LAJuGZEnfXDcQ73zqgDHMtGy+K+uIoUqyY+6MeDCWFwfu+4EFuq76I5EPFofoNAI+Bmmq4A=="], - "@sinonjs/commons": ["@sinonjs/commons@3.0.1", "", { "dependencies": { "type-detect": "4.0.8" } }, "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ=="], + "@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="], + + "@poppinss/colors": ["@poppinss/colors@4.1.6", "", { "dependencies": { "kleur": "^4.1.5" } }, "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg=="], + + "@poppinss/dumper": ["@poppinss/dumper@0.6.5", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@sindresorhus/is": "^7.0.2", "supports-color": "^10.0.0" } }, "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw=="], + + "@poppinss/exception": ["@poppinss/exception@1.2.3", "", {}, "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw=="], + + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.2.4", "", { "os": "android", "cpu": "arm64" }, "sha512-jHC2cnyKz5xU2fhECtFl8OZ83cYNt13GZQD+0uMJ/X3o+ijmd56okHhTUwxVSHPx1IRVIJEZ1/1pPzeLCU6XKA=="], + + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Dc5mPD8F5F/FS8i01syd7FTF6yB2fVthH/TRkjwJkzUK6EpoxHtqvZQP5Zwq80/5z19TWYHIg1KOHboCgVx/aQ=="], + + "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-fpDm4oBo6SqLvWUYCmFhdde3U9KH2fRNNMeAnAPAIwxRL345xutL0EtEUcuoxsoazdJGv/MuDBQHlCDrtbvqOg=="], + + "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.2.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-rSJoreDE/HoIzoaib6MTp5jQtCTdMHKIvItAKT/ImS6Y6Ww76oUaeMyp4Vc/fAgd/ehji068IxetHXAnqUwN9A=="], + + "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-/jm8OGHgn7oGaJu3i/qZI9spUGcJ+y/lk43ttQ/iO1tOd9NissG6o97bighBCiL+BKRngmcDuR6ikfwYdJmVuQ=="], - "@sinonjs/fake-timers": ["@sinonjs/fake-timers@15.4.0", "", { "dependencies": { "@sinonjs/commons": "^3.0.1" } }, "sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA=="], + "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-tIP06BeD9EqvECBrPZ+sqdPlYrT+aYaAiu1wYziVx5elRK/ftm33JxVDy2bXGbr6J0CrtirCkR87/X5a2euEng=="], - "@sinonjs/samsam": ["@sinonjs/samsam@10.0.2", "", { "dependencies": { "@sinonjs/commons": "^3.0.1", "type-detect": "^4.1.0" } }, "sha512-8lVwD1Df1BmzoaOLhMcGGcz/Jyr5QY2KSB75/YK1QgKzoabTeLdIVyhXNZK9ojfSKSdirbXqdbsXXqP9/Ve8+A=="], + "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-Ql1Q0EQqVThvn9VAVlwNzsUvbSFtCMGjLpRRi4pk5i7NZZ4n5ISiLMjHYtus4VQ2PvkSw24zyaCVsiS+sXPj1w=="], + + "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-GjbjXD4XXfN19D0LZNbmiCBUoDiRACsYHr0yaIbbn8aFsXjHZifcYqu/W5Er5X2X990WjHXFrxarn5chzItorQ=="], + + "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-p5WR0NOwaRmJ/B1b6IjEFLLivwEsf3PrdBIhRbhTCQisbo2SvHHpG4ELB/+FgQNnB88LTOF86upmJmbvZdQ2lw=="], + + "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-4/GyVjmhR+Tc6HLJvwc1sOhPqAZtySiSMesOZyX6JQ5XBxoTDEMKQzvo07NIK6nTon/SivlZqvhzvuVBNQhObQ=="], + + "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-l9eeLsCNvPpmSXUej0etw/J1eqV0Jj1D5G/xG6YTijmE6dkv6E2QezgWbTfQk63v952DPqrjOCoiqxq7Bw0YUQ=="], + + "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.2.4", "", { "os": "none", "cpu": "arm64" }, "sha512-e0F355MSTMm3+UOqtV3L24gFUp2N5m1f8L/7d56deik6va+AXdrt9F8LbzGpeWGWRbZEDq4m8NVnJDeBtf9DZg=="], + + "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.2.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-AWLi0uBRYh6QlE7OKhiz+phZC0qwtij2QZmhmOdsLdFn64m7oMpooE9ICE3lhm9xMb4SpDo2WbHcxX1iFLFtqw=="], + + "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.2.4", "", { "os": "win32", "cpu": "x64" }, "sha512-UwSDJOg3dqCAejWdxclJjCsh3Qq4vLYMDxmyHqo1btz3stK2VqgwNd3mm5tuIwzSlGIQ/1H9Hr+Zn09mrezNqQ=="], + + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="], + + "@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="], + + "@speed-highlight/core": ["@speed-highlight/core@1.2.24", "", {}, "sha512-qeW2e1l78afw8VhRPfPQ1Gjj+KU5XFQ/OFV5ti6eTa9bruO7mJyZtA4vw0ofqmA3tKCkROE9xLk3VZoeRc98nw=="], + + "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "@tsconfig/strictest": ["@tsconfig/strictest@2.0.8", "", {}, "sha512-XnQ7vNz5HRN0r88GYf1J9JJjqtZPiHt2woGJOo2dYqyHGGcd6OLGqSlBB6p1j9mpzja6Oe5BoPqWmeDx6X9rLw=="], + "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], + + "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], + + "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], + "@types/node": ["@types/node@22.20.1", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q=="], - "@types/sinon": ["@types/sinon@21.0.1", "", { "dependencies": { "@types/sinonjs__fake-timers": "*" } }, "sha512-5yoJSqLbjH8T9V2bksgRayuhpZy+723/z6wBOR+Soe4ZlXC0eW8Na71TeaZPUWDQvM7LYKa9UGFc6LRqxiR5fQ=="], + "@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="], - "@types/sinonjs__fake-timers": ["@types/sinonjs__fake-timers@15.0.1", "", {}, "sha512-Ko2tjWJq8oozHzHV+reuvS5KYIRAokHnGbDwGh/J64LntgpbuylF74ipEL24HCyRjf9FOlBiBHWBR1RlVKsI1w=="], + "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], "@typescript/typescript-aix-ppc64": ["@typescript/typescript-aix-ppc64@7.0.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ=="], @@ -253,18 +382,60 @@ "@typescript/typescript-win32-x64": ["@typescript/typescript-win32-x64@7.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g=="], + "@vitest/browser": ["@vitest/browser@4.1.10", "", { "dependencies": { "@blazediff/core": "1.9.1", "@vitest/mocker": "4.1.10", "@vitest/utils": "4.1.10", "magic-string": "^0.30.21", "pngjs": "^7.0.0", "sirv": "^3.0.2", "tinyrainbow": "^3.1.0", "ws": "^8.19.0" }, "peerDependencies": { "vitest": "4.1.10" } }, "sha512-UDwuWGwXj646CBx/bQHOaJSX7np0I8JL/UKQYa1e4QrVHH8VdWtx8eaOuf8sy0ShwDgR6NjJAsp5eF6vjF6qng=="], + + "@vitest/browser-playwright": ["@vitest/browser-playwright@4.1.10", "", { "dependencies": { "@vitest/browser": "4.1.10", "@vitest/mocker": "4.1.10", "tinyrainbow": "^3.1.0" }, "peerDependencies": { "playwright": "*", "vitest": "4.1.10" } }, "sha512-nMoXGEiRpT7m3W7NsbvrM2aKNwiNHZf+zEpUCvMteGjZFvfT96Q9fh7QyB98dvDWXiKvrLxA7bJ1mCOOv+JQPw=="], + + "@vitest/expect": ["@vitest/expect@4.1.10", "", { "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" } }, "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA=="], + + "@vitest/mocker": ["@vitest/mocker@4.1.10", "", { "dependencies": { "@vitest/spy": "4.1.10", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow=="], + + "@vitest/pretty-format": ["@vitest/pretty-format@4.1.10", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q=="], + + "@vitest/runner": ["@vitest/runner@4.1.10", "", { "dependencies": { "@vitest/utils": "4.1.10", "pathe": "^2.0.3" } }, "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg=="], + + "@vitest/snapshot": ["@vitest/snapshot@4.1.10", "", { "dependencies": { "@vitest/pretty-format": "4.1.10", "@vitest/utils": "4.1.10", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw=="], + + "@vitest/spy": ["@vitest/spy@4.1.10", "", {}, "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw=="], + + "@vitest/utils": ["@vitest/utils@4.1.10", "", { "dependencies": { "@vitest/pretty-format": "4.1.10", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA=="], + + "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], + + "blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="], + + "buffer-image-size": ["buffer-image-size@0.6.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ=="], + "cac": ["cac@7.0.0", "", {}, "sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ=="], + "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], + + "cjs-module-lexer": ["cjs-module-lexer@1.2.3", "", {}, "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ=="], + + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + + "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], + "dataloader": ["dataloader@2.2.3", "", {}, "sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA=="], - "diff": ["diff@9.0.0", "", {}, "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw=="], + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + + "entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], + + "error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="], + + "es-module-lexer": ["es-module-lexer@2.3.1", "", {}, "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA=="], - "esbuild": ["esbuild@0.28.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.2", "@esbuild/android-arm": "0.28.2", "@esbuild/android-arm64": "0.28.2", "@esbuild/android-x64": "0.28.2", "@esbuild/darwin-arm64": "0.28.2", "@esbuild/darwin-x64": "0.28.2", "@esbuild/freebsd-arm64": "0.28.2", "@esbuild/freebsd-x64": "0.28.2", "@esbuild/linux-arm": "0.28.2", "@esbuild/linux-arm64": "0.28.2", "@esbuild/linux-ia32": "0.28.2", "@esbuild/linux-loong64": "0.28.2", "@esbuild/linux-mips64el": "0.28.2", "@esbuild/linux-ppc64": "0.28.2", "@esbuild/linux-riscv64": "0.28.2", "@esbuild/linux-s390x": "0.28.2", "@esbuild/linux-x64": "0.28.2", "@esbuild/netbsd-arm64": "0.28.2", "@esbuild/netbsd-x64": "0.28.2", "@esbuild/openbsd-arm64": "0.28.2", "@esbuild/openbsd-x64": "0.28.2", "@esbuild/openharmony-arm64": "0.28.2", "@esbuild/sunos-x64": "0.28.2", "@esbuild/win32-arm64": "0.28.2", "@esbuild/win32-ia32": "0.28.2", "@esbuild/win32-x64": "0.28.2" }, "bin": "bin/esbuild" }, "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA=="], + "esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="], + + "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], "eventsource-encoder": ["eventsource-encoder@1.0.2", "", {}, "sha512-iG7mY5LhweLKpgxQ+YdW7Y6YjBgRzGMrKlXzeUpm0VtJpdeag32Q/DMQ11HAT7kO9Jx8dreUL5SHGl6KAGJ9Lg=="], "eventsource-parser": ["eventsource-parser@4.0.0", "", {}, "sha512-aIpvYxbqTx4KYWw73KpCt1Rh22tEAJ144F1qR76CT3Ex+LNMEPKf5HFrK5Yz9fMP1EVT0GrfA35VZvWQhMPuSQ=="], + "expect-type": ["expect-type@1.4.0", "", {}, "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA=="], + "fast-string-truncated-width": ["fast-string-truncated-width@3.0.3", "", {}, "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g=="], "fast-string-width": ["fast-string-width@3.0.2", "", { "dependencies": { "fast-string-truncated-width": "^3.0.2" } }, "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg=="], @@ -275,6 +446,8 @@ "fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], + "happy-dom": ["happy-dom@20.11.2", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "buffer-image-size": "^0.6.4", "entities": "^7.0.1", "whatwg-mimetype": "^3.0.0", "ws": "^8.21.0" } }, "sha512-7MB+bJLkxu3SowAfBJbjW+c55kNz5tkR45gu2qzrxznezhLeN5YIlJbwUgSzlGc+qWoZ8Ykg71H5ezz69xixrw=="], + "human-id": ["human-id@4.2.0", "", { "bin": "dist/cli.js" }, "sha512-K3GbkIWqyvvlpfhBPlbEvD97TtqBpAYA4kt+cn2lD2x2HuohzZCibcA2nOlnJT6exqvJLggoB5nv2dNf192nEA=="], "import-meta-resolve": ["import-meta-resolve@4.2.0", "", {}, "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="], @@ -283,14 +456,54 @@ "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], + "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], + "launch-editor": ["launch-editor@2.14.1", "", { "dependencies": { "picocolors": "^1.1.1", "shell-quote": "^1.8.4" } }, "sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA=="], + "lightningcss": ["lightningcss@1.33.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "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" } }, "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA=="], + + "lightningcss-android-arm64": ["lightningcss-android-arm64@1.33.0", "", { "os": "android", "cpu": "arm64" }, "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg=="], + + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.33.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg=="], + + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.33.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ=="], + + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.33.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg=="], + + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.33.0", "", { "os": "linux", "cpu": "arm" }, "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ=="], + + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.33.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg=="], + + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.33.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ=="], + + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.33.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg=="], + + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.33.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw=="], + + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.33.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA=="], + + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.33.0", "", { "os": "win32", "cpu": "x64" }, "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA=="], + + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "miniflare": ["miniflare@5.20260811.1-alpha", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "0.35.2", "undici": "7.29.0", "workerd": "1.20260811.1", "ws": "8.21.0", "youch": "4.1.0-beta.10" } }, "sha512-DtOG0BeanIxs2sH0smFvExZD89cBQwGckbHiFkRJrrNAUu3NGClZkUxqu+zy7HYfKBAgq935EMY49vIPm3JVdA=="], + + "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], + + "nanoid": ["nanoid@3.3.18", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w=="], + + "obug": ["obug@2.1.4", "", {}, "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA=="], + "oxfmt": ["oxfmt@0.52.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.52.0", "@oxfmt/binding-android-arm64": "0.52.0", "@oxfmt/binding-darwin-arm64": "0.52.0", "@oxfmt/binding-darwin-x64": "0.52.0", "@oxfmt/binding-freebsd-x64": "0.52.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.52.0", "@oxfmt/binding-linux-arm-musleabihf": "0.52.0", "@oxfmt/binding-linux-arm64-gnu": "0.52.0", "@oxfmt/binding-linux-arm64-musl": "0.52.0", "@oxfmt/binding-linux-ppc64-gnu": "0.52.0", "@oxfmt/binding-linux-riscv64-gnu": "0.52.0", "@oxfmt/binding-linux-riscv64-musl": "0.52.0", "@oxfmt/binding-linux-s390x-gnu": "0.52.0", "@oxfmt/binding-linux-x64-gnu": "0.52.0", "@oxfmt/binding-linux-x64-musl": "0.52.0", "@oxfmt/binding-openharmony-arm64": "0.52.0", "@oxfmt/binding-win32-arm64-msvc": "0.52.0", "@oxfmt/binding-win32-ia32-msvc": "0.52.0", "@oxfmt/binding-win32-x64-msvc": "0.52.0" }, "peerDependencies": { "svelte": "^5.0.0", "vite-plus": "*" }, "optionalPeers": ["svelte", "vite-plus"], "bin": "bin/oxfmt" }, "sha512-nJlYM35F64zTDMecCNhoHNkf+D/eHv7xcjj9XDSj+bFAVtN93m7v8DQMdHd6nDG6Akf/kEYYHmDUBs2Dz27Sug=="], "oxlint": ["oxlint@1.78.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.78.0", "@oxlint/binding-android-arm64": "1.78.0", "@oxlint/binding-darwin-arm64": "1.78.0", "@oxlint/binding-darwin-x64": "1.78.0", "@oxlint/binding-freebsd-x64": "1.78.0", "@oxlint/binding-linux-arm-gnueabihf": "1.78.0", "@oxlint/binding-linux-arm-musleabihf": "1.78.0", "@oxlint/binding-linux-arm64-gnu": "1.78.0", "@oxlint/binding-linux-arm64-musl": "1.78.0", "@oxlint/binding-linux-ppc64-gnu": "1.78.0", "@oxlint/binding-linux-riscv64-gnu": "1.78.0", "@oxlint/binding-linux-riscv64-musl": "1.78.0", "@oxlint/binding-linux-s390x-gnu": "1.78.0", "@oxlint/binding-linux-x64-gnu": "1.78.0", "@oxlint/binding-linux-x64-musl": "1.78.0", "@oxlint/binding-openharmony-arm64": "1.78.0", "@oxlint/binding-win32-arm64-msvc": "1.78.0", "@oxlint/binding-win32-ia32-msvc": "1.78.0", "@oxlint/binding-win32-x64-msvc": "1.78.0" }, "peerDependencies": { "oxlint-tsgolint": ">=7.0.2001", "vite-plus": "*" }, "optionalPeers": ["oxlint-tsgolint", "vite-plus"], "bin": "bin/oxlint" }, "sha512-QgQePuxIqKOzo1KSjG2EnITEeWvWnKAm77eq8nrMtf6AGoA+zyGc4PFYtDNJSD25g/ibOwfQ851hZ4/SPkMVoA=="], "package-manager-detector": ["package-manager-detector@1.8.0", "", {}, "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A=="], + "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], + + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "picomatch": ["picomatch@4.0.5", "", {}, "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="], @@ -299,21 +512,45 @@ "playwright-core": ["playwright-core@1.62.1", "", { "bin": "cli.js" }, "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw=="], + "pngjs": ["pngjs@7.0.0", "", {}, "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow=="], + + "postcss": ["postcss@8.5.26", "", { "dependencies": { "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ=="], + + "rolldown": ["rolldown@1.2.4", "", { "dependencies": { "@oxc-project/types": "=0.144.0", "@rolldown/pluginutils": "^1.0.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" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-rSr7irW0K7QRWzjdJXqZowkcRdDtjRduh43rBltnVKd0VFq839l1lJoDvGJb6gl7+4rTTCrPWu+YfujUL8Ug7w=="], + "semver": ["semver@7.8.5", "", { "bin": "bin/semver.js" }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], + "sharp": ["sharp@0.35.2", "", { "dependencies": { "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", "semver": "^7.8.4" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.35.2", "@img/sharp-darwin-x64": "0.35.2", "@img/sharp-freebsd-wasm32": "0.35.2", "@img/sharp-libvips-darwin-arm64": "1.3.1", "@img/sharp-libvips-darwin-x64": "1.3.1", "@img/sharp-libvips-linux-arm": "1.3.1", "@img/sharp-libvips-linux-arm64": "1.3.1", "@img/sharp-libvips-linux-ppc64": "1.3.1", "@img/sharp-libvips-linux-riscv64": "1.3.1", "@img/sharp-libvips-linux-s390x": "1.3.1", "@img/sharp-libvips-linux-x64": "1.3.1", "@img/sharp-libvips-linuxmusl-arm64": "1.3.1", "@img/sharp-libvips-linuxmusl-x64": "1.3.1", "@img/sharp-linux-arm": "0.35.2", "@img/sharp-linux-arm64": "0.35.2", "@img/sharp-linux-ppc64": "0.35.2", "@img/sharp-linux-riscv64": "0.35.2", "@img/sharp-linux-s390x": "0.35.2", "@img/sharp-linux-x64": "0.35.2", "@img/sharp-linuxmusl-arm64": "0.35.2", "@img/sharp-linuxmusl-x64": "0.35.2", "@img/sharp-webcontainers-wasm32": "0.35.2", "@img/sharp-win32-arm64": "0.35.2", "@img/sharp-win32-ia32": "0.35.2", "@img/sharp-win32-x64": "0.35.2" } }, "sha512-FVtFjtBCMiJS6yb5CX7Sop45WFMpeGw6oRKuJnXYgf/f1ms/D7LE/ZUSNxnW7rZ/dbslQWYkoqFHGPaDBtaK4w=="], + "shell-quote": ["shell-quote@1.10.0", "", {}, "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA=="], - "sinon": ["sinon@22.1.0", "", { "dependencies": { "@sinonjs/commons": "^3.0.1", "@sinonjs/fake-timers": "^15.4.0", "@sinonjs/samsam": "^10.0.2", "diff": "^9.0.0" } }, "sha512-n1ajF2rBWMTtEwbKcw4UdFg4nCnDdq/U6RDoxtOd7oapOlRoJ5ynwFx60owROyhDpA9QhMZi0pCO/xtmwFjG7w=="], + "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], + + "sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="], "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], + + "std-env": ["std-env@4.2.0", "", {}, "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw=="], + + "supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], + + "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], + "tinyexec": ["tinyexec@1.3.0", "", {}, "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ=="], "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], "tinypool": ["tinypool@2.1.0", "", {}, "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw=="], - "type-detect": ["type-detect@4.0.8", "", {}, "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="], + "tinyrainbow": ["tinyrainbow@3.1.1", "", {}, "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw=="], + + "totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "typescript": ["typescript@7.0.2", "", { "optionalDependencies": { "@typescript/typescript-aix-ppc64": "7.0.2", "@typescript/typescript-darwin-arm64": "7.0.2", "@typescript/typescript-darwin-x64": "7.0.2", "@typescript/typescript-freebsd-arm64": "7.0.2", "@typescript/typescript-freebsd-x64": "7.0.2", "@typescript/typescript-linux-arm": "7.0.2", "@typescript/typescript-linux-arm64": "7.0.2", "@typescript/typescript-linux-loong64": "7.0.2", "@typescript/typescript-linux-mips64el": "7.0.2", "@typescript/typescript-linux-ppc64": "7.0.2", "@typescript/typescript-linux-riscv64": "7.0.2", "@typescript/typescript-linux-s390x": "7.0.2", "@typescript/typescript-linux-x64": "7.0.2", "@typescript/typescript-netbsd-arm64": "7.0.2", "@typescript/typescript-netbsd-x64": "7.0.2", "@typescript/typescript-openbsd-arm64": "7.0.2", "@typescript/typescript-openbsd-x64": "7.0.2", "@typescript/typescript-sunos-x64": "7.0.2", "@typescript/typescript-win32-arm64": "7.0.2", "@typescript/typescript-win32-x64": "7.0.2" }, "bin": { "tsc": "bin/tsc" } }, "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA=="], @@ -321,8 +558,34 @@ "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + "unenv": ["unenv@2.0.0-rc.24", "", { "dependencies": { "pathe": "^2.0.3" } }, "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw=="], + + "vite": ["vite@8.2.1", "", { "dependencies": { "lightningcss": "^1.33.0", "picomatch": "^4.0.5", "postcss": "^8.5.25", "rolldown": "~1.2.1", "tinyglobby": "^0.2.17" }, "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" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw=="], + + "vitest": ["vitest@4.1.10", "", { "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" }, "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": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "./vitest.mjs" } }, "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw=="], + + "whatwg-mimetype": ["whatwg-mimetype@3.0.0", "", {}, "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q=="], + + "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], + + "workerd": ["workerd@1.20260811.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260811.1", "@cloudflare/workerd-darwin-arm64": "1.20260811.1", "@cloudflare/workerd-linux-64": "1.20260811.1", "@cloudflare/workerd-linux-arm64": "1.20260811.1", "@cloudflare/workerd-windows-64": "1.20260811.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-kh+FFm55JQ4ssxhHZV9VPdMQq3D1nHxNJgwxMtWGD4dGppJvLySdguTRDKgeNTvgq6heSz+6TTXyPSDGj8Yllw=="], + + "wrangler": ["wrangler@4.123.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.5.0", "@cloudflare/unenv-preset": "2.16.1", "blake3-wasm": "2.1.5", "esbuild": "0.28.1", "miniflare": "5.20260811.1-alpha", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260811.1" }, "optionalDependencies": { "fsevents": "2.3.3" }, "peerDependencies": { "@cloudflare/workers-types": "^5.20260811.1" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js", "cf-wrangler": "bin/cf-wrangler.js" } }, "sha512-VXo2I1oa0x9aGAKIFPRSQPqTh0RBY5Ktl44YOhNmsJQFUdJKDA2vVTU6Xj+FC2koll6orJqWZN8jbXVIk9O67Q=="], + + "ws": ["ws@8.21.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw=="], + "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="], - "@sinonjs/samsam/type-detect": ["type-detect@4.1.0", "", {}, "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw=="], + "youch": ["youch@4.1.0-beta.10", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@poppinss/dumper": "^0.6.4", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.3" } }, "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ=="], + + "youch-core": ["youch-core@0.3.3", "", { "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } }, "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA=="], + + "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], + + "miniflare/ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="], + + "vite/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "wrangler/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], } } diff --git a/deno.lock b/deno.lock index 82d25149..85926b83 100644 --- a/deno.lock +++ b/deno.lock @@ -3,20 +3,25 @@ "specifiers": { "npm:@changesets/changelog-github@1": "1.0.0", "npm:@changesets/cli@3": "3.0.0", + "npm:@cloudflare/vitest-pool-workers@~0.21.3": "0.21.3_@vitest+runner@4.1.10_@vitest+snapshot@4.1.10_vitest@4.1.10__@types+node@22.20.1__@vitest+browser-playwright@4.1.10__happy-dom@20.11.2__vite@8.2.1___@types+node@22.20.1___esbuild@0.28.1__esbuild@0.28.1__playwright@1.62.1_@types+node@22.20.1_@vitest+browser-playwright@4.1.10__playwright@1.62.1__vitest@4.1.10__@types+node@22.20.1__esbuild@0.28.1__happy-dom@20.11.2__vite@8.2.1___@types+node@22.20.1___esbuild@0.28.1_happy-dom@20.11.2_playwright@1.62.1_vite@8.2.1__@types+node@22.20.1__esbuild@0.28.1", "npm:@tsconfig/strictest@^2.0.8": "2.0.8", "npm:@types/node@^22.19.19": "22.20.1", - "npm:@types/sinon@^21.0.1": "21.0.1", - "npm:esbuild@0.28": "0.28.2", + "npm:@vitest/browser-playwright@^4.1.10": "4.1.10_playwright@1.62.1_vitest@4.1.10_@types+node@22.20.1_esbuild@0.28.1_happy-dom@20.11.2_vite@8.2.1__@types+node@22.20.1__esbuild@0.28.1", + "npm:@vitest/browser@^4.1.10": "4.1.10_vitest@4.1.10__@types+node@22.20.1__@vitest+browser-playwright@4.1.10__happy-dom@20.11.2__vite@8.2.1___@types+node@22.20.1___esbuild@0.28.1__esbuild@0.28.1__playwright@1.62.1_@types+node@22.20.1_@vitest+browser-playwright@4.1.10__playwright@1.62.1__vitest@4.1.10__@types+node@22.20.1__esbuild@0.28.1__happy-dom@20.11.2__vite@8.2.1___@types+node@22.20.1___esbuild@0.28.1_esbuild@0.28.1_happy-dom@20.11.2_vite@8.2.1__@types+node@22.20.1__esbuild@0.28.1", "npm:eventsource-encoder@^1.0.2": "1.0.2", "npm:eventsource-parser@4": "4.0.0", + "npm:happy-dom@^20.11.2": "20.11.2", "npm:oxfmt@0.52": "0.52.0", "npm:oxlint@^1.67.0": "1.78.0", "npm:playwright@^1.60.0": "1.62.1", - "npm:sinon@22": "22.1.0", "npm:typescript@7": "7.0.2", - "npm:undici@7": "7.29.0" + "npm:vitest@*": "4.1.10_@types+node@22.20.1_@vitest+browser-playwright@4.1.10_happy-dom@20.11.2_vite@8.2.1__@types+node@22.20.1__esbuild@0.28.1_esbuild@0.28.1_playwright@1.62.1", + "npm:vitest@^4.1.10": "4.1.10_@types+node@22.20.1_@vitest+browser-playwright@4.1.10_happy-dom@20.11.2_vite@8.2.1__@types+node@22.20.1__esbuild@0.28.1_esbuild@0.28.1_playwright@1.62.1" }, "npm": { + "@blazediff/core@1.9.1": { + "integrity": "sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==" + }, "@changesets/apply-release-plan@8.0.0": { "integrity": "sha512-kUd2pbf1w5/AYmBMb0Tt+rkIPCjFJdT0SZMrkOjJT/WV/QbtmvkyB5jkV0oaNPheavprZk+SfUiozUti7TIL2w==", "dependencies": [ @@ -179,136 +184,380 @@ "sisteransi" ] }, - "@esbuild/aix-ppc64@0.28.2": { - "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "@cloudflare/kv-asset-handler@0.5.0": { + "integrity": "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==" + }, + "@cloudflare/unenv-preset@2.16.1_unenv@2.0.0-rc.24_workerd@1.20260811.1": { + "integrity": "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw==", + "dependencies": [ + "unenv", + "workerd" + ], + "optionalPeers": [ + "workerd" + ] + }, + "@cloudflare/vitest-pool-workers@0.21.3_@vitest+runner@4.1.10_@vitest+snapshot@4.1.10_vitest@4.1.10__@types+node@22.20.1__@vitest+browser-playwright@4.1.10__happy-dom@20.11.2__vite@8.2.1___@types+node@22.20.1___esbuild@0.28.1__esbuild@0.28.1__playwright@1.62.1_@types+node@22.20.1_@vitest+browser-playwright@4.1.10__playwright@1.62.1__vitest@4.1.10__@types+node@22.20.1__esbuild@0.28.1__happy-dom@20.11.2__vite@8.2.1___@types+node@22.20.1___esbuild@0.28.1_happy-dom@20.11.2_playwright@1.62.1_vite@8.2.1__@types+node@22.20.1__esbuild@0.28.1": { + "integrity": "sha512-jCoGRQ6FlsP5adp1GJISvITOGdTHTpsWOq3KkSGIfeDY/5RKjTUagDwaXjpqBXY5gAk6id/QbgnGuCTAg6lSTQ==", + "dependencies": [ + "@vitest/runner", + "@vitest/snapshot", + "cjs-module-lexer", + "esbuild", + "miniflare", + "vitest", + "wrangler", + "zod" + ] + }, + "@cloudflare/workerd-darwin-64@1.20260811.1": { + "integrity": "sha512-i5jqz+ywtOefr0AJbiAc8qxBLfSim/B0WJG7aW3B+pWnoVfMJdUQvi+BWcFKZJ0MoCci3KadTx6g31VfuEEqpQ==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@cloudflare/workerd-darwin-arm64@1.20260811.1": { + "integrity": "sha512-NoOUM/nvaDdm2Onlnz33FikWjtatzulNtvwvy4xs0IrHaTCHwC0c8NwIt6s+AI13FkDs02/vm2I3GTPLCT9+hQ==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@cloudflare/workerd-linux-64@1.20260811.1": { + "integrity": "sha512-sdYq2jL1AD1supa3fsi5O4zTB28wSjvTHj7Migh6/ts8EROPdvrSwv+rdGHhv8HJNAz/wbIAY3wZsi1Rw4uUIg==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@cloudflare/workerd-linux-arm64@1.20260811.1": { + "integrity": "sha512-RIRv4shbu1kg05sD+DHTpSFCNnb5Dl2SkPDMUykqZa508tkPqe7VVw7gO0Q5msTBGyL0FfFrLuRxwwfA8u5Sow==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@cloudflare/workerd-windows-64@1.20260811.1": { + "integrity": "sha512-g6VquwjASlYAibcNW/0E6Zszht4qLkmnXOGwIjjRHl2A0Qz48kVeMcGvyH6eA0G9U3OzZojjYFpP+YeyQmmdjw==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@cspotcode/source-map-support@0.8.1": { + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dependencies": [ + "@jridgewell/trace-mapping" + ] + }, + "@emnapi/runtime@1.11.3": { + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "dependencies": [ + "tslib" + ] + }, + "@esbuild/aix-ppc64@0.28.1": { + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", "os": ["aix"], "cpu": ["ppc64"] }, - "@esbuild/android-arm64@0.28.2": { - "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "@esbuild/android-arm64@0.28.1": { + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", "os": ["android"], "cpu": ["arm64"] }, - "@esbuild/android-arm@0.28.2": { - "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "@esbuild/android-arm@0.28.1": { + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", "os": ["android"], "cpu": ["arm"] }, - "@esbuild/android-x64@0.28.2": { - "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "@esbuild/android-x64@0.28.1": { + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", "os": ["android"], "cpu": ["x64"] }, - "@esbuild/darwin-arm64@0.28.2": { - "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "@esbuild/darwin-arm64@0.28.1": { + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", "os": ["darwin"], "cpu": ["arm64"] }, - "@esbuild/darwin-x64@0.28.2": { - "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "@esbuild/darwin-x64@0.28.1": { + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", "os": ["darwin"], "cpu": ["x64"] }, - "@esbuild/freebsd-arm64@0.28.2": { - "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "@esbuild/freebsd-arm64@0.28.1": { + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", "os": ["freebsd"], "cpu": ["arm64"] }, - "@esbuild/freebsd-x64@0.28.2": { - "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "@esbuild/freebsd-x64@0.28.1": { + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", "os": ["freebsd"], "cpu": ["x64"] }, - "@esbuild/linux-arm64@0.28.2": { - "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "@esbuild/linux-arm64@0.28.1": { + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", "os": ["linux"], "cpu": ["arm64"] }, - "@esbuild/linux-arm@0.28.2": { - "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "@esbuild/linux-arm@0.28.1": { + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", "os": ["linux"], "cpu": ["arm"] }, - "@esbuild/linux-ia32@0.28.2": { - "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "@esbuild/linux-ia32@0.28.1": { + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", "os": ["linux"], "cpu": ["ia32"] }, - "@esbuild/linux-loong64@0.28.2": { - "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "@esbuild/linux-loong64@0.28.1": { + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", "os": ["linux"], "cpu": ["loong64"] }, - "@esbuild/linux-mips64el@0.28.2": { - "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "@esbuild/linux-mips64el@0.28.1": { + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", "os": ["linux"], "cpu": ["mips64el"] }, - "@esbuild/linux-ppc64@0.28.2": { - "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "@esbuild/linux-ppc64@0.28.1": { + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", "os": ["linux"], "cpu": ["ppc64"] }, - "@esbuild/linux-riscv64@0.28.2": { - "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "@esbuild/linux-riscv64@0.28.1": { + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", "os": ["linux"], "cpu": ["riscv64"] }, - "@esbuild/linux-s390x@0.28.2": { - "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "@esbuild/linux-s390x@0.28.1": { + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", "os": ["linux"], "cpu": ["s390x"] }, - "@esbuild/linux-x64@0.28.2": { - "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "@esbuild/linux-x64@0.28.1": { + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", "os": ["linux"], "cpu": ["x64"] }, - "@esbuild/netbsd-arm64@0.28.2": { - "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "@esbuild/netbsd-arm64@0.28.1": { + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", "os": ["netbsd"], "cpu": ["arm64"] }, - "@esbuild/netbsd-x64@0.28.2": { - "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "@esbuild/netbsd-x64@0.28.1": { + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", "os": ["netbsd"], "cpu": ["x64"] }, - "@esbuild/openbsd-arm64@0.28.2": { - "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "@esbuild/openbsd-arm64@0.28.1": { + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", "os": ["openbsd"], "cpu": ["arm64"] }, - "@esbuild/openbsd-x64@0.28.2": { - "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "@esbuild/openbsd-x64@0.28.1": { + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", "os": ["openbsd"], "cpu": ["x64"] }, - "@esbuild/openharmony-arm64@0.28.2": { - "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "@esbuild/openharmony-arm64@0.28.1": { + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", "os": ["openharmony"], "cpu": ["arm64"] }, - "@esbuild/sunos-x64@0.28.2": { - "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "@esbuild/sunos-x64@0.28.1": { + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", "os": ["sunos"], "cpu": ["x64"] }, - "@esbuild/win32-arm64@0.28.2": { - "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "@esbuild/win32-arm64@0.28.1": { + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@esbuild/win32-ia32@0.28.1": { + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "os": ["win32"], + "cpu": ["ia32"] + }, + "@esbuild/win32-x64@0.28.1": { + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@img/colour@1.1.0": { + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==" + }, + "@img/sharp-darwin-arm64@0.35.2": { + "integrity": "sha512-eEieHsMksAW4IiO5NzauESRl2D2qz3J/kwUxUrSfV06A93eEaRfMpHXyUb1mAqrR7i8U9A0GRqE9pjn6u1Jjpg==", + "optionalDependencies": [ + "@img/sharp-libvips-darwin-arm64" + ], + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@img/sharp-darwin-x64@0.35.2": { + "integrity": "sha512-BaktuGPCeHJMARpodR8jK4uKiZrPAy9WrfQW0sdI37clracq8Bp01AYS3SZgi5FS/y5twa9t4+LIuuxQjqRrWw==", + "optionalDependencies": [ + "@img/sharp-libvips-darwin-x64" + ], + "os": ["darwin"], + "cpu": ["x64"] + }, + "@img/sharp-freebsd-wasm32@0.35.2": { + "integrity": "sha512-YoAxdnd8hPUkvLHd3bWY+YA8nw3xM/RyRopYucNsWHVSan8NLVM3X2volsfoRDcXdUJPg6tXahSd7HXPK7lRnw==", + "dependencies": [ + "@img/sharp-wasm32" + ], + "os": ["freebsd"] + }, + "@img/sharp-libvips-darwin-arm64@1.3.1": { + "integrity": "sha512-4V/M3roRMTYjiwZY9IOVQOE8OyeCxFAkYmyZDrZl51uOKjibm3oeEJ4WAmLxutAfzFbC9jqUiPs2gbnGflH+7g==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@img/sharp-libvips-darwin-x64@1.3.1": { + "integrity": "sha512-c0/DxItpJv2+dGhgycJBBgotdqruGYDvA79drdh0MD1dFpy7JzJ/PlXwi1H4rFf0eTy8tgbI91aHDnZIceY3jQ==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@img/sharp-libvips-linux-arm64@1.3.1": { + "integrity": "sha512-JznefmcK9j1JKPz8AkQDh89kjojubyfOasWBPKfzMIhPwsgDy9evpE/naJTXXXmghS1iFwR8u/kTwh/I2/+GCw==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@img/sharp-libvips-linux-arm@1.3.1": { + "integrity": "sha512-aGGy9aWzXgHBG7HNyQPWorZthlp7+x6fDRoPAQbGO3ThcttuTyKIx3NuSHb6zb4gBNq6/yNn9f1cy9nFKS/Vmg==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@img/sharp-libvips-linux-ppc64@1.3.1": { + "integrity": "sha512-1EkwGNCZk6iWNCMWqrvdJ+r1j0PT1zIz60CNPhYnJlK/zyeWqlsPZIe+ocBVqPF8k/Ssee/NCk+tE9Ryrko6ng==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@img/sharp-libvips-linux-riscv64@1.3.1": { + "integrity": "sha512-Ilays+w2bXdnxzxtQdmXR62u8o8GYa3eL4+Gr+1KiE4xperMZUslRaVPJwwPkzlHEjGfXAfRVAa/7CYCtSqsBw==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@img/sharp-libvips-linux-s390x@1.3.1": { + "integrity": "sha512-VfBwVHQTbRoj4XlpA/KLZ7ltgMpz+4WSejFzQ+GnoImjo1PtEJ59QB2qR1xQEeRPYIkNrPIm2L4cICMvz4C2ew==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@img/sharp-libvips-linux-x64@1.3.1": { + "integrity": "sha512-+c8ukgwU62DS54nCAjw7keOfHUkmr0B5QHEdcOqRnodF/MNXJbVI8Eopoj4B/0H8Asr65I+A4Amrn7a85/md6A==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@img/sharp-libvips-linuxmusl-arm64@1.3.1": { + "integrity": "sha512-qlKb/pwbkAi1WMsJrYHk7CuDrd12s27U2QnRhFYUoJNrRCmkosMTttuRFat/DDB3IlDm5qE1TJgZ4JDnHX8Ldw==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@img/sharp-libvips-linuxmusl-x64@1.3.1": { + "integrity": "sha512-yO21HwoUVLN8Qa+/SBjQLMYwBWAVJjeGPNe+hc0OUeMeifEtJqu5a1c4HayE1nNpDih9y3/KkoltfkDodmKAlg==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@img/sharp-linux-arm64@0.35.2": { + "integrity": "sha512-af12Pnd0ZGu2HfP8NayB0kk6eC/lrfbQE6HlR4jD+34wdJ1Vw9TF6TMn6ZvffT+WgqVsl0hRbmNvz2u/23VmwA==", + "optionalDependencies": [ + "@img/sharp-libvips-linux-arm64" + ], + "os": ["linux"], + "cpu": ["arm64"] + }, + "@img/sharp-linux-arm@0.35.2": { + "integrity": "sha512-SE4kzF2mepn6z+6E7L6lsV8FzuLL6IPQdyX8ZiwROAG/G8td+hP/m7FsFPwidtrF19gvajuC9l6TxAVcsA4S7A==", + "optionalDependencies": [ + "@img/sharp-libvips-linux-arm" + ], + "os": ["linux"], + "cpu": ["arm"] + }, + "@img/sharp-linux-ppc64@0.35.2": { + "integrity": "sha512-hYSBm7zcNtDCozCxQHYZJiu63b/bXsgRZuOxCIBZsStMM9Vap47iFHdbX4kCvQsblPB/k+clhELpdQJHQLSHvg==", + "optionalDependencies": [ + "@img/sharp-libvips-linux-ppc64" + ], + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@img/sharp-linux-riscv64@0.35.2": { + "integrity": "sha512-qQt0Kc13+Hoan/Awq/qMSQw3L+RI1NCRPgD5cUJ/1WSSmIoysLOc72jlRM3E0OHN9Yr313jgeQ2T+zW+F03QFA==", + "optionalDependencies": [ + "@img/sharp-libvips-linux-riscv64" + ], + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@img/sharp-linux-s390x@0.35.2": { + "integrity": "sha512-E4fLLfRPzDLlEeDaTzI98OFLcv++WL5ChLLMwPoVd0CIoZQqupBSNbOisPL5am9XsbQ9T84+iiMpUvbFtkunbA==", + "optionalDependencies": [ + "@img/sharp-libvips-linux-s390x" + ], + "os": ["linux"], + "cpu": ["s390x"] + }, + "@img/sharp-linux-x64@0.35.2": { + "integrity": "sha512-gi0zFJJRLswfCZmHtJdikXPOc5u7qamSOS3NHedLqLd4W8Q0NqjdBr6TTRIgsfFjqfTsHFgdfvJ9LwqSgcHiAA==", + "optionalDependencies": [ + "@img/sharp-libvips-linux-x64" + ], + "os": ["linux"], + "cpu": ["x64"] + }, + "@img/sharp-linuxmusl-arm64@0.35.2": { + "integrity": "sha512-siWbOW1u6HFnFLrp0waKyW7VEf7jYvcDWdrXEFa8AkdAQgEvuu5Fz8/Y70w9EeqAdwDtfU012BhEHHaDqvQNzg==", + "optionalDependencies": [ + "@img/sharp-libvips-linuxmusl-arm64" + ], + "os": ["linux"], + "cpu": ["arm64"] + }, + "@img/sharp-linuxmusl-x64@0.35.2": { + "integrity": "sha512-YBqMMcjDi4QGYiSn4vNOYBhmlC4z5AXqkOUUqI2e0AFA4urNv4ESgOgwNl3K+4etQhha0twXlzeF20bbULm9Yg==", + "optionalDependencies": [ + "@img/sharp-libvips-linuxmusl-x64" + ], + "os": ["linux"], + "cpu": ["x64"] + }, + "@img/sharp-wasm32@0.35.2": { + "integrity": "sha512-Mrv4JQNYVQ94xH+jzZ9r+gowleN8mv2FTgKT+PI6bx5C0G8TdNYndu161pg2i7uoBwxy2ImPMHrJOM2LZef7Bw==", + "dependencies": [ + "@emnapi/runtime" + ] + }, + "@img/sharp-webcontainers-wasm32@0.35.2": { + "integrity": "sha512-QNV27pxs9wpApEiCfvHM1RDoP1w1+2KrUWWDPEhEwg+latvOrfuhWrHWZKwdSFwU6jh3myjw/yOCRsUIuOft3g==", + "dependencies": [ + "@img/sharp-wasm32" + ], + "cpu": ["wasm32"] + }, + "@img/sharp-win32-arm64@0.35.2": { + "integrity": "sha512-BiVRYc/t6/Vl3e1hBx0hugG4oN9Pydf4fgMSpxTQJmwGUg/YoXTWHiFeRymHfCZzifxu4F4rpk/I67D0LQ20wQ==", "os": ["win32"], "cpu": ["arm64"] }, - "@esbuild/win32-ia32@0.28.2": { - "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "@img/sharp-win32-ia32@0.35.2": { + "integrity": "sha512-YYEhx9PImCC7T0tI8JDMi4DB9LwLCXCU5OWNYEXAxh5Q1ShKkyC6byxzoBJ3gEFDnH2lQckWuDe70G7mB2XJog==", "os": ["win32"], "cpu": ["ia32"] }, - "@esbuild/win32-x64@0.28.2": { - "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "@img/sharp-win32-x64@0.35.2": { + "integrity": "sha512-imoOyBcoM/iiUr4J6VPpCNjPnjvP/Gks95898yB8YqoGGYmHYbOyCuNv9FMhFgtaiHFGbHW8bxKqRV6VjtXThQ==", "os": ["win32"], "cpu": ["x64"] }, + "@jridgewell/resolve-uri@3.1.2": { + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" + }, + "@jridgewell/sourcemap-codec@1.5.5": { + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" + }, + "@jridgewell/trace-mapping@0.3.9": { + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dependencies": [ + "@jridgewell/resolve-uri", + "@jridgewell/sourcemap-codec" + ] + }, "@manypkg/find-root@3.1.0": { "integrity": "sha512-BcSqCyKhBVZ5YkSzOiheMCV41kqAFptW6xGqYSTjkVTl9XQpr+pqHhwgGCOHQtjDCv7Is6EFyA14Sm5GVbVABA==", "dependencies": [ @@ -330,6 +579,9 @@ "yaml" ] }, + "@oxc-project/types@0.144.0": { + "integrity": "sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg==" + }, "@oxfmt/binding-android-arm-eabi@0.52.0": { "integrity": "sha512-17EMSJnQ9g+upVHrAUYDMfH5lvRKQ9Nvg8WtEoH72oDr1VpWz+7/o3tD97U1EToen2YAQ/68JmtDYkQUi20dfQ==", "os": ["android"], @@ -523,43 +775,139 @@ "@pnpm/deps.graph-sequencer@1100.0.1": { "integrity": "sha512-pOr5+q1fLYKwFN3LAJuGZEnfXDcQ73zqgDHMtGy+K+uIoUqyY+6MeDCWFwfu+4EFuq76I5EPFofoNAI+Bmmq4A==" }, - "@sinonjs/commons@3.0.1": { - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dependencies": [ - "type-detect@4.0.8" - ] + "@polka/url@1.0.0-next.29": { + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==" }, - "@sinonjs/fake-timers@15.4.0": { - "integrity": "sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA==", + "@poppinss/colors@4.1.6": { + "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", "dependencies": [ - "@sinonjs/commons" + "kleur" ] }, - "@sinonjs/samsam@10.0.2": { - "integrity": "sha512-8lVwD1Df1BmzoaOLhMcGGcz/Jyr5QY2KSB75/YK1QgKzoabTeLdIVyhXNZK9ojfSKSdirbXqdbsXXqP9/Ve8+A==", + "@poppinss/dumper@0.6.5": { + "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", "dependencies": [ - "@sinonjs/commons", - "type-detect@4.1.0" + "@poppinss/colors", + "@sindresorhus/is", + "supports-color" ] }, + "@poppinss/exception@1.2.3": { + "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==" + }, + "@rolldown/binding-android-arm64@1.2.4": { + "integrity": "sha512-jHC2cnyKz5xU2fhECtFl8OZ83cYNt13GZQD+0uMJ/X3o+ijmd56okHhTUwxVSHPx1IRVIJEZ1/1pPzeLCU6XKA==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@rolldown/binding-darwin-arm64@1.2.4": { + "integrity": "sha512-Dc5mPD8F5F/FS8i01syd7FTF6yB2fVthH/TRkjwJkzUK6EpoxHtqvZQP5Zwq80/5z19TWYHIg1KOHboCgVx/aQ==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@rolldown/binding-darwin-x64@1.2.4": { + "integrity": "sha512-fpDm4oBo6SqLvWUYCmFhdde3U9KH2fRNNMeAnAPAIwxRL345xutL0EtEUcuoxsoazdJGv/MuDBQHlCDrtbvqOg==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@rolldown/binding-freebsd-x64@1.2.4": { + "integrity": "sha512-rSJoreDE/HoIzoaib6MTp5jQtCTdMHKIvItAKT/ImS6Y6Ww76oUaeMyp4Vc/fAgd/ehji068IxetHXAnqUwN9A==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@rolldown/binding-linux-arm-gnueabihf@1.2.4": { + "integrity": "sha512-/jm8OGHgn7oGaJu3i/qZI9spUGcJ+y/lk43ttQ/iO1tOd9NissG6o97bighBCiL+BKRngmcDuR6ikfwYdJmVuQ==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@rolldown/binding-linux-arm64-gnu@1.2.4": { + "integrity": "sha512-tIP06BeD9EqvECBrPZ+sqdPlYrT+aYaAiu1wYziVx5elRK/ftm33JxVDy2bXGbr6J0CrtirCkR87/X5a2euEng==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@rolldown/binding-linux-arm64-musl@1.2.4": { + "integrity": "sha512-Ql1Q0EQqVThvn9VAVlwNzsUvbSFtCMGjLpRRi4pk5i7NZZ4n5ISiLMjHYtus4VQ2PvkSw24zyaCVsiS+sXPj1w==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@rolldown/binding-linux-ppc64-gnu@1.2.4": { + "integrity": "sha512-GjbjXD4XXfN19D0LZNbmiCBUoDiRACsYHr0yaIbbn8aFsXjHZifcYqu/W5Er5X2X990WjHXFrxarn5chzItorQ==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@rolldown/binding-linux-s390x-gnu@1.2.4": { + "integrity": "sha512-p5WR0NOwaRmJ/B1b6IjEFLLivwEsf3PrdBIhRbhTCQisbo2SvHHpG4ELB/+FgQNnB88LTOF86upmJmbvZdQ2lw==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@rolldown/binding-linux-x64-gnu@1.2.4": { + "integrity": "sha512-4/GyVjmhR+Tc6HLJvwc1sOhPqAZtySiSMesOZyX6JQ5XBxoTDEMKQzvo07NIK6nTon/SivlZqvhzvuVBNQhObQ==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@rolldown/binding-linux-x64-musl@1.2.4": { + "integrity": "sha512-l9eeLsCNvPpmSXUej0etw/J1eqV0Jj1D5G/xG6YTijmE6dkv6E2QezgWbTfQk63v952DPqrjOCoiqxq7Bw0YUQ==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@rolldown/binding-openharmony-arm64@1.2.4": { + "integrity": "sha512-e0F355MSTMm3+UOqtV3L24gFUp2N5m1f8L/7d56deik6va+AXdrt9F8LbzGpeWGWRbZEDq4m8NVnJDeBtf9DZg==", + "os": ["openharmony"], + "cpu": ["arm64"] + }, + "@rolldown/binding-win32-arm64-msvc@1.2.4": { + "integrity": "sha512-AWLi0uBRYh6QlE7OKhiz+phZC0qwtij2QZmhmOdsLdFn64m7oMpooE9ICE3lhm9xMb4SpDo2WbHcxX1iFLFtqw==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@rolldown/binding-win32-x64-msvc@1.2.4": { + "integrity": "sha512-UwSDJOg3dqCAejWdxclJjCsh3Qq4vLYMDxmyHqo1btz3stK2VqgwNd3mm5tuIwzSlGIQ/1H9Hr+Zn09mrezNqQ==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@rolldown/pluginutils@1.0.1": { + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==" + }, + "@sindresorhus/is@7.2.0": { + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==" + }, + "@speed-highlight/core@1.2.24": { + "integrity": "sha512-qeW2e1l78afw8VhRPfPQ1Gjj+KU5XFQ/OFV5ti6eTa9bruO7mJyZtA4vw0ofqmA3tKCkROE9xLk3VZoeRc98nw==" + }, + "@standard-schema/spec@1.1.0": { + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==" + }, "@tsconfig/strictest@2.0.8": { "integrity": "sha512-XnQ7vNz5HRN0r88GYf1J9JJjqtZPiHt2woGJOo2dYqyHGGcd6OLGqSlBB6p1j9mpzja6Oe5BoPqWmeDx6X9rLw==" }, + "@types/chai@5.2.3": { + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dependencies": [ + "@types/deep-eql", + "assertion-error" + ] + }, + "@types/deep-eql@4.0.2": { + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==" + }, + "@types/estree@1.0.9": { + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==" + }, "@types/node@22.20.1": { "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", "dependencies": [ "undici-types" ] }, - "@types/sinon@21.0.1": { - "integrity": "sha512-5yoJSqLbjH8T9V2bksgRayuhpZy+723/z6wBOR+Soe4ZlXC0eW8Na71TeaZPUWDQvM7LYKa9UGFc6LRqxiR5fQ==", + "@types/whatwg-mimetype@3.0.2": { + "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==" + }, + "@types/ws@8.18.1": { + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", "dependencies": [ - "@types/sinonjs__fake-timers" + "@types/node" ] }, - "@types/sinonjs__fake-timers@15.0.1": { - "integrity": "sha512-Ko2tjWJq8oozHzHV+reuvS5KYIRAokHnGbDwGh/J64LntgpbuylF74ipEL24HCyRjf9FOlBiBHWBR1RlVKsI1w==" - }, "@typescript/typescript-aix-ppc64@7.0.2": { "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", "os": ["aix"], @@ -660,17 +1008,130 @@ "os": ["win32"], "cpu": ["x64"] }, + "@vitest/browser-playwright@4.1.10_playwright@1.62.1_vitest@4.1.10_@types+node@22.20.1_esbuild@0.28.1_happy-dom@20.11.2_vite@8.2.1__@types+node@22.20.1__esbuild@0.28.1": { + "integrity": "sha512-nMoXGEiRpT7m3W7NsbvrM2aKNwiNHZf+zEpUCvMteGjZFvfT96Q9fh7QyB98dvDWXiKvrLxA7bJ1mCOOv+JQPw==", + "dependencies": [ + "@vitest/browser", + "@vitest/mocker", + "playwright", + "tinyrainbow", + "vitest" + ] + }, + "@vitest/browser@4.1.10_vitest@4.1.10__@types+node@22.20.1__@vitest+browser-playwright@4.1.10__happy-dom@20.11.2__vite@8.2.1___@types+node@22.20.1___esbuild@0.28.1__esbuild@0.28.1__playwright@1.62.1_@types+node@22.20.1_@vitest+browser-playwright@4.1.10__playwright@1.62.1__vitest@4.1.10__@types+node@22.20.1__esbuild@0.28.1__happy-dom@20.11.2__vite@8.2.1___@types+node@22.20.1___esbuild@0.28.1_esbuild@0.28.1_happy-dom@20.11.2_vite@8.2.1__@types+node@22.20.1__esbuild@0.28.1": { + "integrity": "sha512-UDwuWGwXj646CBx/bQHOaJSX7np0I8JL/UKQYa1e4QrVHH8VdWtx8eaOuf8sy0ShwDgR6NjJAsp5eF6vjF6qng==", + "dependencies": [ + "@blazediff/core", + "@vitest/mocker", + "@vitest/utils", + "magic-string", + "pngjs", + "sirv", + "tinyrainbow", + "vitest", + "ws" + ] + }, + "@vitest/expect@4.1.10": { + "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", + "dependencies": [ + "@standard-schema/spec", + "@types/chai", + "@vitest/spy", + "@vitest/utils", + "chai", + "tinyrainbow" + ] + }, + "@vitest/mocker@4.1.10_vite@8.2.1__@types+node@22.20.1__esbuild@0.28.1_@types+node@22.20.1_esbuild@0.28.1": { + "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", + "dependencies": [ + "@vitest/spy", + "estree-walker", + "magic-string", + "vite" + ], + "optionalPeers": [ + "vite" + ] + }, + "@vitest/pretty-format@4.1.10": { + "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", + "dependencies": [ + "tinyrainbow" + ] + }, + "@vitest/runner@4.1.10": { + "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", + "dependencies": [ + "@vitest/utils", + "pathe" + ] + }, + "@vitest/snapshot@4.1.10": { + "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", + "dependencies": [ + "@vitest/pretty-format", + "@vitest/utils", + "magic-string", + "pathe" + ] + }, + "@vitest/spy@4.1.10": { + "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==" + }, + "@vitest/utils@4.1.10": { + "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", + "dependencies": [ + "@vitest/pretty-format", + "convert-source-map", + "tinyrainbow" + ] + }, + "assertion-error@2.0.1": { + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==" + }, + "blake3-wasm@2.1.5": { + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==" + }, + "buffer-image-size@0.6.4": { + "integrity": "sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ==", + "dependencies": [ + "@types/node" + ] + }, "cac@7.0.0": { "integrity": "sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==" }, + "chai@6.2.2": { + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==" + }, + "cjs-module-lexer@1.2.3": { + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" + }, + "convert-source-map@2.0.0": { + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "cookie@1.1.1": { + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==" + }, "dataloader@2.2.3": { "integrity": "sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA==" }, - "diff@9.0.0": { - "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==" + "detect-libc@2.1.2": { + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==" + }, + "entities@7.0.1": { + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==" + }, + "error-stack-parser-es@1.0.5": { + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==" + }, + "es-module-lexer@2.3.1": { + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==" }, - "esbuild@0.28.2": { - "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "esbuild@0.28.1": { + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", "optionalDependencies": [ "@esbuild/aix-ppc64", "@esbuild/android-arm", @@ -702,12 +1163,21 @@ "scripts": true, "bin": true }, + "estree-walker@3.0.3": { + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dependencies": [ + "@types/estree" + ] + }, "eventsource-encoder@1.0.2": { "integrity": "sha512-iG7mY5LhweLKpgxQ+YdW7Y6YjBgRzGMrKlXzeUpm0VtJpdeag32Q/DMQ11HAT7kO9Jx8dreUL5SHGl6KAGJ9Lg==" }, "eventsource-parser@4.0.0": { "integrity": "sha512-aIpvYxbqTx4KYWw73KpCt1Rh22tEAJ144F1qR76CT3Ex+LNMEPKf5HFrK5Yz9fMP1EVT0GrfA35VZvWQhMPuSQ==" }, + "expect-type@1.4.0": { + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==" + }, "fast-string-truncated-width@3.0.3": { "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==" }, @@ -737,6 +1207,23 @@ "os": ["darwin"], "scripts": true }, + "fsevents@2.3.3": { + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "os": ["darwin"], + "scripts": true + }, + "happy-dom@20.11.2": { + "integrity": "sha512-7MB+bJLkxu3SowAfBJbjW+c55kNz5tkR45gu2qzrxznezhLeN5YIlJbwUgSzlGc+qWoZ8Ykg71H5ezz69xixrw==", + "dependencies": [ + "@types/node", + "@types/whatwg-mimetype", + "@types/ws", + "buffer-image-size", + "entities", + "whatwg-mimetype", + "ws" + ] + }, "human-id@4.2.0": { "integrity": "sha512-K3GbkIWqyvvlpfhBPlbEvD97TtqBpAYA4kt+cn2lD2x2HuohzZCibcA2nOlnJT6exqvJLggoB5nv2dNf192nEA==", "bin": true @@ -750,6 +1237,9 @@ "jsonc-parser@3.3.1": { "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==" }, + "kleur@4.1.5": { + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==" + }, "launch-editor@2.14.1": { "integrity": "sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==", "dependencies": [ @@ -757,6 +1247,107 @@ "shell-quote" ] }, + "lightningcss-android-arm64@1.33.0": { + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "os": ["android"], + "cpu": ["arm64"] + }, + "lightningcss-darwin-arm64@1.33.0": { + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "lightningcss-darwin-x64@1.33.0": { + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "lightningcss-freebsd-x64@1.33.0": { + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "lightningcss-linux-arm-gnueabihf@1.33.0": { + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "os": ["linux"], + "cpu": ["arm"] + }, + "lightningcss-linux-arm64-gnu@1.33.0": { + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "lightningcss-linux-arm64-musl@1.33.0": { + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "lightningcss-linux-x64-gnu@1.33.0": { + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "os": ["linux"], + "cpu": ["x64"] + }, + "lightningcss-linux-x64-musl@1.33.0": { + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "os": ["linux"], + "cpu": ["x64"] + }, + "lightningcss-win32-arm64-msvc@1.33.0": { + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "lightningcss-win32-x64-msvc@1.33.0": { + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "os": ["win32"], + "cpu": ["x64"] + }, + "lightningcss@1.33.0": { + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "dependencies": [ + "detect-libc" + ], + "optionalDependencies": [ + "lightningcss-android-arm64", + "lightningcss-darwin-arm64", + "lightningcss-darwin-x64", + "lightningcss-freebsd-x64", + "lightningcss-linux-arm-gnueabihf", + "lightningcss-linux-arm64-gnu", + "lightningcss-linux-arm64-musl", + "lightningcss-linux-x64-gnu", + "lightningcss-linux-x64-musl", + "lightningcss-win32-arm64-msvc", + "lightningcss-win32-x64-msvc" + ] + }, + "magic-string@0.30.21": { + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dependencies": [ + "@jridgewell/sourcemap-codec" + ] + }, + "miniflare@5.20260811.1-alpha": { + "integrity": "sha512-DtOG0BeanIxs2sH0smFvExZD89cBQwGckbHiFkRJrrNAUu3NGClZkUxqu+zy7HYfKBAgq935EMY49vIPm3JVdA==", + "dependencies": [ + "@cspotcode/source-map-support", + "sharp", + "undici", + "workerd", + "ws", + "youch" + ] + }, + "mrmime@2.0.1": { + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==" + }, + "nanoid@3.3.18": { + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "bin": true + }, + "obug@2.1.4": { + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==" + }, "oxfmt@0.52.0": { "integrity": "sha512-nJlYM35F64zTDMecCNhoHNkf+D/eHv7xcjj9XDSj+bFAVtN93m7v8DQMdHd6nDG6Akf/kEYYHmDUBs2Dz27Sug==", "dependencies": [ @@ -813,6 +1404,12 @@ "package-manager-detector@1.8.0": { "integrity": "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==" }, + "path-to-regexp@6.3.0": { + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==" + }, + "pathe@2.0.3": { + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==" + }, "picocolors@1.1.1": { "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, @@ -829,7 +1426,42 @@ "playwright-core" ], "optionalDependencies": [ - "fsevents" + "fsevents@2.3.2" + ], + "bin": true + }, + "pngjs@7.0.0": { + "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==" + }, + "postcss@8.5.26": { + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "dependencies": [ + "nanoid", + "picocolors", + "source-map-js" + ] + }, + "rolldown@1.2.4": { + "integrity": "sha512-rSr7irW0K7QRWzjdJXqZowkcRdDtjRduh43rBltnVKd0VFq839l1lJoDvGJb6gl7+4rTTCrPWu+YfujUL8Ug7w==", + "dependencies": [ + "@oxc-project/types", + "@rolldown/pluginutils" + ], + "optionalDependencies": [ + "@rolldown/binding-android-arm64", + "@rolldown/binding-darwin-arm64", + "@rolldown/binding-darwin-x64", + "@rolldown/binding-freebsd-x64", + "@rolldown/binding-linux-arm-gnueabihf", + "@rolldown/binding-linux-arm64-gnu", + "@rolldown/binding-linux-arm64-musl", + "@rolldown/binding-linux-ppc64-gnu", + "@rolldown/binding-linux-s390x-gnu", + "@rolldown/binding-linux-x64-gnu", + "@rolldown/binding-linux-x64-musl", + "@rolldown/binding-openharmony-arm64", + "@rolldown/binding-win32-arm64-msvc", + "@rolldown/binding-win32-x64-msvc" ], "bin": true }, @@ -837,21 +1469,73 @@ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "bin": true }, + "sharp@0.35.2": { + "integrity": "sha512-FVtFjtBCMiJS6yb5CX7Sop45WFMpeGw6oRKuJnXYgf/f1ms/D7LE/ZUSNxnW7rZ/dbslQWYkoqFHGPaDBtaK4w==", + "dependencies": [ + "@img/colour", + "detect-libc", + "semver" + ], + "optionalDependencies": [ + "@img/sharp-darwin-arm64", + "@img/sharp-darwin-x64", + "@img/sharp-freebsd-wasm32", + "@img/sharp-libvips-darwin-arm64", + "@img/sharp-libvips-darwin-x64", + "@img/sharp-libvips-linux-arm", + "@img/sharp-libvips-linux-arm64", + "@img/sharp-libvips-linux-ppc64", + "@img/sharp-libvips-linux-riscv64", + "@img/sharp-libvips-linux-s390x", + "@img/sharp-libvips-linux-x64", + "@img/sharp-libvips-linuxmusl-arm64", + "@img/sharp-libvips-linuxmusl-x64", + "@img/sharp-linux-arm", + "@img/sharp-linux-arm64", + "@img/sharp-linux-ppc64", + "@img/sharp-linux-riscv64", + "@img/sharp-linux-s390x", + "@img/sharp-linux-x64", + "@img/sharp-linuxmusl-arm64", + "@img/sharp-linuxmusl-x64", + "@img/sharp-webcontainers-wasm32", + "@img/sharp-win32-arm64", + "@img/sharp-win32-ia32", + "@img/sharp-win32-x64" + ] + }, "shell-quote@1.10.0": { "integrity": "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==" }, - "sinon@22.1.0": { - "integrity": "sha512-n1ajF2rBWMTtEwbKcw4UdFg4nCnDdq/U6RDoxtOd7oapOlRoJ5ynwFx60owROyhDpA9QhMZi0pCO/xtmwFjG7w==", + "siginfo@2.0.0": { + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==" + }, + "sirv@3.0.2": { + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", "dependencies": [ - "@sinonjs/commons", - "@sinonjs/fake-timers", - "@sinonjs/samsam", - "diff" + "@polka/url", + "mrmime", + "totalist" ] }, "sisteransi@1.0.5": { "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" }, + "source-map-js@1.2.1": { + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" + }, + "stackback@0.0.2": { + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==" + }, + "std-env@4.2.0": { + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==" + }, + "supports-color@10.2.2": { + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==" + }, + "tinybench@2.9.0": { + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==" + }, "tinyexec@1.3.0": { "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==" }, @@ -865,11 +1549,14 @@ "tinypool@2.1.0": { "integrity": "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==" }, - "type-detect@4.0.8": { - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + "tinyrainbow@3.1.1": { + "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==" }, - "type-detect@4.1.0": { - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==" + "totalist@3.0.1": { + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==" + }, + "tslib@2.8.1": { + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "typescript@7.0.2": { "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", @@ -903,9 +1590,132 @@ "undici@7.29.0": { "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==" }, + "unenv@2.0.0-rc.24": { + "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", + "dependencies": [ + "pathe" + ] + }, + "vite@8.2.1_@types+node@22.20.1_esbuild@0.28.1": { + "integrity": "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==", + "dependencies": [ + "@types/node", + "esbuild", + "lightningcss", + "picomatch", + "postcss", + "rolldown", + "tinyglobby" + ], + "optionalDependencies": [ + "fsevents@2.3.3" + ], + "optionalPeers": [ + "@types/node", + "esbuild" + ], + "bin": true + }, + "vitest@4.1.10_@types+node@22.20.1_@vitest+browser-playwright@4.1.10_happy-dom@20.11.2_vite@8.2.1__@types+node@22.20.1__esbuild@0.28.1_esbuild@0.28.1_playwright@1.62.1": { + "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", + "dependencies": [ + "@types/node", + "@vitest/browser-playwright", + "@vitest/expect", + "@vitest/mocker", + "@vitest/pretty-format", + "@vitest/runner", + "@vitest/snapshot", + "@vitest/spy", + "@vitest/utils", + "es-module-lexer", + "expect-type", + "happy-dom", + "magic-string", + "obug", + "pathe", + "picomatch", + "std-env", + "tinybench", + "tinyexec", + "tinyglobby", + "tinyrainbow", + "vite", + "why-is-node-running" + ], + "optionalPeers": [ + "@types/node", + "@vitest/browser-playwright", + "happy-dom" + ], + "bin": true + }, + "whatwg-mimetype@3.0.0": { + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==" + }, + "why-is-node-running@2.3.0": { + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dependencies": [ + "siginfo", + "stackback" + ], + "bin": true + }, + "workerd@1.20260811.1": { + "integrity": "sha512-kh+FFm55JQ4ssxhHZV9VPdMQq3D1nHxNJgwxMtWGD4dGppJvLySdguTRDKgeNTvgq6heSz+6TTXyPSDGj8Yllw==", + "optionalDependencies": [ + "@cloudflare/workerd-darwin-64", + "@cloudflare/workerd-darwin-arm64", + "@cloudflare/workerd-linux-64", + "@cloudflare/workerd-linux-arm64", + "@cloudflare/workerd-windows-64" + ], + "scripts": true, + "bin": true + }, + "wrangler@4.123.0": { + "integrity": "sha512-VXo2I1oa0x9aGAKIFPRSQPqTh0RBY5Ktl44YOhNmsJQFUdJKDA2vVTU6Xj+FC2koll6orJqWZN8jbXVIk9O67Q==", + "dependencies": [ + "@cloudflare/kv-asset-handler", + "@cloudflare/unenv-preset", + "blake3-wasm", + "esbuild", + "miniflare", + "path-to-regexp", + "unenv", + "workerd" + ], + "optionalDependencies": [ + "fsevents@2.3.3" + ], + "bin": true + }, + "ws@8.21.0": { + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==" + }, "yaml@2.9.0": { "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", "bin": true + }, + "youch-core@0.3.3": { + "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", + "dependencies": [ + "@poppinss/exception", + "error-stack-parser-es" + ] + }, + "youch@4.1.0-beta.10": { + "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", + "dependencies": [ + "@poppinss/colors", + "@poppinss/dumper", + "@speed-highlight/core", + "cookie", + "youch-core" + ] + }, + "zod@4.4.3": { + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==" } }, "workspace": { @@ -913,18 +1723,19 @@ "dependencies": [ "npm:@changesets/changelog-github@1", "npm:@changesets/cli@3", + "npm:@cloudflare/vitest-pool-workers@~0.21.3", "npm:@tsconfig/strictest@^2.0.8", "npm:@types/node@^22.19.19", - "npm:@types/sinon@^21.0.1", - "npm:esbuild@0.28", + "npm:@vitest/browser-playwright@^4.1.10", + "npm:@vitest/browser@^4.1.10", "npm:eventsource-encoder@^1.0.2", "npm:eventsource-parser@4", + "npm:happy-dom@^20.11.2", "npm:oxfmt@0.52", "npm:oxlint@^1.67.0", "npm:playwright@^1.60.0", - "npm:sinon@22", "npm:typescript@7", - "npm:undici@7" + "npm:vitest@^4.1.10" ] } } diff --git a/package-lock.json b/package-lock.json index 31273d88..c35f20cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,22 +14,30 @@ "devDependencies": { "@changesets/changelog-github": "^1.0.0", "@changesets/cli": "^3.0.0", + "@cloudflare/vitest-pool-workers": "^0.21.3", "@tsconfig/strictest": "^2.0.8", "@types/node": "^22.19.19", - "@types/sinon": "^21.0.1", - "esbuild": "^0.28.0", + "@vitest/browser": "^4.1.10", + "@vitest/browser-playwright": "^4.1.10", "eventsource-encoder": "^1.0.2", + "happy-dom": "^20.11.2", "oxfmt": "^0.52.0", "oxlint": "^1.67.0", "playwright": "^1.60.0", - "sinon": "^22.0.0", "typescript": "^7.0.0", - "undici": "^7.0.0" + "vitest": "^4.1.10" }, "engines": { "node": ">=22.12.0" } }, + "node_modules/@blazediff/core": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@blazediff/core/-/core-1.9.1.tgz", + "integrity": "sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==", + "dev": true, + "license": "MIT" + }, "node_modules/@changesets/apply-release-plan": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-8.0.0.tgz", @@ -330,10 +338,55 @@ "node": ">= 20.12.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", - "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.5.0.tgz", + "integrity": "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==", + "dev": true, + "license": "MIT OR Apache-2.0", + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@cloudflare/unenv-preset": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.16.1.tgz", + "integrity": "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw==", + "dev": true, + "license": "MIT OR Apache-2.0", + "peerDependencies": { + "unenv": "2.0.0-rc.24", + "workerd": ">1.20260305.0 <2.0.0-0" + }, + "peerDependenciesMeta": { + "workerd": { + "optional": true + } + } + }, + "node_modules/@cloudflare/vitest-pool-workers": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@cloudflare/vitest-pool-workers/-/vitest-pool-workers-0.21.3.tgz", + "integrity": "sha512-jCoGRQ6FlsP5adp1GJISvITOGdTHTpsWOq3KkSGIfeDY/5RKjTUagDwaXjpqBXY5gAk6id/QbgnGuCTAg6lSTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cjs-module-lexer": "1.2.3", + "esbuild": "0.28.1", + "miniflare": "5.20260811.1-alpha", + "wrangler": "4.123.0", + "zod": "4.4.3" + }, + "peerDependencies": { + "@vitest/runner": "^4.1.0", + "@vitest/snapshot": "^4.1.0", + "vitest": "^4.1.0" + } + }, + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", "cpu": [ "ppc64" ], @@ -347,10 +400,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", - "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", "cpu": [ "arm" ], @@ -364,10 +417,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", - "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", "cpu": [ "arm64" ], @@ -381,10 +434,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", - "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", "cpu": [ "x64" ], @@ -398,10 +451,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", - "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", "cpu": [ "arm64" ], @@ -415,10 +468,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", - "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", "cpu": [ "x64" ], @@ -432,10 +485,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", - "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", "cpu": [ "arm64" ], @@ -449,10 +502,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", - "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", "cpu": [ "x64" ], @@ -466,10 +519,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", - "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", "cpu": [ "arm" ], @@ -483,10 +536,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", - "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", "cpu": [ "arm64" ], @@ -500,10 +553,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", - "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", "cpu": [ "ia32" ], @@ -517,10 +570,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", - "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", "cpu": [ "loong64" ], @@ -534,10 +587,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", - "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", "cpu": [ "mips64el" ], @@ -551,10 +604,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", - "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", "cpu": [ "ppc64" ], @@ -568,10 +621,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", - "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", "cpu": [ "riscv64" ], @@ -585,10 +638,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", - "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", "cpu": [ "s390x" ], @@ -602,10 +655,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", - "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", "cpu": [ "x64" ], @@ -619,10 +672,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", - "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", "cpu": [ "arm64" ], @@ -636,10 +689,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", - "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", "cpu": [ "x64" ], @@ -653,10 +706,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", - "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", "cpu": [ "arm64" ], @@ -670,10 +723,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", - "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", "cpu": [ "x64" ], @@ -687,10 +740,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", - "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", "cpu": [ "arm64" ], @@ -704,10 +757,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", - "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", "cpu": [ "x64" ], @@ -721,10 +774,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", - "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", "cpu": [ "arm64" ], @@ -738,10 +791,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", - "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", "cpu": [ "ia32" ], @@ -755,10 +808,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", - "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", "cpu": [ "x64" ], @@ -772,211 +825,311 @@ "node": ">=18" } }, - "node_modules/@manypkg/find-root": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-3.1.0.tgz", - "integrity": "sha512-BcSqCyKhBVZ5YkSzOiheMCV41kqAFptW6xGqYSTjkVTl9XQpr+pqHhwgGCOHQtjDCv7Is6EFyA14Sm5GVbVABA==", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "@manypkg/tools": "^2.1.0" + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=20.0.0" + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20260811.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260811.1.tgz", + "integrity": "sha512-i5jqz+ywtOefr0AJbiAc8qxBLfSim/B0WJG7aW3B+pWnoVfMJdUQvi+BWcFKZJ0MoCci3KadTx6g31VfuEEqpQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" } }, - "node_modules/@manypkg/get-packages": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-3.1.0.tgz", - "integrity": "sha512-0TbBVyvPrP7xGYBI/cP8UP+yl/z+HtbTttAD7FMAJgn/kXOTwh5/60TsqP9ZYY710forNfyV0N8P/IE/ujGZJg==", + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20260811.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260811.1.tgz", + "integrity": "sha512-NoOUM/nvaDdm2Onlnz33FikWjtatzulNtvwvy4xs0IrHaTCHwC0c8NwIt6s+AI13FkDs02/vm2I3GTPLCT9+hQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@manypkg/find-root": "^3.1.0", - "@manypkg/tools": "^2.1.0" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=20.0.0" + "node": ">=16" } }, - "node_modules/@manypkg/tools": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@manypkg/tools/-/tools-2.1.2.tgz", - "integrity": "sha512-6QEf6yqFbETdwGITKq57aYoPfX/3K8XFNwsAlx0C1M7o8cb79sv1M3w+tWuWvIcSbNqrLF7OD7YpZMVVz335hQ==", + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20260811.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260811.1.tgz", + "integrity": "sha512-sdYq2jL1AD1supa3fsi5O4zTB28wSjvTHj7Migh6/ts8EROPdvrSwv+rdGHhv8HJNAz/wbIAY3wZsi1Rw4uUIg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "jju": "^1.4.0", - "tinyglobby": "^0.2.13", - "yaml": "^2.9.0" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=20.0.0" + "node": ">=16" } }, - "node_modules/@oxfmt/binding-android-arm-eabi": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.52.0.tgz", - "integrity": "sha512-17EMSJnQ9g+upVHrAUYDMfH5lvRKQ9Nvg8WtEoH72oDr1VpWz+7/o3tD97U1EToen2YAQ/68JmtDYkQUi20dfQ==", + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20260811.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260811.1.tgz", + "integrity": "sha512-RIRv4shbu1kg05sD+DHTpSFCNnb5Dl2SkPDMUykqZa508tkPqe7VVw7gO0Q5msTBGyL0FfFrLuRxwwfA8u5Sow==", "cpu": [ - "arm" + "arm64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "android" + "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=16" } }, - "node_modules/@oxfmt/binding-android-arm64": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.52.0.tgz", - "integrity": "sha512-A2G1IdwGEW2lLJkIxcvuirRH1CzSl/e0NX11zTlW1gvxJThfwbI/BEoaKrTNpm7M2FchvIf6guvIQU7d5iz+OQ==", + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20260811.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260811.1.tgz", + "integrity": "sha512-g6VquwjASlYAibcNW/0E6Zszht4qLkmnXOGwIjjRHl2A0Qz48kVeMcGvyH6eA0G9U3OzZojjYFpP+YeyQmmdjw==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "android" + "win32" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=16" } }, - "node_modules/@oxfmt/binding-darwin-arm64": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.52.0.tgz", - "integrity": "sha512-f9+bLvOYxy7NttCLFTvQ7afmqDOWY4wIP9xdvfj5trQ1qj6f2UFAGwZESlfsMjvJNTyRpXfIlOanCI9FOvoeQA==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "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/@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.2", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.2.tgz", + "integrity": "sha512-eEieHsMksAW4IiO5NzauESRl2D2qz3J/kwUxUrSfV06A93eEaRfMpHXyUb1mAqrR7i8U9A0GRqE9pjn6u1Jjpg==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "darwin" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.1" } }, - "node_modules/@oxfmt/binding-darwin-x64": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.52.0.tgz", - "integrity": "sha512-YSTB9sJ5nnQd/Q0ddHkgof0ZCHPAnWZT1IW2SJ8omz7CP7KluJhO1fNHrpqdxCtpztJwSs4hY1uAee35wKxxaw==", + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.2.tgz", + "integrity": "sha512-BaktuGPCeHJMARpodR8jK4uKiZrPAy9WrfQW0sdI37clracq8Bp01AYS3SZgi5FS/y5twa9t4+LIuuxQjqRrWw==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "darwin" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.1" } }, - "node_modules/@oxfmt/binding-freebsd-x64": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.52.0.tgz", - "integrity": "sha512-NIrRNTTPCs4UbmVs0bxLSCDlLCtIRMJIXklNKaXa5Oj2/K1UIMBvgE8+uPVo01Io3N9HF0+GAX+aAHjUgZS7vA==", - "cpu": [ - "x64" - ], + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.2.tgz", + "integrity": "sha512-YoAxdnd8hPUkvLHd3bWY+YA8nw3xM/RyRopYucNsWHVSan8NLVM3X2volsfoRDcXdUJPg6tXahSd7HXPK7lRnw==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "freebsd" ], + "dependencies": { + "@img/sharp-wasm32": "0.35.2" + }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxfmt/binding-linux-arm-gnueabihf": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.52.0.tgz", - "integrity": "sha512-JXUCde8mn3GpgQouz2PXUokgy/uT1QrRJBL2s983VWcSQp62wTFYiNXgTKdeo1Jgbr0IgUnKKvzIk/YBlj/nVQ==", + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.1.tgz", + "integrity": "sha512-4V/M3roRMTYjiwZY9IOVQOE8OyeCxFAkYmyZDrZl51uOKjibm3oeEJ4WAmLxutAfzFbC9jqUiPs2gbnGflH+7g==", "cpu": [ - "arm" + "arm64" ], "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "linux" + "darwin" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxfmt/binding-linux-arm-musleabihf": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.52.0.tgz", - "integrity": "sha512-psbUXaRZ+V8DaXz10Qf7LSHtdtdKAmC8fxXgeU608jjzrmWK4quamZMOpl6sf+dikoFHA85uE93Q0BqxrCdQrQ==", + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.1.tgz", + "integrity": "sha512-c0/DxItpJv2+dGhgycJBBgotdqruGYDvA79drdh0MD1dFpy7JzJ/PlXwi1H4rFf0eTy8tgbI91aHDnZIceY3jQ==", "cpu": [ - "arm" + "x64" ], "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "linux" + "darwin" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxfmt/binding-linux-arm64-gnu": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.52.0.tgz", - "integrity": "sha512-Jw7MgWUU9lcLCcy82updISP3EthTlfvAwR6gWNxPzqly7+fLvOi2gHQE9xXQjpqaVLm/8P+gOzlv9ODuoVlaaw==", + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.1.tgz", + "integrity": "sha512-aGGy9aWzXgHBG7HNyQPWorZthlp7+x6fDRoPAQbGO3ThcttuTyKIx3NuSHb6zb4gBNq6/yNn9f1cy9nFKS/Vmg==", "cpu": [ - "arm64" + "arm" ], "dev": true, "libc": [ "glibc" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxfmt/binding-linux-arm64-musl": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.52.0.tgz", - "integrity": "sha512-wZg6bLjDvh2KibyI3QFUYo8GTXneIFsd0JvehtvJiUmQ8WRPERgxd/VM4ctWb86U5FT1FkqgS8/wZKVB+AZScg==", + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.1.tgz", + "integrity": "sha512-JznefmcK9j1JKPz8AkQDh89kjojubyfOasWBPKfzMIhPwsgDy9evpE/naJTXXXmghS1iFwR8u/kTwh/I2/+GCw==", "cpu": [ "arm64" ], "dev": true, "libc": [ - "musl" + "glibc" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxfmt/binding-linux-ppc64-gnu": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.52.0.tgz", - "integrity": "sha512-IngE8uxhNvxcMrLjZNDo9xNLY7rEK33AKnaMd2B46he1e/mz2CfcW6If/U1wUjdRZddm1QzQaciqZkuMkdh1FA==", + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.1.tgz", + "integrity": "sha512-1EkwGNCZk6iWNCMWqrvdJ+r1j0PT1zIz60CNPhYnJlK/zyeWqlsPZIe+ocBVqPF8k/Ssee/NCk+tE9Ryrko6ng==", "cpu": [ "ppc64" ], @@ -984,19 +1137,19 @@ "libc": [ "glibc" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxfmt/binding-linux-riscv64-gnu": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.52.0.tgz", - "integrity": "sha512-H3+DdFMv/efN3Efmhsv18jDrpiWWqKG7wsfAlQBqAt6z/E2Bx+TwEj2Nowe51CPOWB8/mFBC2dAMSgVFLvvowA==", + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.1.tgz", + "integrity": "sha512-Ilays+w2bXdnxzxtQdmXR62u8o8GYa3eL4+Gr+1KiE4xperMZUslRaVPJwwPkzlHEjGfXAfRVAa/7CYCtSqsBw==", "cpu": [ "riscv64" ], @@ -1004,79 +1157,79 @@ "libc": [ "glibc" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxfmt/binding-linux-riscv64-musl": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.52.0.tgz", - "integrity": "sha512-zji+1kb7lJKohSDjzC1IsS+K/cKRs1hdVf0ZH0VbdbiakmtLvN9twBoXo/k8VdjFax7kfo+DyPxS7vv52br1aw==", + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.1.tgz", + "integrity": "sha512-VfBwVHQTbRoj4XlpA/KLZ7ltgMpz+4WSejFzQ+GnoImjo1PtEJ59QB2qR1xQEeRPYIkNrPIm2L4cICMvz4C2ew==", "cpu": [ - "riscv64" + "s390x" ], "dev": true, "libc": [ - "musl" + "glibc" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxfmt/binding-linux-s390x-gnu": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.52.0.tgz", - "integrity": "sha512-hcLBYedpCy7ToUvvBidWk7+11Yhg1oAZ4+6hKPic/mQI6NaqXJSXMps5nFlwUuX2ewhtLZZDPg63TI042qGKBg==", + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.1.tgz", + "integrity": "sha512-+c8ukgwU62DS54nCAjw7keOfHUkmr0B5QHEdcOqRnodF/MNXJbVI8Eopoj4B/0H8Asr65I+A4Amrn7a85/md6A==", "cpu": [ - "s390x" + "x64" ], "dev": true, "libc": [ "glibc" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxfmt/binding-linux-x64-gnu": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.52.0.tgz", - "integrity": "sha512-IDO2loXK2OtTOhSPchU9MW25mWL2QCDGdJbjN8MXKZVS80qXe5gMTwQWu/gMJ3juoBHbkuUZNB2N1LHzNT7DoA==", + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.1.tgz", + "integrity": "sha512-qlKb/pwbkAi1WMsJrYHk7CuDrd12s27U2QnRhFYUoJNrRCmkosMTttuRFat/DDB3IlDm5qE1TJgZ4JDnHX8Ldw==", "cpu": [ - "x64" + "arm64" ], "dev": true, "libc": [ - "glibc" + "musl" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxfmt/binding-linux-x64-musl": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.52.0.tgz", - "integrity": "sha512-mAV2Hjn0SatJ+KoAzKUC3eJhdJ8wv+3m1KyuS0dTsbF0c5weq+QrCt/DRZZM+uj/XiKzCDEUKYsBF30e2qkcyw==", + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.1.tgz", + "integrity": "sha512-yO21HwoUVLN8Qa+/SBjQLMYwBWAVJjeGPNe+hc0OUeMeifEtJqu5a1c4HayE1nNpDih9y3/KkoltfkDodmKAlg==", "cpu": [ "x64" ], @@ -1084,1360 +1237,3961 @@ "libc": [ "musl" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxfmt/binding-openharmony-arm64": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.52.0.tgz", - "integrity": "sha512-vd4npaUIwChxp7XzkqmepBWTT9YMcSe/NBApVGPC30/lLyOVaV3dvma1SKo03t8O73BPRAG7EyJzGlN5cJM5hQ==", + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.2.tgz", + "integrity": "sha512-SE4kzF2mepn6z+6E7L6lsV8FzuLL6IPQdyX8ZiwROAG/G8td+hP/m7FsFPwidtrF19gvajuC9l6TxAVcsA4S7A==", "cpu": [ - "arm64" + "arm" ], "dev": true, - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ - "openharmony" + "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.1" } }, - "node_modules/@oxfmt/binding-win32-arm64-msvc": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.52.0.tgz", - "integrity": "sha512-k2sz6gWQdMfh5HPpIS+Bw/0UEV/kaK2xuqJRrWL233sEHx9WLlsmvlPFM4HUNThkYbSN0U0vPW7LVKZWDS8hPQ==", + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.2.tgz", + "integrity": "sha512-af12Pnd0ZGu2HfP8NayB0kk6eC/lrfbQE6HlR4jD+34wdJ1Vw9TF6TMn6ZvffT+WgqVsl0hRbmNvz2u/23VmwA==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.1" } }, - "node_modules/@oxfmt/binding-win32-ia32-msvc": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.52.0.tgz", - "integrity": "sha512-rhke69GTcArodLHpjMTfNnvjTEBryDeZcUCKK/VjXDMtfTULl6QRh0ymX5/hbCUv2WjYm9h/QbW++q2vE15gWQ==", + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.2.tgz", + "integrity": "sha512-hYSBm7zcNtDCozCxQHYZJiu63b/bXsgRZuOxCIBZsStMM9Vap47iFHdbX4kCvQsblPB/k+clhELpdQJHQLSHvg==", "cpu": [ - "ia32" + "ppc64" ], "dev": true, - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.1" } }, - "node_modules/@oxfmt/binding-win32-x64-msvc": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.52.0.tgz", - "integrity": "sha512-q5xL7oeXkZdEtNZWBdvehJcmt+GRu9l2bK40yJs1jJXlqq+r0Hygb1rTjq+FM2o/2xyt4cufH6KRplHp3Jjsvw==", + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.2.tgz", + "integrity": "sha512-qQt0Kc13+Hoan/Awq/qMSQw3L+RI1NCRPgD5cUJ/1WSSmIoysLOc72jlRM3E0OHN9Yr313jgeQ2T+zW+F03QFA==", "cpu": [ - "x64" + "riscv64" ], "dev": true, - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.1" } }, - "node_modules/@oxlint/binding-android-arm-eabi": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.78.0.tgz", - "integrity": "sha512-Bu819lmAfZMUHErrpe0cEWj3iaefuUODHSU8+UbXy67V/r7/7f4K3FL0NmbD85E+wiFLDYuhP8Zlv0XnVeXshw==", + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.2.tgz", + "integrity": "sha512-E4fLLfRPzDLlEeDaTzI98OFLcv++WL5ChLLMwPoVd0CIoZQqupBSNbOisPL5am9XsbQ9T84+iiMpUvbFtkunbA==", "cpu": [ - "arm" + "s390x" ], "dev": true, - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ - "android" + "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.1" } }, - "node_modules/@oxlint/binding-android-arm64": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.78.0.tgz", - "integrity": "sha512-CDfxZgB61B7buRdY2FJoAYYPPXCZ1EoC1LKscnC5dg3kjobdxiconvAvvN1BmHyW4PyFT3jRLDag/BY/roSNBQ==", + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.2.tgz", + "integrity": "sha512-gi0zFJJRLswfCZmHtJdikXPOc5u7qamSOS3NHedLqLd4W8Q0NqjdBr6TTRIgsfFjqfTsHFgdfvJ9LwqSgcHiAA==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ - "android" + "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.1" } }, - "node_modules/@oxlint/binding-darwin-arm64": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.78.0.tgz", - "integrity": "sha512-2Y2U9Ahrz+OO0Ej88f9SJYq51/jUBp1Mc7iZu0ukrbeeZ3gpRGfzIFnoqfHDY96xr0GEfNrPUBFEy0nN5aD7HA==", + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.2.tgz", + "integrity": "sha512-siWbOW1u6HFnFLrp0waKyW7VEf7jYvcDWdrXEFa8AkdAQgEvuu5Fz8/Y70w9EeqAdwDtfU012BhEHHaDqvQNzg==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", + "libc": [ + "musl" + ], + "license": "Apache-2.0", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.1" } }, - "node_modules/@oxlint/binding-darwin-x64": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.78.0.tgz", - "integrity": "sha512-rpych6eJq6m9jDRypTEaPD1xysaEW5h9+xuxhGK/QhOg+/xaqPZrCrTNoIl/f3nEjuJeCEmstNDlrE9rJi/3/g==", + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.2.tgz", + "integrity": "sha512-YBqMMcjDi4QGYiSn4vNOYBhmlC4z5AXqkOUUqI2e0AFA4urNv4ESgOgwNl3K+4etQhha0twXlzeF20bbULm9Yg==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", + "libc": [ + "musl" + ], + "license": "Apache-2.0", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.1" } }, - "node_modules/@oxlint/binding-freebsd-x64": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.78.0.tgz", - "integrity": "sha512-IcMGrQT3QizkOESUJd5et+rOhVqSkNDfNik1cvrKDqIbzqx9KMtRswpFgkCuNTSwylCFLKhGUu8KmqY1ZnC0Dg==", - "cpu": [ - "x64" - ], + "node_modules/@img/sharp-wasm32": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.2.tgz", + "integrity": "sha512-Mrv4JQNYVQ94xH+jzZ9r+gowleN8mv2FTgKT+PI6bx5C0G8TdNYndu161pg2i7uoBwxy2ImPMHrJOM2LZef7Bw==", "dev": true, - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@emnapi/runtime": "^1.11.1" + }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxlint/binding-linux-arm-gnueabihf": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.78.0.tgz", - "integrity": "sha512-/uLdoJ0IXE6vo/0f0LKjinQAp+re+VMaCWaNT8ENIv2EOCkSsc8SGaflXAuW0Jua2dq5+GLVWm1NQK7P3UFSNQ==", + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.2.tgz", + "integrity": "sha512-QNV27pxs9wpApEiCfvHM1RDoP1w1+2KrUWWDPEhEwg+latvOrfuhWrHWZKwdSFwU6jh3myjw/yOCRsUIuOft3g==", "cpu": [ - "arm" + "wasm32" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@img/sharp-wasm32": "0.35.2" + }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxlint/binding-linux-arm-musleabihf": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.78.0.tgz", - "integrity": "sha512-7xi4Wb/O8NRJhLoUXmDJMUVpNYvB5kefdhFU1Jb8rtae4QoXlTiLwI14X4YvAXVZLNZChP8m5qO9SQAlWQTbkQ==", + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.2.tgz", + "integrity": "sha512-BiVRYc/t6/Vl3e1hBx0hugG4oN9Pydf4fgMSpxTQJmwGUg/YoXTWHiFeRymHfCZzifxu4F4rpk/I67D0LQ20wQ==", "cpu": [ - "arm" + "arm64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxlint/binding-linux-arm64-gnu": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.78.0.tgz", - "integrity": "sha512-4hFW0+fVXa3OIh1Y4A5SPkmvI4wuuBSrCVKzOyE7PTjhc7yEqZ1pmvEEeS5Lj/MaqvegFxXyF33N+6jkehxdyg==", + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.2.tgz", + "integrity": "sha512-YYEhx9PImCC7T0tI8JDMi4DB9LwLCXCU5OWNYEXAxh5Q1ShKkyC6byxzoBJ3gEFDnH2lQckWuDe70G7mB2XJog==", "cpu": [ - "arm64" + "ia32" ], "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxlint/binding-linux-arm64-musl": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.78.0.tgz", - "integrity": "sha512-oC0mvsgBJjlMijSDEhx9KuvR9zYeHXceA9MjbuXB1F8NSR78Yj2unOBrstEvTVaq+pko+kuue6DajC00eqvTdg==", + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.2.tgz", + "integrity": "sha512-imoOyBcoM/iiUr4J6VPpCNjPnjvP/Gks95898yB8YqoGGYmHYbOyCuNv9FMhFgtaiHFGbHW8bxKqRV6VjtXThQ==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@oxlint/binding-linux-ppc64-gnu": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.78.0.tgz", - "integrity": "sha512-XAllT5SUZS+ohjuZ3/5S0cwe0r7eboiuigeStCZ5DXRYx/2KVM2UvQXvAfyzXEimtQjAB7cDQ2YxDe2Zl2WNQQ==", - "cpu": [ - "ppc64" - ], + "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, - "libc": [ - "glibc" - ], "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=6.0.0" } }, - "node_modules/@oxlint/binding-linux-riscv64-gnu": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.78.0.tgz", - "integrity": "sha512-trucMER/0QtecoXvc1y/UVqE3kwJipDwrx4oHfj+nNm3dq2zjP44WT0CfHNDPM3G1DXIkx/gY6lAD21NSCZVhA==", - "cpu": [ - "riscv64" - ], + "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.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@oxlint/binding-linux-riscv64-musl": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.78.0.tgz", - "integrity": "sha512-cm3O4F/HQbdzOUX5mKHqG5KDL6E5w0pnlZ+fbBy2rmLryPOowkuLagFHTopQsEIpjcaZoPOrL+BmmAytAG9HFg==", + "node_modules/@manypkg/find-root": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-3.1.0.tgz", + "integrity": "sha512-BcSqCyKhBVZ5YkSzOiheMCV41kqAFptW6xGqYSTjkVTl9XQpr+pqHhwgGCOHQtjDCv7Is6EFyA14Sm5GVbVABA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@manypkg/tools": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@manypkg/get-packages": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-3.1.0.tgz", + "integrity": "sha512-0TbBVyvPrP7xGYBI/cP8UP+yl/z+HtbTttAD7FMAJgn/kXOTwh5/60TsqP9ZYY710forNfyV0N8P/IE/ujGZJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@manypkg/find-root": "^3.1.0", + "@manypkg/tools": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@manypkg/tools": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@manypkg/tools/-/tools-2.1.2.tgz", + "integrity": "sha512-6QEf6yqFbETdwGITKq57aYoPfX/3K8XFNwsAlx0C1M7o8cb79sv1M3w+tWuWvIcSbNqrLF7OD7YpZMVVz335hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "jju": "^1.4.0", + "tinyglobby": "^0.2.13", + "yaml": "^2.9.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "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/@oxfmt/binding-android-arm-eabi": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.52.0.tgz", + "integrity": "sha512-17EMSJnQ9g+upVHrAUYDMfH5lvRKQ9Nvg8WtEoH72oDr1VpWz+7/o3tD97U1EToen2YAQ/68JmtDYkQUi20dfQ==", "cpu": [ - "riscv64" + "arm" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ - "linux" + "android" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@oxlint/binding-linux-s390x-gnu": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.78.0.tgz", - "integrity": "sha512-33wRf6HqGNsybJ3qX4cGaQN2ODPxNmc1rMa0mrTmx3eFq1VzOnvQooi9bIGVYakW8a/wmqVx1mgsUm8R2xfTiw==", + "node_modules/@oxfmt/binding-android-arm64": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.52.0.tgz", + "integrity": "sha512-A2G1IdwGEW2lLJkIxcvuirRH1CzSl/e0NX11zTlW1gvxJThfwbI/BEoaKrTNpm7M2FchvIf6guvIQU7d5iz+OQ==", "cpu": [ - "s390x" + "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ - "linux" + "android" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@oxlint/binding-linux-x64-gnu": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.78.0.tgz", - "integrity": "sha512-rRdISSYegj6VganMZ9tjRjijowfHJ09IZU01i0toBAqr6n5LEtwHq2IeS4FjW2RoskOHlb6efB26H5izYb3GEQ==", + "node_modules/@oxfmt/binding-darwin-arm64": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.52.0.tgz", + "integrity": "sha512-f9+bLvOYxy7NttCLFTvQ7afmqDOWY4wIP9xdvfj5trQ1qj6f2UFAGwZESlfsMjvJNTyRpXfIlOanCI9FOvoeQA==", "cpu": [ - "x64" + "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ - "linux" + "darwin" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@oxlint/binding-linux-x64-musl": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.78.0.tgz", - "integrity": "sha512-GmsP4rW0xTL6u5CVdcDsaN5Fbc7hBc382Wmar1kttbnwSEviM+rSINKOMQ+UQ6iH+AGwC+8gaAiwu134Tgh6Lg==", + "node_modules/@oxfmt/binding-darwin-x64": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.52.0.tgz", + "integrity": "sha512-YSTB9sJ5nnQd/Q0ddHkgof0ZCHPAnWZT1IW2SJ8omz7CP7KluJhO1fNHrpqdxCtpztJwSs4hY1uAee35wKxxaw==", "cpu": [ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ - "linux" + "darwin" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@oxlint/binding-openharmony-arm64": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.78.0.tgz", - "integrity": "sha512-sy9yeYuADc8a+n4TLBayzMCZiHPW78DcIFVpOXTmdKHWQeM9xe5uzkqIIZmi326D5hY9XVwacipEB1p7tQjPAg==", + "node_modules/@oxfmt/binding-freebsd-x64": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.52.0.tgz", + "integrity": "sha512-NIrRNTTPCs4UbmVs0bxLSCDlLCtIRMJIXklNKaXa5Oj2/K1UIMBvgE8+uPVo01Io3N9HF0+GAX+aAHjUgZS7vA==", "cpu": [ - "arm64" + "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "openharmony" + "freebsd" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@oxlint/binding-win32-arm64-msvc": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.78.0.tgz", - "integrity": "sha512-rjc2hF1KfMi8fZj1X/m3AmnHbdsF3rL0v6KQg0Uc880Yb2khjz+3U14sfdZ7jWTpRnN1m1NQa/TT7uU9lJWPrA==", + "node_modules/@oxfmt/binding-linux-arm-gnueabihf": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.52.0.tgz", + "integrity": "sha512-JXUCde8mn3GpgQouz2PXUokgy/uT1QrRJBL2s983VWcSQp62wTFYiNXgTKdeo1Jgbr0IgUnKKvzIk/YBlj/nVQ==", "cpu": [ - "arm64" + "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@oxlint/binding-win32-ia32-msvc": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.78.0.tgz", - "integrity": "sha512-zcuXFVrEFHIafRfkCQT8w/Xe41o07ozl/vwHq7p94vB29xVzsB0sZGYORU1jhcYKv3Lr0J3HbJ2T4fHH5rWmvA==", + "node_modules/@oxfmt/binding-linux-arm-musleabihf": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.52.0.tgz", + "integrity": "sha512-psbUXaRZ+V8DaXz10Qf7LSHtdtdKAmC8fxXgeU608jjzrmWK4quamZMOpl6sf+dikoFHA85uE93Q0BqxrCdQrQ==", "cpu": [ - "ia32" + "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@oxlint/binding-win32-x64-msvc": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.78.0.tgz", - "integrity": "sha512-Sb5ocmLSuYeOuXd+CFOToGKp/gjXUEWDnvIGwhnh8aq8wY4TMmEnKnvbogSW7RdMZv77JSARduS7/gv+khYEjA==", + "node_modules/@oxfmt/binding-linux-arm64-gnu": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.52.0.tgz", + "integrity": "sha512-Jw7MgWUU9lcLCcy82updISP3EthTlfvAwR6gWNxPzqly7+fLvOi2gHQE9xXQjpqaVLm/8P+gOzlv9ODuoVlaaw==", "cpu": [ - "x64" + "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@pnpm/deps.graph-sequencer": { - "version": "1100.0.1", - "resolved": "https://registry.npmjs.org/@pnpm/deps.graph-sequencer/-/deps.graph-sequencer-1100.0.1.tgz", - "integrity": "sha512-pOr5+q1fLYKwFN3LAJuGZEnfXDcQ73zqgDHMtGy+K+uIoUqyY+6MeDCWFwfu+4EFuq76I5EPFofoNAI+Bmmq4A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=22.13" - }, - "funding": { - "url": "https://opencollective.com/pnpm" - } - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "15.4.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.4.0.tgz", - "integrity": "sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-10.0.2.tgz", - "integrity": "sha512-8lVwD1Df1BmzoaOLhMcGGcz/Jyr5QY2KSB75/YK1QgKzoabTeLdIVyhXNZK9ojfSKSdirbXqdbsXXqP9/Ve8+A==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "type-detect": "^4.1.0" - } - }, - "node_modules/@sinonjs/samsam/node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "node_modules/@oxfmt/binding-linux-arm64-musl": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.52.0.tgz", + "integrity": "sha512-wZg6bLjDvh2KibyI3QFUYo8GTXneIFsd0JvehtvJiUmQ8WRPERgxd/VM4ctWb86U5FT1FkqgS8/wZKVB+AZScg==", + "cpu": [ + "arm64" + ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4" - } - }, - "node_modules/@tsconfig/strictest": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@tsconfig/strictest/-/strictest-2.0.8.tgz", - "integrity": "sha512-XnQ7vNz5HRN0r88GYf1J9JJjqtZPiHt2woGJOo2dYqyHGGcd6OLGqSlBB6p1j9mpzja6Oe5BoPqWmeDx6X9rLw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "22.20.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", - "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/sinon": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-21.0.1.tgz", - "integrity": "sha512-5yoJSqLbjH8T9V2bksgRayuhpZy+723/z6wBOR+Soe4ZlXC0eW8Na71TeaZPUWDQvM7LYKa9UGFc6LRqxiR5fQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/sinonjs__fake-timers": "*" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-15.0.1.tgz", - "integrity": "sha512-Ko2tjWJq8oozHzHV+reuvS5KYIRAokHnGbDwGh/J64LntgpbuylF74ipEL24HCyRjf9FOlBiBHWBR1RlVKsI1w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript/typescript-aix-ppc64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", - "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", + "node_modules/@oxfmt/binding-linux-ppc64-gnu": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.52.0.tgz", + "integrity": "sha512-IngE8uxhNvxcMrLjZNDo9xNLY7rEK33AKnaMd2B46he1e/mz2CfcW6If/U1wUjdRZddm1QzQaciqZkuMkdh1FA==", "cpu": [ "ppc64" ], "dev": true, - "license": "Apache-2.0", + "libc": [ + "glibc" + ], + "license": "MIT", "optional": true, "os": [ - "aix" + "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-darwin-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", - "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", + "node_modules/@oxfmt/binding-linux-riscv64-gnu": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.52.0.tgz", + "integrity": "sha512-H3+DdFMv/efN3Efmhsv18jDrpiWWqKG7wsfAlQBqAt6z/E2Bx+TwEj2Nowe51CPOWB8/mFBC2dAMSgVFLvvowA==", "cpu": [ - "arm64" + "riscv64" ], "dev": true, - "license": "Apache-2.0", + "libc": [ + "glibc" + ], + "license": "MIT", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-darwin-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", - "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", + "node_modules/@oxfmt/binding-linux-riscv64-musl": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.52.0.tgz", + "integrity": "sha512-zji+1kb7lJKohSDjzC1IsS+K/cKRs1hdVf0ZH0VbdbiakmtLvN9twBoXo/k8VdjFax7kfo+DyPxS7vv52br1aw==", "cpu": [ - "x64" + "riscv64" ], "dev": true, - "license": "Apache-2.0", + "libc": [ + "musl" + ], + "license": "MIT", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-freebsd-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", - "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "node_modules/@oxfmt/binding-linux-s390x-gnu": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.52.0.tgz", + "integrity": "sha512-hcLBYedpCy7ToUvvBidWk7+11Yhg1oAZ4+6hKPic/mQI6NaqXJSXMps5nFlwUuX2ewhtLZZDPg63TI042qGKBg==", "cpu": [ - "arm64" + "s390x" ], "dev": true, - "license": "Apache-2.0", + "libc": [ + "glibc" + ], + "license": "MIT", "optional": true, "os": [ - "freebsd" + "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-freebsd-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", - "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "node_modules/@oxfmt/binding-linux-x64-gnu": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.52.0.tgz", + "integrity": "sha512-IDO2loXK2OtTOhSPchU9MW25mWL2QCDGdJbjN8MXKZVS80qXe5gMTwQWu/gMJ3juoBHbkuUZNB2N1LHzNT7DoA==", "cpu": [ "x64" ], "dev": true, - "license": "Apache-2.0", + "libc": [ + "glibc" + ], + "license": "MIT", "optional": true, "os": [ - "freebsd" + "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-arm": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", - "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", + "node_modules/@oxfmt/binding-linux-x64-musl": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.52.0.tgz", + "integrity": "sha512-mAV2Hjn0SatJ+KoAzKUC3eJhdJ8wv+3m1KyuS0dTsbF0c5weq+QrCt/DRZZM+uj/XiKzCDEUKYsBF30e2qkcyw==", "cpu": [ - "arm" + "x64" ], "dev": true, - "license": "Apache-2.0", + "libc": [ + "musl" + ], + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", - "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", + "node_modules/@oxfmt/binding-openharmony-arm64": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.52.0.tgz", + "integrity": "sha512-vd4npaUIwChxp7XzkqmepBWTT9YMcSe/NBApVGPC30/lLyOVaV3dvma1SKo03t8O73BPRAG7EyJzGlN5cJM5hQ==", "cpu": [ "arm64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "linux" + "openharmony" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-loong64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", - "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "node_modules/@oxfmt/binding-win32-arm64-msvc": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.52.0.tgz", + "integrity": "sha512-k2sz6gWQdMfh5HPpIS+Bw/0UEV/kaK2xuqJRrWL233sEHx9WLlsmvlPFM4HUNThkYbSN0U0vPW7LVKZWDS8hPQ==", "cpu": [ - "loong64" + "arm64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-mips64el": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", - "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "node_modules/@oxfmt/binding-win32-ia32-msvc": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.52.0.tgz", + "integrity": "sha512-rhke69GTcArodLHpjMTfNnvjTEBryDeZcUCKK/VjXDMtfTULl6QRh0ymX5/hbCUv2WjYm9h/QbW++q2vE15gWQ==", "cpu": [ - "mips64el" + "ia32" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-ppc64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", - "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "node_modules/@oxfmt/binding-win32-x64-msvc": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.52.0.tgz", + "integrity": "sha512-q5xL7oeXkZdEtNZWBdvehJcmt+GRu9l2bK40yJs1jJXlqq+r0Hygb1rTjq+FM2o/2xyt4cufH6KRplHp3Jjsvw==", "cpu": [ - "ppc64" + "x64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-riscv64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", - "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", + "node_modules/@oxlint/binding-android-arm-eabi": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.78.0.tgz", + "integrity": "sha512-Bu819lmAfZMUHErrpe0cEWj3iaefuUODHSU8+UbXy67V/r7/7f4K3FL0NmbD85E+wiFLDYuhP8Zlv0XnVeXshw==", "cpu": [ - "riscv64" + "arm" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "linux" + "android" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-s390x": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", - "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", + "node_modules/@oxlint/binding-android-arm64": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.78.0.tgz", + "integrity": "sha512-CDfxZgB61B7buRdY2FJoAYYPPXCZ1EoC1LKscnC5dg3kjobdxiconvAvvN1BmHyW4PyFT3jRLDag/BY/roSNBQ==", "cpu": [ - "s390x" + "arm64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "linux" + "android" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", - "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", + "node_modules/@oxlint/binding-darwin-arm64": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.78.0.tgz", + "integrity": "sha512-2Y2U9Ahrz+OO0Ej88f9SJYq51/jUBp1Mc7iZu0ukrbeeZ3gpRGfzIFnoqfHDY96xr0GEfNrPUBFEy0nN5aD7HA==", "cpu": [ - "x64" + "arm64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "linux" + "darwin" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-netbsd-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", - "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", + "node_modules/@oxlint/binding-darwin-x64": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.78.0.tgz", + "integrity": "sha512-rpych6eJq6m9jDRypTEaPD1xysaEW5h9+xuxhGK/QhOg+/xaqPZrCrTNoIl/f3nEjuJeCEmstNDlrE9rJi/3/g==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "netbsd" + "darwin" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-netbsd-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", - "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", + "node_modules/@oxlint/binding-freebsd-x64": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.78.0.tgz", + "integrity": "sha512-IcMGrQT3QizkOESUJd5et+rOhVqSkNDfNik1cvrKDqIbzqx9KMtRswpFgkCuNTSwylCFLKhGUu8KmqY1ZnC0Dg==", "cpu": [ "x64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "netbsd" + "freebsd" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-openbsd-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", - "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", + "node_modules/@oxlint/binding-linux-arm-gnueabihf": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.78.0.tgz", + "integrity": "sha512-/uLdoJ0IXE6vo/0f0LKjinQAp+re+VMaCWaNT8ENIv2EOCkSsc8SGaflXAuW0Jua2dq5+GLVWm1NQK7P3UFSNQ==", "cpu": [ - "arm64" + "arm" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "openbsd" + "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-openbsd-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", - "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", + "node_modules/@oxlint/binding-linux-arm-musleabihf": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.78.0.tgz", + "integrity": "sha512-7xi4Wb/O8NRJhLoUXmDJMUVpNYvB5kefdhFU1Jb8rtae4QoXlTiLwI14X4YvAXVZLNZChP8m5qO9SQAlWQTbkQ==", "cpu": [ - "x64" + "arm" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "openbsd" + "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-sunos-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", - "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", + "node_modules/@oxlint/binding-linux-arm64-gnu": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.78.0.tgz", + "integrity": "sha512-4hFW0+fVXa3OIh1Y4A5SPkmvI4wuuBSrCVKzOyE7PTjhc7yEqZ1pmvEEeS5Lj/MaqvegFxXyF33N+6jkehxdyg==", "cpu": [ - "x64" + "arm64" ], "dev": true, - "license": "Apache-2.0", + "libc": [ + "glibc" + ], + "license": "MIT", "optional": true, "os": [ - "sunos" + "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-win32-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", - "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", + "node_modules/@oxlint/binding-linux-arm64-musl": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.78.0.tgz", + "integrity": "sha512-oC0mvsgBJjlMijSDEhx9KuvR9zYeHXceA9MjbuXB1F8NSR78Yj2unOBrstEvTVaq+pko+kuue6DajC00eqvTdg==", "cpu": [ "arm64" ], "dev": true, - "license": "Apache-2.0", + "libc": [ + "musl" + ], + "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-win32-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", - "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", + "node_modules/@oxlint/binding-linux-ppc64-gnu": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.78.0.tgz", + "integrity": "sha512-XAllT5SUZS+ohjuZ3/5S0cwe0r7eboiuigeStCZ5DXRYx/2KVM2UvQXvAfyzXEimtQjAB7cDQ2YxDe2Zl2WNQQ==", "cpu": [ - "x64" + "ppc64" ], "dev": true, - "license": "Apache-2.0", + "libc": [ + "glibc" + ], + "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/cac": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cac/-/cac-7.0.0.tgz", - "integrity": "sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==", + "node_modules/@oxlint/binding-linux-riscv64-gnu": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.78.0.tgz", + "integrity": "sha512-trucMER/0QtecoXvc1y/UVqE3kwJipDwrx4oHfj+nNm3dq2zjP44WT0CfHNDPM3G1DXIkx/gY6lAD21NSCZVhA==", + "cpu": [ + "riscv64" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=20.19.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/dataloader": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.3.tgz", - "integrity": "sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA==", - "dev": true, - "license": "MIT" - }, - "node_modules/diff": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz", - "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==", + "node_modules/@oxlint/binding-linux-riscv64-musl": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.78.0.tgz", + "integrity": "sha512-cm3O4F/HQbdzOUX5mKHqG5KDL6E5w0pnlZ+fbBy2rmLryPOowkuLagFHTopQsEIpjcaZoPOrL+BmmAytAG9HFg==", + "cpu": [ + "riscv64" + ], "dev": true, - "license": "BSD-3-Clause", + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.3.1" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/esbuild": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", - "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "node_modules/@oxlint/binding-linux-s390x-gnu": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.78.0.tgz", + "integrity": "sha512-33wRf6HqGNsybJ3qX4cGaQN2ODPxNmc1rMa0mrTmx3eFq1VzOnvQooi9bIGVYakW8a/wmqVx1mgsUm8R2xfTiw==", + "cpu": [ + "s390x" + ], "dev": true, - "hasInstallScript": true, + "libc": [ + "glibc" + ], "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.2", - "@esbuild/android-arm": "0.28.2", - "@esbuild/android-arm64": "0.28.2", - "@esbuild/android-x64": "0.28.2", - "@esbuild/darwin-arm64": "0.28.2", - "@esbuild/darwin-x64": "0.28.2", - "@esbuild/freebsd-arm64": "0.28.2", - "@esbuild/freebsd-x64": "0.28.2", - "@esbuild/linux-arm": "0.28.2", - "@esbuild/linux-arm64": "0.28.2", - "@esbuild/linux-ia32": "0.28.2", - "@esbuild/linux-loong64": "0.28.2", - "@esbuild/linux-mips64el": "0.28.2", - "@esbuild/linux-ppc64": "0.28.2", - "@esbuild/linux-riscv64": "0.28.2", - "@esbuild/linux-s390x": "0.28.2", - "@esbuild/linux-x64": "0.28.2", - "@esbuild/netbsd-arm64": "0.28.2", - "@esbuild/netbsd-x64": "0.28.2", - "@esbuild/openbsd-arm64": "0.28.2", - "@esbuild/openbsd-x64": "0.28.2", - "@esbuild/openharmony-arm64": "0.28.2", - "@esbuild/sunos-x64": "0.28.2", - "@esbuild/win32-arm64": "0.28.2", - "@esbuild/win32-ia32": "0.28.2", - "@esbuild/win32-x64": "0.28.2" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/eventsource-encoder": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/eventsource-encoder/-/eventsource-encoder-1.0.2.tgz", - "integrity": "sha512-iG7mY5LhweLKpgxQ+YdW7Y6YjBgRzGMrKlXzeUpm0VtJpdeag32Q/DMQ11HAT7kO9Jx8dreUL5SHGl6KAGJ9Lg==", + "node_modules/@oxlint/binding-linux-x64-gnu": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.78.0.tgz", + "integrity": "sha512-rRdISSYegj6VganMZ9tjRjijowfHJ09IZU01i0toBAqr6n5LEtwHq2IeS4FjW2RoskOHlb6efB26H5izYb3GEQ==", + "cpu": [ + "x64" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18.0.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/eventsource-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-4.0.0.tgz", - "integrity": "sha512-aIpvYxbqTx4KYWw73KpCt1Rh22tEAJ144F1qR76CT3Ex+LNMEPKf5HFrK5Yz9fMP1EVT0GrfA35VZvWQhMPuSQ==", + "node_modules/@oxlint/binding-linux-x64-musl": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.78.0.tgz", + "integrity": "sha512-GmsP4rW0xTL6u5CVdcDsaN5Fbc7hBc382Wmar1kttbnwSEviM+rSINKOMQ+UQ6iH+AGwC+8gaAiwu134Tgh6Lg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=22.12" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/fast-string-truncated-width": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz", - "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-string-width": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz", - "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==", + "node_modules/@oxlint/binding-openharmony-arm64": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.78.0.tgz", + "integrity": "sha512-sy9yeYuADc8a+n4TLBayzMCZiHPW78DcIFVpOXTmdKHWQeM9xe5uzkqIIZmi326D5hY9XVwacipEB1p7tQjPAg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "fast-string-truncated-width": "^3.0.2" + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/fast-wrap-ansi": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.2.tgz", - "integrity": "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==", + "node_modules/@oxlint/binding-win32-arm64-msvc": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.78.0.tgz", + "integrity": "sha512-rjc2hF1KfMi8fZj1X/m3AmnHbdsF3rL0v6KQg0Uc880Yb2khjz+3U14sfdZ7jWTpRnN1m1NQa/TT7uU9lJWPrA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "fast-string-width": "^3.0.2" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "node_modules/@oxlint/binding-win32-ia32-msvc": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.78.0.tgz", + "integrity": "sha512-zcuXFVrEFHIafRfkCQT8w/Xe41o07ozl/vwHq7p94vB29xVzsB0sZGYORU1jhcYKv3Lr0J3HbJ2T4fHH5rWmvA==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "node_modules/@oxlint/binding-win32-x64-msvc": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.78.0.tgz", + "integrity": "sha512-Sb5ocmLSuYeOuXd+CFOToGKp/gjXUEWDnvIGwhnh8aq8wY4TMmEnKnvbogSW7RdMZv77JSARduS7/gv+khYEjA==", + "cpu": [ + "x64" + ], "dev": true, - "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ - "darwin" + "win32" ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/human-id": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/human-id/-/human-id-4.2.0.tgz", - "integrity": "sha512-K3GbkIWqyvvlpfhBPlbEvD97TtqBpAYA4kt+cn2lD2x2HuohzZCibcA2nOlnJT6exqvJLggoB5nv2dNf192nEA==", + "node_modules/@pnpm/deps.graph-sequencer": { + "version": "1100.0.1", + "resolved": "https://registry.npmjs.org/@pnpm/deps.graph-sequencer/-/deps.graph-sequencer-1100.0.1.tgz", + "integrity": "sha512-pOr5+q1fLYKwFN3LAJuGZEnfXDcQ73zqgDHMtGy+K+uIoUqyY+6MeDCWFwfu+4EFuq76I5EPFofoNAI+Bmmq4A==", "dev": true, "license": "MIT", - "bin": { - "human-id": "dist/cli.js" + "engines": { + "node": ">=22.13" + }, + "funding": { + "url": "https://opencollective.com/pnpm" } }, - "node_modules/import-meta-resolve": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", - "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, + "node_modules/@poppinss/colors": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz", + "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "kleur": "^4.1.5" } }, - "node_modules/jju": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", - "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "node_modules/@poppinss/dumper": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz", + "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@sindresorhus/is": "^7.0.2", + "supports-color": "^10.0.0" + } }, - "node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "node_modules/@poppinss/exception": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz", + "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==", "dev": true, "license": "MIT" }, - "node_modules/launch-editor": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.14.1.tgz", - "integrity": "sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==", + "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", - "dependencies": { - "picocolors": "^1.1.1", - "shell-quote": "^1.8.4" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/oxfmt": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.52.0.tgz", - "integrity": "sha512-nJlYM35F64zTDMecCNhoHNkf+D/eHv7xcjj9XDSj+bFAVtN93m7v8DQMdHd6nDG6Akf/kEYYHmDUBs2Dz27Sug==", + "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", - "dependencies": { - "tinypool": "2.1.0" - }, - "bin": { - "oxfmt": "bin/oxfmt" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/sponsors/Boshen" - }, - "optionalDependencies": { - "@oxfmt/binding-android-arm-eabi": "0.52.0", - "@oxfmt/binding-android-arm64": "0.52.0", - "@oxfmt/binding-darwin-arm64": "0.52.0", - "@oxfmt/binding-darwin-x64": "0.52.0", - "@oxfmt/binding-freebsd-x64": "0.52.0", - "@oxfmt/binding-linux-arm-gnueabihf": "0.52.0", - "@oxfmt/binding-linux-arm-musleabihf": "0.52.0", - "@oxfmt/binding-linux-arm64-gnu": "0.52.0", - "@oxfmt/binding-linux-arm64-musl": "0.52.0", - "@oxfmt/binding-linux-ppc64-gnu": "0.52.0", - "@oxfmt/binding-linux-riscv64-gnu": "0.52.0", - "@oxfmt/binding-linux-riscv64-musl": "0.52.0", - "@oxfmt/binding-linux-s390x-gnu": "0.52.0", - "@oxfmt/binding-linux-x64-gnu": "0.52.0", - "@oxfmt/binding-linux-x64-musl": "0.52.0", - "@oxfmt/binding-openharmony-arm64": "0.52.0", - "@oxfmt/binding-win32-arm64-msvc": "0.52.0", - "@oxfmt/binding-win32-ia32-msvc": "0.52.0", - "@oxfmt/binding-win32-x64-msvc": "0.52.0" - }, - "peerDependencies": { - "svelte": "^5.0.0", - "vite-plus": "*" - }, - "peerDependenciesMeta": { - "svelte": { - "optional": true - }, - "vite-plus": { - "optional": true - } } }, - "node_modules/oxlint": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.78.0.tgz", - "integrity": "sha512-QgQePuxIqKOzo1KSjG2EnITEeWvWnKAm77eq8nrMtf6AGoA+zyGc4PFYtDNJSD25g/ibOwfQ851hZ4/SPkMVoA==", + "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", - "bin": { - "oxlint": "bin/oxlint" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/sponsors/Boshen" - }, - "optionalDependencies": { - "@oxlint/binding-android-arm-eabi": "1.78.0", - "@oxlint/binding-android-arm64": "1.78.0", - "@oxlint/binding-darwin-arm64": "1.78.0", - "@oxlint/binding-darwin-x64": "1.78.0", - "@oxlint/binding-freebsd-x64": "1.78.0", - "@oxlint/binding-linux-arm-gnueabihf": "1.78.0", - "@oxlint/binding-linux-arm-musleabihf": "1.78.0", - "@oxlint/binding-linux-arm64-gnu": "1.78.0", - "@oxlint/binding-linux-arm64-musl": "1.78.0", - "@oxlint/binding-linux-ppc64-gnu": "1.78.0", - "@oxlint/binding-linux-riscv64-gnu": "1.78.0", - "@oxlint/binding-linux-riscv64-musl": "1.78.0", - "@oxlint/binding-linux-s390x-gnu": "1.78.0", - "@oxlint/binding-linux-x64-gnu": "1.78.0", - "@oxlint/binding-linux-x64-musl": "1.78.0", - "@oxlint/binding-openharmony-arm64": "1.78.0", - "@oxlint/binding-win32-arm64-msvc": "1.78.0", - "@oxlint/binding-win32-ia32-msvc": "1.78.0", - "@oxlint/binding-win32-x64-msvc": "1.78.0" - }, - "peerDependencies": { - "oxlint-tsgolint": ">=7.0.2001", - "vite-plus": "*" - }, - "peerDependenciesMeta": { - "oxlint-tsgolint": { - "optional": true - }, - "vite-plus": { - "optional": true - } } }, - "node_modules/package-manager-detector": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.8.0.tgz", - "integrity": "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==", + "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" + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "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": "ISC" + "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/@sindresorhus/is": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@speed-highlight/core": { + "version": "1.2.24", + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.24.tgz", + "integrity": "sha512-qeW2e1l78afw8VhRPfPQ1Gjj+KU5XFQ/OFV5ti6eTa9bruO7mJyZtA4vw0ofqmA3tKCkROE9xLk3VZoeRc98nw==", + "dev": true, + "license": "CC0-1.0" + }, + "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/@tsconfig/strictest": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/strictest/-/strictest-2.0.8.tgz", + "integrity": "sha512-XnQ7vNz5HRN0r88GYf1J9JJjqtZPiHt2woGJOo2dYqyHGGcd6OLGqSlBB6p1j9mpzja6Oe5BoPqWmeDx6X9rLw==", + "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/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", + "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/whatwg-mimetype": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz", + "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript/typescript-aix-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", + "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-darwin-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", + "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-darwin-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", + "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-freebsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", + "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-freebsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", + "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-arm": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", + "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", + "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-loong64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", + "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-mips64el": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", + "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", + "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-riscv64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", + "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-s390x": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", + "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", + "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-netbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", + "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-netbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", + "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-openbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", + "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-openbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", + "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-sunos-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", + "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-win32-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", + "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-win32-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", + "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@vitest/browser": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.1.10.tgz", + "integrity": "sha512-UDwuWGwXj646CBx/bQHOaJSX7np0I8JL/UKQYa1e4QrVHH8VdWtx8eaOuf8sy0ShwDgR6NjJAsp5eF6vjF6qng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@blazediff/core": "1.9.1", + "@vitest/mocker": "4.1.10", + "@vitest/utils": "4.1.10", + "magic-string": "^0.30.21", + "pngjs": "^7.0.0", + "sirv": "^3.0.2", + "tinyrainbow": "^3.1.0", + "ws": "^8.19.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "4.1.10" + } + }, + "node_modules/@vitest/browser-playwright": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.1.10.tgz", + "integrity": "sha512-nMoXGEiRpT7m3W7NsbvrM2aKNwiNHZf+zEpUCvMteGjZFvfT96Q9fh7QyB98dvDWXiKvrLxA7bJ1mCOOv+JQPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/browser": "4.1.10", + "@vitest/mocker": "4.1.10", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "playwright": "*", + "vitest": "4.1.10" + }, + "peerDependenciesMeta": { + "playwright": { + "optional": false + } + } + }, + "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/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/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true, + "license": "MIT" + }, + "node_modules/buffer-image-size": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/buffer-image-size/-/buffer-image-size-0.6.4.tgz", + "integrity": "sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/cac": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cac/-/cac-7.0.0.tgz", + "integrity": "sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, + "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/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true, + "license": "MIT" + }, + "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/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/dataloader": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.3.tgz", + "integrity": "sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA==", + "dev": true, + "license": "MIT" + }, + "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/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "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/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/eventsource-encoder": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/eventsource-encoder/-/eventsource-encoder-1.0.2.tgz", + "integrity": "sha512-iG7mY5LhweLKpgxQ+YdW7Y6YjBgRzGMrKlXzeUpm0VtJpdeag32Q/DMQ11HAT7kO9Jx8dreUL5SHGl6KAGJ9Lg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-4.0.0.tgz", + "integrity": "sha512-aIpvYxbqTx4KYWw73KpCt1Rh22tEAJ144F1qR76CT3Ex+LNMEPKf5HFrK5Yz9fMP1EVT0GrfA35VZvWQhMPuSQ==", + "license": "MIT", + "engines": { + "node": ">=22.12" + } + }, + "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-string-truncated-width": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz", + "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-string-width": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz", + "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-string-truncated-width": "^3.0.2" + } + }, + "node_modules/fast-wrap-ansi": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.2.tgz", + "integrity": "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-string-width": "^3.0.2" + } + }, + "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/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/happy-dom": { + "version": "20.11.2", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-20.11.2.tgz", + "integrity": "sha512-7MB+bJLkxu3SowAfBJbjW+c55kNz5tkR45gu2qzrxznezhLeN5YIlJbwUgSzlGc+qWoZ8Ykg71H5ezz69xixrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": ">=20.0.0", + "@types/whatwg-mimetype": "^3.0.2", + "@types/ws": "^8.18.1", + "buffer-image-size": "^0.6.4", + "entities": "^7.0.1", + "whatwg-mimetype": "^3.0.0", + "ws": "^8.21.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/human-id": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/human-id/-/human-id-4.2.0.tgz", + "integrity": "sha512-K3GbkIWqyvvlpfhBPlbEvD97TtqBpAYA4kt+cn2lD2x2HuohzZCibcA2nOlnJT6exqvJLggoB5nv2dNf192nEA==", + "dev": true, + "license": "MIT", + "bin": { + "human-id": "dist/cli.js" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/launch-editor": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.14.1.tgz", + "integrity": "sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.1.1", + "shell-quote": "^1.8.4" + } + }, + "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/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/miniflare": { + "version": "5.20260811.1-alpha", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-5.20260811.1-alpha.tgz", + "integrity": "sha512-DtOG0BeanIxs2sH0smFvExZD89cBQwGckbHiFkRJrrNAUu3NGClZkUxqu+zy7HYfKBAgq935EMY49vIPm3JVdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "0.8.1", + "sharp": "0.35.2", + "undici": "7.29.0", + "workerd": "1.20260811.1", + "ws": "8.21.0", + "youch": "4.1.0-beta.10" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/miniflare/node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "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/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/oxfmt": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.52.0.tgz", + "integrity": "sha512-nJlYM35F64zTDMecCNhoHNkf+D/eHv7xcjj9XDSj+bFAVtN93m7v8DQMdHd6nDG6Akf/kEYYHmDUBs2Dz27Sug==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinypool": "2.1.0" + }, + "bin": { + "oxfmt": "bin/oxfmt" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxfmt/binding-android-arm-eabi": "0.52.0", + "@oxfmt/binding-android-arm64": "0.52.0", + "@oxfmt/binding-darwin-arm64": "0.52.0", + "@oxfmt/binding-darwin-x64": "0.52.0", + "@oxfmt/binding-freebsd-x64": "0.52.0", + "@oxfmt/binding-linux-arm-gnueabihf": "0.52.0", + "@oxfmt/binding-linux-arm-musleabihf": "0.52.0", + "@oxfmt/binding-linux-arm64-gnu": "0.52.0", + "@oxfmt/binding-linux-arm64-musl": "0.52.0", + "@oxfmt/binding-linux-ppc64-gnu": "0.52.0", + "@oxfmt/binding-linux-riscv64-gnu": "0.52.0", + "@oxfmt/binding-linux-riscv64-musl": "0.52.0", + "@oxfmt/binding-linux-s390x-gnu": "0.52.0", + "@oxfmt/binding-linux-x64-gnu": "0.52.0", + "@oxfmt/binding-linux-x64-musl": "0.52.0", + "@oxfmt/binding-openharmony-arm64": "0.52.0", + "@oxfmt/binding-win32-arm64-msvc": "0.52.0", + "@oxfmt/binding-win32-ia32-msvc": "0.52.0", + "@oxfmt/binding-win32-x64-msvc": "0.52.0" + }, + "peerDependencies": { + "svelte": "^5.0.0", + "vite-plus": "*" + }, + "peerDependenciesMeta": { + "svelte": { + "optional": true + }, + "vite-plus": { + "optional": true + } + } + }, + "node_modules/oxlint": { + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.78.0.tgz", + "integrity": "sha512-QgQePuxIqKOzo1KSjG2EnITEeWvWnKAm77eq8nrMtf6AGoA+zyGc4PFYtDNJSD25g/ibOwfQ851hZ4/SPkMVoA==", + "dev": true, + "license": "MIT", + "bin": { + "oxlint": "bin/oxlint" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxlint/binding-android-arm-eabi": "1.78.0", + "@oxlint/binding-android-arm64": "1.78.0", + "@oxlint/binding-darwin-arm64": "1.78.0", + "@oxlint/binding-darwin-x64": "1.78.0", + "@oxlint/binding-freebsd-x64": "1.78.0", + "@oxlint/binding-linux-arm-gnueabihf": "1.78.0", + "@oxlint/binding-linux-arm-musleabihf": "1.78.0", + "@oxlint/binding-linux-arm64-gnu": "1.78.0", + "@oxlint/binding-linux-arm64-musl": "1.78.0", + "@oxlint/binding-linux-ppc64-gnu": "1.78.0", + "@oxlint/binding-linux-riscv64-gnu": "1.78.0", + "@oxlint/binding-linux-riscv64-musl": "1.78.0", + "@oxlint/binding-linux-s390x-gnu": "1.78.0", + "@oxlint/binding-linux-x64-gnu": "1.78.0", + "@oxlint/binding-linux-x64-musl": "1.78.0", + "@oxlint/binding-openharmony-arm64": "1.78.0", + "@oxlint/binding-win32-arm64-msvc": "1.78.0", + "@oxlint/binding-win32-ia32-msvc": "1.78.0", + "@oxlint/binding-win32-x64-msvc": "1.78.0" + }, + "peerDependencies": { + "oxlint-tsgolint": ">=7.0.2001", + "vite-plus": "*" + }, + "peerDependenciesMeta": { + "oxlint-tsgolint": { + "optional": true + }, + "vite-plus": { + "optional": true + } + } + }, + "node_modules/package-manager-detector": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.8.0.tgz", + "integrity": "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, + "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/playwright": { + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.1.tgz", + "integrity": "sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.62.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz", + "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/pngjs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", + "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.19.0" + } + }, + "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/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/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/sharp": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.2.tgz", + "integrity": "sha512-FVtFjtBCMiJS6yb5CX7Sop45WFMpeGw6oRKuJnXYgf/f1ms/D7LE/ZUSNxnW7rZ/dbslQWYkoqFHGPaDBtaK4w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.4" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.2", + "@img/sharp-darwin-x64": "0.35.2", + "@img/sharp-freebsd-wasm32": "0.35.2", + "@img/sharp-libvips-darwin-arm64": "1.3.1", + "@img/sharp-libvips-darwin-x64": "1.3.1", + "@img/sharp-libvips-linux-arm": "1.3.1", + "@img/sharp-libvips-linux-arm64": "1.3.1", + "@img/sharp-libvips-linux-ppc64": "1.3.1", + "@img/sharp-libvips-linux-riscv64": "1.3.1", + "@img/sharp-libvips-linux-s390x": "1.3.1", + "@img/sharp-libvips-linux-x64": "1.3.1", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.1", + "@img/sharp-libvips-linuxmusl-x64": "1.3.1", + "@img/sharp-linux-arm": "0.35.2", + "@img/sharp-linux-arm64": "0.35.2", + "@img/sharp-linux-ppc64": "0.35.2", + "@img/sharp-linux-riscv64": "0.35.2", + "@img/sharp-linux-s390x": "0.35.2", + "@img/sharp-linux-x64": "0.35.2", + "@img/sharp-linuxmusl-arm64": "0.35.2", + "@img/sharp-linuxmusl-x64": "0.35.2", + "@img/sharp-webcontainers-wasm32": "0.35.2", + "@img/sharp-win32-arm64": "0.35.2", + "@img/sharp-win32-ia32": "0.35.2", + "@img/sharp-win32-x64": "0.35.2" + } + }, + "node_modules/shell-quote": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.10.0.tgz", + "integrity": "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/sirv": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "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/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/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "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": "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/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/tinypool": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-2.1.0.tgz", + "integrity": "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.0.0 || >=22.0.0" + } + }, + "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/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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/typescript": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", + "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc" + }, + "engines": { + "node": ">=16.20.0" + }, + "optionalDependencies": { + "@typescript/typescript-aix-ppc64": "7.0.2", + "@typescript/typescript-darwin-arm64": "7.0.2", + "@typescript/typescript-darwin-x64": "7.0.2", + "@typescript/typescript-freebsd-arm64": "7.0.2", + "@typescript/typescript-freebsd-x64": "7.0.2", + "@typescript/typescript-linux-arm": "7.0.2", + "@typescript/typescript-linux-arm64": "7.0.2", + "@typescript/typescript-linux-loong64": "7.0.2", + "@typescript/typescript-linux-mips64el": "7.0.2", + "@typescript/typescript-linux-ppc64": "7.0.2", + "@typescript/typescript-linux-riscv64": "7.0.2", + "@typescript/typescript-linux-s390x": "7.0.2", + "@typescript/typescript-linux-x64": "7.0.2", + "@typescript/typescript-netbsd-arm64": "7.0.2", + "@typescript/typescript-netbsd-x64": "7.0.2", + "@typescript/typescript-openbsd-arm64": "7.0.2", + "@typescript/typescript-openbsd-x64": "7.0.2", + "@typescript/typescript-sunos-x64": "7.0.2", + "@typescript/typescript-win32-arm64": "7.0.2", + "@typescript/typescript-win32-x64": "7.0.2" + } + }, + "node_modules/undici": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", + "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unenv": { + "version": "2.0.0-rc.24", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", + "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3" + } + }, + "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/vite/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/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/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "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/workerd": { + "version": "1.20260811.1", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260811.1.tgz", + "integrity": "sha512-kh+FFm55JQ4ssxhHZV9VPdMQq3D1nHxNJgwxMtWGD4dGppJvLySdguTRDKgeNTvgq6heSz+6TTXyPSDGj8Yllw==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20260811.1", + "@cloudflare/workerd-darwin-arm64": "1.20260811.1", + "@cloudflare/workerd-linux-64": "1.20260811.1", + "@cloudflare/workerd-linux-arm64": "1.20260811.1", + "@cloudflare/workerd-windows-64": "1.20260811.1" + } + }, + "node_modules/wrangler": { + "version": "4.123.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.123.0.tgz", + "integrity": "sha512-VXo2I1oa0x9aGAKIFPRSQPqTh0RBY5Ktl44YOhNmsJQFUdJKDA2vVTU6Xj+FC2koll6orJqWZN8jbXVIk9O67Q==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@cloudflare/kv-asset-handler": "0.5.0", + "@cloudflare/unenv-preset": "2.16.1", + "blake3-wasm": "2.1.5", + "esbuild": "0.28.1", + "miniflare": "5.20260811.1-alpha", + "path-to-regexp": "6.3.0", + "unenv": "2.0.0-rc.24", + "workerd": "1.20260811.1" + }, + "bin": { + "cf-wrangler": "bin/cf-wrangler.js", + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" + }, + "engines": { + "node": ">=22.0.0" + }, + "optionalDependencies": { + "fsevents": "2.3.3" + }, + "peerDependencies": { + "@cloudflare/workers-types": "^5.20260811.1" + }, + "peerDependenciesMeta": { + "@cloudflare/workers-types": { + "optional": true + } + } + }, + "node_modules/wrangler/node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "node_modules/wrangler/node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=18" } }, - "node_modules/playwright": { - "version": "1.62.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.1.tgz", - "integrity": "sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==", + "node_modules/wrangler/node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.62.1" - }, - "bin": { - "playwright": "cli.js" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=20" - }, - "optionalDependencies": { - "fsevents": "2.3.2" + "node": ">=18" } }, - "node_modules/playwright-core": { - "version": "1.62.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz", - "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==", + "node_modules/wrangler/node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=20" + "node": ">=18" } }, - "node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/shell-quote": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.10.0.tgz", - "integrity": "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==", + "node_modules/wrangler/node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/sinon": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-22.1.0.tgz", - "integrity": "sha512-n1ajF2rBWMTtEwbKcw4UdFg4nCnDdq/U6RDoxtOd7oapOlRoJ5ynwFx60owROyhDpA9QhMZi0pCO/xtmwFjG7w==", + "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^15.4.0", - "@sinonjs/samsam": "^10.0.2", - "diff": "^9.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "node_modules/wrangler/node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/tinyexec": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", - "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "node_modules/wrangler/node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { "node": ">=18" } }, - "node_modules/tinyglobby": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", - "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "node_modules/wrangler/node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "node": ">=18" } }, - "node_modules/tinypool": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-2.1.0.tgz", - "integrity": "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==", + "node_modules/wrangler/node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^20.0.0 || >=22.0.0" + "node": ">=18" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "node_modules/wrangler/node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/typescript": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", - "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", + "node_modules/wrangler/node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", "dev": true, - "license": "Apache-2.0", + "hasInstallScript": true, + "license": "MIT", "bin": { - "tsc": "bin/tsc" + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=16.20.0" + "node": ">=18" }, "optionalDependencies": { - "@typescript/typescript-aix-ppc64": "7.0.2", - "@typescript/typescript-darwin-arm64": "7.0.2", - "@typescript/typescript-darwin-x64": "7.0.2", - "@typescript/typescript-freebsd-arm64": "7.0.2", - "@typescript/typescript-freebsd-x64": "7.0.2", - "@typescript/typescript-linux-arm": "7.0.2", - "@typescript/typescript-linux-arm64": "7.0.2", - "@typescript/typescript-linux-loong64": "7.0.2", - "@typescript/typescript-linux-mips64el": "7.0.2", - "@typescript/typescript-linux-ppc64": "7.0.2", - "@typescript/typescript-linux-riscv64": "7.0.2", - "@typescript/typescript-linux-s390x": "7.0.2", - "@typescript/typescript-linux-x64": "7.0.2", - "@typescript/typescript-netbsd-arm64": "7.0.2", - "@typescript/typescript-netbsd-x64": "7.0.2", - "@typescript/typescript-openbsd-arm64": "7.0.2", - "@typescript/typescript-openbsd-x64": "7.0.2", - "@typescript/typescript-sunos-x64": "7.0.2", - "@typescript/typescript-win32-arm64": "7.0.2", - "@typescript/typescript-win32-x64": "7.0.2" - } - }, - "node_modules/undici": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", - "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/wrangler/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": ">=20.18.1" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "node_modules/ws": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } }, "node_modules/yaml": { "version": "2.9.0", @@ -2454,6 +5208,41 @@ "funding": { "url": "https://github.com/sponsors/eemeli" } + }, + "node_modules/youch": { + "version": "4.1.0-beta.10", + "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", + "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@poppinss/dumper": "^0.6.4", + "@speed-highlight/core": "^1.2.7", + "cookie": "^1.0.2", + "youch-core": "^0.3.3" + } + }, + "node_modules/youch-core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", + "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/exception": "^1.2.2", + "error-stack-parser-es": "^1.0.5" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index 00677837..47ff0a82 100644 --- a/package.json +++ b/package.json @@ -52,18 +52,20 @@ "changeset:status": "changeset status --since=origin/main", "clean": "node scripts/clean.ts", "format": "oxfmt --write .", - "lint": "oxlint . && tsc --noEmit", - "posttest": "npm run lint", + "lint": "oxlint . && tsc --noEmit && tsc --noEmit -p tsconfig.test.json", "prebuild": "npm run clean", "prepare": "npm run build", "release": "changeset publish", - "test": "npm run test:types && npm run test:node && npm run test:browser", - "test:browser": "node test/browser/client.browser.test.ts", - "test:bun": "bun run test/bun/client.bun.test.ts", - "test:deno": "deno run --allow-net --allow-read --allow-env --unstable-sloppy-imports test/deno/client.deno.test.ts", - "test:node": "node test/node/client.node.test.ts", + "test": "vitest run", + "test:browser": "vitest run --config ./vitest.browser.config.ts", + "test:bun": "bun run vitest run", + "test:deno": "deno run -A --node-modules-dir npm:vitest run", "test:types": "npm run build && tsc -p tsconfig.types.json", - "version:packages": "changeset version && npm install --package-lock-only --no-audit --no-fund" + "version:packages": "changeset version && npm install --package-lock-only --no-audit --no-fund", + "test:all": "npm run test:types && npm run test && npm run test:browser && npm run test:bun && npm run test:deno && npm run test:happy-dom && npm run test:workerd", + "test:happy-dom": "vitest run --config ./vitest.happy-dom.config.ts", + "test:workerd": "vitest run --config ./vitest.workerd.config.ts", + "posttest": "npm run lint" }, "dependencies": { "eventsource-parser": "^4.0.0" @@ -71,17 +73,18 @@ "devDependencies": { "@changesets/changelog-github": "^1.0.0", "@changesets/cli": "^3.0.0", + "@cloudflare/vitest-pool-workers": "^0.21.3", "@tsconfig/strictest": "^2.0.8", "@types/node": "^22.19.19", - "@types/sinon": "^21.0.1", - "esbuild": "^0.28.0", + "@vitest/browser": "^4.1.10", + "@vitest/browser-playwright": "^4.1.10", "eventsource-encoder": "^1.0.2", + "happy-dom": "^20.11.2", "oxfmt": "^0.52.0", "oxlint": "^1.67.0", "playwright": "^1.60.0", - "sinon": "^22.0.0", "typescript": "^7.0.0", - "undici": "^7.0.0" + "vitest": "^4.1.10" }, "browserslist": [ "node >= 22.12.0", diff --git a/test/browser/browser-test.html b/test/browser/browser-test.html deleted file mode 100644 index bb38de23..00000000 --- a/test/browser/browser-test.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - eventsource-client tests - - - - -
-
Preparing test environment…
-
- - - - diff --git a/test/browser/browser-test.ts b/test/browser/browser-test.ts deleted file mode 100644 index 414e0589..00000000 --- a/test/browser/browser-test.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Compiled by ESBuild for the browser - */ -import {registerTests} from '../tests.ts' -import {createRunner, type TestEvent} from '../waffletest/index.ts' - -if (!windowHasBeenExtended(window)) { - throw new Error('window.reportTest has not been defined by playwright') -} - -const runner = registerTests({ - environment: 'browser', - runner: createRunner({onEvent: window.reportTest}), - port: 3883, -}) - -const el = document.getElementById('waffletest') -if (el) { - el.innerText = `Running ${runner.getTestCount()} tests…` -} - -runner.runTests().then((result) => { - if (!el) { - console.error('Could not find element with id "waffletest"') - return - } - - el.innerText = `Tests completed ${result.success ? 'successfully' : 'with errors'}` - el.className = result.success ? 'success' : 'fail' -}) - -// Added by our playwright-based test runner -interface ExtendedWindow extends Window { - reportTest: (event: TestEvent) => void -} - -function windowHasBeenExtended(win: Window): win is ExtendedWindow { - return 'reportTest' in win && typeof win.reportTest === 'function' -} diff --git a/test/browser/client.browser.test.ts b/test/browser/client.browser.test.ts deleted file mode 100644 index f98d6e18..00000000 --- a/test/browser/client.browser.test.ts +++ /dev/null @@ -1,189 +0,0 @@ -/* eslint-disable no-console */ -/** - * This module: - * - Starts a development server - * - Spawns browsers and points them at the server - * - Runs the tests in the browser (using waffletest) - * - Reports results from browser to node using the registered function `reportTest` - * - Prints the test results to the console - * - * Is this weird? Yes. - * Is there a better way? Maybe. But I haven't found one. - * - * Supported flags: - * - * --browser=firefox|chromium|webkit - * --no-close - * --no-headless - * --serial - */ -import {type BrowserType, chromium, firefox, webkit} from 'playwright' - -import {getServer} from '../server.ts' -import {type TestEvent} from '../waffletest/index.ts' -import {nodeReporter} from '../waffletest/reporters/nodeReporter.ts' - -type BrowserName = 'firefox' | 'chromium' | 'webkit' - -const browsers: Record = { - firefox, - chromium, - webkit, -} - -const {onPass: reportPass, onFail: reportFail, onEnd: reportEnd} = nodeReporter - -const BROWSER_TEST_PORT = 3883 -const RUN_IN_SERIAL = process.argv.includes('--serial') -const NO_HEADLESS = process.argv.includes('--no-headless') -const NO_CLOSE = process.argv.includes('--no-close') - -const browserFlag = getBrowserFlag() -if (browserFlag && !isDefinedBrowserType(browserFlag)) { - throw new Error(`Invalid browser flag. Must be one of: ${Object.keys(browsers).join(', ')}`) -} - -const browserFlagType = isDefinedBrowserType(browserFlag) ? browsers[browserFlag] : undefined - -// Run the tests in browsers -;(async function run() { - const server = await getServer(BROWSER_TEST_PORT) - const jobs = - browserFlag && browserFlagType - ? [{name: browserFlag, browserType: browserFlagType}] - : Object.entries(browsers).map(([name, browserType]) => ({name, browserType})) - - // Run all browsers in parallel, unless --serial is defined - let totalFailures = 0 - let totalTests = 0 - - if (RUN_IN_SERIAL) { - for (const job of jobs) { - const {failures, tests} = reportBrowserResult(job.name, await runBrowserTest(job.browserType)) - totalFailures += failures - totalTests += tests - } - } else { - await Promise.all( - jobs.map(async (job) => { - const {failures, tests} = reportBrowserResult( - job.name, - await runBrowserTest(job.browserType), - ) - totalFailures += failures - totalTests += tests - }), - ) - } - - function reportBrowserResult( - browserName: string, - events: TestEvent[], - ): {failures: number; passes: number; tests: number} { - console.log(`Browser: ${browserName}`) - - let passes = 0 - let failures = 0 - for (const event of events) { - switch (event.event) { - case 'start': - // Ignored - break - case 'pass': - passes++ - reportPass(event) - break - case 'fail': - failures++ - reportFail(event) - break - case 'end': - reportEnd(event) - break - default: - // eslint-disable-next-line @typescript-eslint/no-explicit-any - throw new Error(`Unexpected event: ${(event as any).event}`) - } - } - - return {failures, passes, tests: passes + failures} - } - - console.log(`Ran ${totalTests} tests against ${jobs.length} browsers`) - - await server.close() - - if (totalFailures > 0) { - // eslint-disable-next-line no-process-exit - process.exit(1) - } -})() - -async function runBrowserTest(browserType: BrowserType): Promise { - let resolve: (value: TestEvent[] | PromiseLike) => void - const promise = new Promise((_resolve) => { - resolve = _resolve - }) - - const domain = getBaseUrl(BROWSER_TEST_PORT) - const browser = await browserType.launch({headless: !NO_HEADLESS}) - const context = await browser.newContext() - await context.clearCookies() - - const page = await context.newPage() - const events: TestEvent[] = [] - - await page.exposeFunction('reportTest', async (event: TestEvent) => { - events.push(event) - - if (event.event !== 'end') { - return - } - - // Teardown - if (!NO_CLOSE) { - await context.close() - await browser.close() - } - resolve(events) - }) - - await page.goto(`${domain}/browser-test`) - - return promise -} - -function isDefinedBrowserType(browserName: string | undefined): browserName is BrowserName { - return typeof browserName === 'string' && browserName in browsers -} - -function getBrowserFlag(): BrowserName | undefined { - const resolved = (function getFlag() { - // Look for --browser - const flagIndex = process.argv.indexOf('--browser') - let flag = flagIndex === -1 ? undefined : process.argv[flagIndex + 1] - if (flag) { - return flag - } - - // Look for --browser= - flag = process.argv.find((arg) => arg.startsWith('--browser=')) - return flag ? flag.split('=')[1] : undefined - })() - - if (!resolved) { - return undefined - } - - if (!isDefinedBrowserType(resolved)) { - throw new Error(`Invalid browser flag. Must be one of: ${Object.keys(browsers).join(', ')}`) - } - - return resolved -} - -function getBaseUrl(port: number): string { - return typeof document === 'undefined' - ? `http://127.0.0.1:${port}` - : `${location.protocol}//${location.hostname}:${port}` -} diff --git a/test/bun/client.bun.test.ts b/test/bun/client.bun.test.ts deleted file mode 100644 index 1864ccb4..00000000 --- a/test/bun/client.bun.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import {getServer} from '../server.ts' -import {registerTests} from '../tests.ts' -import {createRunner} from '../waffletest/index.ts' -import {nodeReporter} from '../waffletest/reporters/nodeReporter.ts' - -const BUN_TEST_PORT = 3946 - -// Run the tests in bun -;(async function run() { - const server = await getServer(BUN_TEST_PORT) - - const runner = registerTests({ - environment: 'bun', - runner: createRunner(nodeReporter), - fetch: globalThis.fetch, - port: BUN_TEST_PORT, - }) - - const result = await runner.runTests() - - // Teardown - await Promise.race([server.close(), new Promise((resolve) => setTimeout(resolve, 5000))]) - - // eslint-disable-next-line no-process-exit - process.exit(result.failures) -})() diff --git a/test/client.test.ts b/test/client.test.ts new file mode 100644 index 00000000..61fbaf19 --- /dev/null +++ b/test/client.test.ts @@ -0,0 +1,887 @@ +import {expect, test, vi} from 'vitest' + +import { + type ErrorEvent, + EventSource as OurEventSource, + type EventSourceFetchInit, + type FetchLike, +} from '../src/index.ts' +import {deferClose, getCallCounter} from './helpers/callCounter.ts' +import { + crossOrigin, + crossOriginUrl, + esInit, + hasBrowserSemantics, + request, + serverOrigin, + serverUrl, +} from './helpers/env.ts' +import {unicodeLines} from './helpers/fixtures.ts' + +/** Only meaningful where CORS, cookies and `withCredentials` are actually enforced. */ +const browserTest = test.runIf(hasBrowserSemantics) + +test('can connect, receive message, manually disconnect', async () => { + const onMessage = getCallCounter({name: 'onMessage'}) + const es = new OurEventSource(new URL(`${serverUrl}/`)) + es.addEventListener('welcome', onMessage.listener, false) + + await onMessage.waitForCallCount(1) + + expect(onMessage.callCount).toBe(1) + expect(onMessage.lastArg).toMatchObject({ + data: 'Hello, world!', + origin: serverOrigin, + }) + + await deferClose(es) +}) + +test('`target` on open, message and error events is the EventSource instance', async () => { + const onOpen = getCallCounter({name: 'onOpen'}) + const onMessage = getCallCounter({name: 'onMessage'}) + const onError = getCallCounter({name: 'onError'}) + const es = new OurEventSource(`${serverUrl}/end-after-one`) + + es.addEventListener('open', onOpen.listener) + es.addEventListener('progress', onMessage.listener) + es.addEventListener('error', onError.listener) + + await onOpen.waitForCallCount(1) + await onMessage.waitForCallCount(1) + await onError.waitForCallCount(1) + + expect(onOpen.lastArg.target).toBe(es) + expect(onMessage.lastArg.target).toBe(es) + expect(onError.lastArg.target).toBe(es) + + await deferClose(es) +}) + +test('can connect using URL string only', async () => { + const es = new OurEventSource(`${serverUrl}/`) + const onMessage = getCallCounter({name: 'onMessage'}) + es.addEventListener('welcome', onMessage.listener, false) + + await onMessage.waitForCallCount(1) + await deferClose(es) +}) + +test('passes `no-store` to `fetch`, avoiding cache', async () => { + let passedInit: EventSourceFetchInit | undefined + + const onMessage = getCallCounter({name: 'onMessage'}) + const es = new OurEventSource(new URL(`${serverUrl}/debug`), { + fetch: (url, init) => { + passedInit = init + return request(url, init) + }, + }) + + es.addEventListener('debug', onMessage.listener, false) + await onMessage.waitForCallCount(1) + + expect(passedInit).toMatchObject({cache: 'no-store'}) + await deferClose(es) +}) + +test('can handle unicode data correctly', async () => { + const onMessage = getCallCounter({name: 'onMessage'}) + const es = new OurEventSource(`${serverUrl}/unicode`, esInit) + + const messages: Array<{data: string}> = [] + es.addEventListener('unicode', (evt) => { + messages.push(evt) + onMessage.listener(evt) + }) + + await onMessage.waitForCallCount(2) + expect(messages[0]?.data).toBe(unicodeLines[0]) + expect(messages[1]?.data).toBe(unicodeLines[1]) + + await deferClose(es) +}) + +test('can use `es.onopen` to listen for open events, nulling it unsubscribes', async () => { + const onError = getCallCounter({name: 'onError'}) + const onOpen = getCallCounter({name: 'onOpen'}) + const es = new OurEventSource(`${serverUrl}/counter`, esInit) + es.addEventListener('error', onError.listener) + es.onopen = onOpen.listener + + await onOpen.waitForCallCount(2) + es.onopen = null + + await onError.waitForCallCount(4) // 4 disconnects + + // If `es.onopen = null` did not work, this should be 4 + expect(onOpen.callCount).toBe(2) + await deferClose(es) +}) + +test('can use `es.onerror` to listen for error events, nulling it unsubscribes', async () => { + const onError = getCallCounter({name: 'onError'}) + const onOpen = getCallCounter({name: 'onOpen'}) + const es = new OurEventSource(`${serverUrl}/counter`, esInit) + es.addEventListener('open', onOpen.listener) + es.onerror = onError.listener + + await onOpen.waitForCallCount(3) + es.onerror = null + + await onOpen.waitForCallCount(4) // 4 connects + + // If `es.onerror = null` did not work, this should be 4 + expect(onError.callCount).toBe(2) + await deferClose(es) +}) + +test('can use `es.onmessage` to listen for explicit `message` events, nulling it unsubscribes', async () => { + const onMessage = getCallCounter({name: 'onMessage'}) + const onError = getCallCounter({name: 'onError'}) + const es = new OurEventSource(`${serverUrl}/counter?event=message`, esInit) + es.addEventListener('error', onError.listener) + es.onmessage = onMessage.listener + + await onError.waitForCallCount(2) + es.onmessage = null + + await onError.waitForCallCount(3) // 3 disconnects + + // If `es.onmessage = null` did not work, this should be 9, + // since each connect emits 3 message then closes + expect(onMessage.callCount).toBe(6) + await deferClose(es) +}) + +test('can use `es.onmessage` to listen for implicit `message` events, nulling it unsubscribes', async () => { + const onMessage = getCallCounter({name: 'onMessage'}) + const onError = getCallCounter({name: 'onError'}) + const es = new OurEventSource(`${serverUrl}/counter?event=`, esInit) + es.addEventListener('error', onError.listener) + es.onmessage = onMessage.listener + + await onError.waitForCallCount(2) + es.onmessage = null + + await onError.waitForCallCount(3) // 3 disconnects + + // If `es.onmessage = null` did not work, this should be 9, + // since each connect emits 3 message then closes + expect(onMessage.callCount).toBe(6) + await deferClose(es) +}) + +test('`es.onmessage` does not fire for non-`message` events', async () => { + const onMessage = getCallCounter({name: 'onMessage'}) + const onOpen = getCallCounter({name: 'onOpen'}) + const es = new OurEventSource(`${serverUrl}/counter`, esInit) + es.addEventListener('open', onOpen.listener) + es.onmessage = onMessage.listener + + await onOpen.waitForCallCount(3) + es.onmessage = null + + // `event` was never "message" (or blank), only ever `counter` + expect(onMessage.callCount).toBe(0) + await deferClose(es) +}) + +test('can redeclare `es.onopen` after initial assignment', async () => { + const onError = getCallCounter({name: 'onError'}) + const onOpen = getCallCounter({name: 'onOpen'}) + const onOpenNew = getCallCounter({name: 'onOpen (new)'}) + const es = new OurEventSource(`${serverUrl}/counter`, esInit) + es.addEventListener('error', onError.listener) + es.onopen = onOpen.listener + + await onOpen.waitForCallCount(2) + es.onopen = onOpenNew.listener + + await onError.waitForCallCount(4) // 4 disconnects + + // If `es.onopen = ` did not work, this should be 4 + expect(onOpen.callCount).toBe(2) + expect(onOpenNew.callCount).toBe(2) + await deferClose(es) +}) + +test('can redeclare `es.onerror` after initial assignment', async () => { + const onError = getCallCounter({name: 'onError'}) + const onErrorNew = getCallCounter({name: 'onError (new)'}) + const onOpen = getCallCounter({name: 'onOpen'}) + const es = new OurEventSource(`${serverUrl}/counter`, esInit) + es.addEventListener('open', onOpen.listener) + es.onerror = onError.listener + + await onOpen.waitForCallCount(3) + es.onerror = onErrorNew.listener + + await onOpen.waitForCallCount(4) // 4 connects + + // If `es.onerror = ` did not work, this should be 4 + expect(onError.callCount).toBe(2) + expect(onErrorNew.callCount).toBe(1) + await deferClose(es) +}) + +test('can redeclare `es.onmessage` after initial assignment', async () => { + const onMessage = getCallCounter({name: 'onMessage'}) + const onMessageNew = getCallCounter({name: 'onMessage (new)'}) + const onError = getCallCounter({name: 'onError'}) + const es = new OurEventSource(`${serverUrl}/counter?event=message`, esInit) + es.addEventListener('error', onError.listener) + es.onmessage = onMessage.listener + + await onError.waitForCallCount(2) + es.onmessage = onMessageNew.listener + + await onError.waitForCallCount(3) // 3 disconnects + + // If `es.onmessage = ` did not work, this should be 9, + // since each connect emits 3 message then closes + expect(onMessage.callCount).toBe(6) + expect(onMessageNew.callCount).toBe(3) + await deferClose(es) +}) + +test('on-handlers fire in registration order relative to `addEventListener`', async () => { + const order: string[] = [] + const onOpen = getCallCounter({name: 'onOpen'}) + const es = new OurEventSource(`${serverUrl}/`, esInit) + + // `addEventListener` is registered _before_ the `onopen` handler is assigned, so per spec + // the `addEventListener` callback must fire first (the event handler IDL attribute fires + // in the order it was set, relative to other listeners). + es.addEventListener('open', () => order.push('addEventListener')) + es.onopen = (event) => { + order.push('onopen') + onOpen.listener(event) + } + + await onOpen.waitForCallCount(1) + + expect(order[0], 'first handler to fire').toBe('addEventListener') + expect(order[1], 'second handler to fire').toBe('onopen') + + await deferClose(es) +}) + +test('message event contains correct properties', async () => { + const onMessage = getCallCounter({name: 'onMessage'}) + const es = new OurEventSource(`${serverUrl}/counter`, esInit) + + es.addEventListener('counter', onMessage.listener) + await onMessage.waitForCallCount(1) + + expect(onMessage.lastArg).toMatchObject({ + data: 'Counter is at 1', + type: 'counter', + lastEventId: '1', + origin: serverOrigin, + defaultPrevented: false, + cancelable: false, + timeStamp: expect.any(Number), + }) + await deferClose(es) +}) + +test('will reconnect with last received message id if server disconnects', async () => { + const onMessage = getCallCounter({name: 'onMessage'}) + const onError = getCallCounter({name: 'onError'}) + const url = `${serverUrl}/counter` + const es = new OurEventSource(url, esInit) + es.addEventListener('counter', onMessage.listener) + es.addEventListener('error', onError.listener) + + // While still receiving messages (we receive 3 at a time before it disconnects) + await onMessage.waitForCallCount(1) + expect(es.readyState, 'readyState').toBe(OurEventSource.OPEN) // Open (connected) + + // While waiting for reconnect (after 3 messages it will disconnect and reconnect) + await onError.waitForCallCount(1) + expect(es.readyState, 'readyState').toBe(OurEventSource.CONNECTING) // Connecting (reconnecting) + expect(onMessage.callCount).toBe(3) + + // Will reconnect infinitely, stop at 8 messages + await onMessage.waitForCallCount(8) + + expect(es.url).toBe(url) + expect(onMessage.lastArg).toMatchObject({ + data: 'Counter is at 8', + type: 'counter', + lastEventId: '8', + origin: serverOrigin, + }) + expect(onMessage.callCount).toBe(8) + + await deferClose(es) +}) + +test('will not reconnect after explicit `close()`', async () => { + const onMessage = getCallCounter({name: 'onMessage'}) + const onError = getCallCounter({name: 'onError'}) + const clientId = Math.random().toString(36).slice(2) + const url = `${serverUrl}/identified?client-id=${clientId}` + const es = new OurEventSource(url, esInit) + + es.addEventListener('message', onMessage.listener) + es.addEventListener('error', onError.listener) + + // Should receive a message containing the number of listeners on the given ID + await onMessage.waitForCallCount(1) + expect(onMessage.lastArg).toMatchObject({data: '1'}) + expect(es.readyState, 'readyState').toBe(OurEventSource.OPEN) // Open (connected) + + // Explicitly disconnect. Should normally reconnect within ~250ms (server sends retry: 250) + // but we'll close it before that happens + es.close() + expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) + expect(onMessage.callCount).toBe(1) + + // After 500 ms, there should still only be a single connect with this client ID + await new Promise((resolve) => setTimeout(resolve, 500)) + expect(await request(url).then((res) => res.json())).toMatchObject({clientIdConnects: 1}) + + // Wait another 500 ms, just to be sure there are no slow reconnects + await new Promise((resolve) => setTimeout(resolve, 500)) + expect(await request(url).then((res) => res.json())).toMatchObject({clientIdConnects: 1}) +}) + +test('will not reconnect after explicit `close()` in `onError`', async () => { + const onMessage = getCallCounter({name: 'onMessage'}) + const onError = getCallCounter({name: 'onError', onCall: () => es.close()}) + const clientId = Math.random().toString(36).slice(2) + const url = `${serverUrl}/identified?client-id=${clientId}&auto-close=true` + const es = new OurEventSource(url, esInit) + es.addEventListener('open', () => expect(es.readyState).toBe(OurEventSource.OPEN)) + es.addEventListener('message', onMessage.listener) + es.addEventListener('error', onError.listener) + + // Should receive a message containing the number of listeners on the given ID + await onMessage.waitForCallCount(1) + expect(onMessage.lastArg, 'onMessage `event` argument').toMatchObject({data: '1'}) + + await onError.waitForCallCount(1) + expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) // `onDisconnect` called first, closes ES. + + // After 50 ms, we should still be in closing state - no reconnecting + expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) + + // After 500 ms, there should be no clients connected to the given ID + await new Promise((resolve) => setTimeout(resolve, 500)) + expect(await request(url).then((res) => res.json())).toMatchObject({clientIdConnects: 1}) + expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) + + // Wait another 500 ms, just to be sure there are no slow reconnects + await new Promise((resolve) => setTimeout(resolve, 500)) + expect(await request(url).then((res) => res.json())).toMatchObject({clientIdConnects: 1}) + expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) +}) + +test('will have correct ready state throughout lifecycle', async () => { + const onMessage = getCallCounter({name: 'onMessage'}) + const onOpen = getCallCounter({name: 'onOpen'}) + const onError = getCallCounter({name: 'onError'}) + const url = `${serverUrl}/slow-connect` + const es = new OurEventSource(url, esInit) + + es.addEventListener('message', onMessage.listener) + es.addEventListener('open', onOpen.listener) + es.addEventListener('error', onError.listener) + + // Connecting + expect(es.readyState, 'readyState').toBe(OurEventSource.CONNECTING) + + // Connected + await onOpen.waitForCallCount(1) + expect(es.readyState, 'readyState').toBe(OurEventSource.OPEN) + + // Disconnected + await onError.waitForCallCount(1) + expect(es.readyState, 'readyState').toBe(OurEventSource.CONNECTING) + + // Closed + await es.close() + expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) +}) + +test('will close stream on HTTP 204', async () => { + const onMessage = getCallCounter({name: 'onMessage'}) + const onError = getCallCounter({name: 'onError'}) + const es = new OurEventSource(`${serverUrl}/end-after-one`, esInit) + + es.addEventListener('progress', onMessage.listener) + es.addEventListener('error', onError.listener) + + // First disconnect, then reconnect and given a 204 + await onError.waitForCallCount(2) + + // Only the first connect should have given a message + await onMessage.waitForCallCount(1) + + expect(onMessage.callCount).toBe(1) + expect(onMessage.lastArg).toMatchObject({ + data: '100%', + type: 'progress', + lastEventId: 'prct-100', + }) + expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) // CLOSED + + await deferClose(es) +}) + +/** + * Note: Browser behavior varies in what they do on non-string/URL `url`: + * - Chrome and Safari `toString()`s the value, which is obviously wrong according to spec: + * > If urlRecord is failure, then throw a "SyntaxError" DOMException. + * - Firefox throws a `DOMException` with message `An invalid or illegal string was specified` + * (correct according to spec). + * + * We choose to go with the spec (eg mirrors Firefox behavior) if `DOMException` exists, + * otherwise we throw a `SyntaxError`. + */ +test('throws if `url` is not a string/url', () => { + let thrown: unknown + try { + // @ts-expect-error Should be a string or URL + const es = new OurEventSource(123, esInit) + es.close() + } catch (err: unknown) { + thrown = err + } + + // Fails with a readable diff rather than a bare "expected to throw" if it did not throw + expect(thrown).toBeInstanceOf(DOMException) + expect(thrown).toMatchObject({message: 'An invalid or illegal string was specified'}) +}) + +test('can request cross-origin', async () => { + const onMessage = getCallCounter({name: 'onMessage'}) + const es = new OurEventSource(new URL(`${crossOriginUrl}/cors`), esInit) + es.addEventListener('origin', onMessage.listener) + + await onMessage.waitForCallCount(1) + expect(onMessage.callCount).toBe(1) + + expect(onMessage.lastArg).toMatchObject({type: 'origin'}) + + // Browsers send an `Origin` header on cross-origin requests; the server-side runtimes do not + expect(onMessage.lastArg).toMatchObject({ + data: hasBrowserSemantics ? serverOrigin : '', + }) + + await deferClose(es) +}) + +// Same-origin redirect tests +;[301, 302, 307, 308].forEach((status) => { + test(`redirects: handles ${status} to same origin`, async () => { + const id = Math.random().toString(36).slice(2) + const onMessage = getCallCounter({name: 'onMessage'}) + const onOpen = getCallCounter({name: 'onOpen'}) + const url = `${serverUrl}/redirect?status=${status}&id=${id}` + const es = new OurEventSource(url, { + ...esInit, + withCredentials: true, + fetch(dstUrl, init) { + return request(dstUrl, { + ...init, + headers: {...init?.headers, authorization: 'Bearer foo'}, + }) + }, + }) + es.addEventListener('message', onMessage.listener) + es.addEventListener('open', onOpen.listener) + + await onMessage.waitForCallCount(1) + + // URL should be the original connected URL, even after redirect + expect(es.url).toBe(url) + + const firstMessage = onMessage.lastArg + expect(firstMessage).toMatchObject({origin: serverOrigin}) + expect(JSON.parse(firstMessage.data)).toMatchObject({ + origin: serverOrigin, + from: url, + redirects: 1, + auth: 'Bearer foo', + }) + + // Reconnected and received another message + await onOpen.waitForCallCount(2) + await onMessage.waitForCallCount(2) + + const lastMessage = onMessage.lastArg + expect(lastMessage).toMatchObject({origin: serverOrigin}) + expect(JSON.parse(lastMessage.data)).toMatchObject({ + origin: serverOrigin, + from: url, + redirects: 2, + auth: 'Bearer foo', + }) + + // Deno/Bun seems to set timeStamp to `0` πŸ€·β€β™‚οΈ + if (firstMessage.timeStamp > 0) { + expect(firstMessage.timeStamp).not.toBe(lastMessage.timeStamp) + } + + await deferClose(es) + }) +}) + +// Cross-origin redirect tests +;[301, 302, 307, 308].forEach((status) => { + test(`redirects: handles ${status} to different origin`, async () => { + const id = Math.random().toString(36).slice(2) + const onMessage = getCallCounter({name: 'onMessage'}) + const onOpen = getCallCounter({name: 'onOpen'}) + const url = `${serverUrl}/redirect?status=${status}&id=${id}&cors=true` + const es = new OurEventSource(url, { + ...esInit, + withCredentials: true, + fetch(dstUrl, init) { + return request(dstUrl, { + ...init, + headers: {...init?.headers, authorization: 'Bearer foo'}, + }) + }, + }) + es.addEventListener('message', onMessage.listener) + es.addEventListener('open', onOpen.listener) + + await onMessage.waitForCallCount(1) + + // URL should be the original connected URL, even after redirect + expect(es.url).toBe(url) + + const firstMessage = onMessage.lastArg + expect(firstMessage).toMatchObject({origin: crossOrigin}) + expect(JSON.parse(firstMessage.data)).toMatchObject({ + origin: crossOrigin, + from: url, + redirects: 1, + auth: null, // Authorization header should not follow cross-origin redirects + }) + + // Reconnected and received another message + await onOpen.waitForCallCount(2) + await onMessage.waitForCallCount(2) + + const lastMessage = onMessage.lastArg + expect(lastMessage).toMatchObject({origin: crossOrigin}) + expect(JSON.parse(lastMessage.data)).toMatchObject({ + origin: crossOrigin, + from: url, + redirects: 2, + auth: null, // Authorization header should not follow cross-origin redirects + }) + + // Deno/Bun seems to set timeStamp to `0` πŸ€·β€β™‚οΈ + if (firstMessage.timeStamp > 0) { + expect(firstMessage.timeStamp).not.toBe(lastMessage.timeStamp) + } + + await deferClose(es) + }) +}) + +browserTest( + 'can use the `withCredentials` option to control cookies being sent/not sent cross-origin', + async () => { + // `withCredentials` only applies to cross-origin requests (per spec) + + // With `withCredentials: true`, cookies should be sent + let onOpen = getCallCounter({name: 'onOpen'}) + let es = new OurEventSource(`${crossOriginUrl}/authed`, { + ...esInit, + withCredentials: true, + fetch(url, init) { + expect(init).toMatchObject({credentials: 'include'}) + return request(url, init) + }, + }) + + es.addEventListener('open', onOpen.listener) + await onOpen.waitForCallCount(1) + await deferClose(es) + + // With `withCredentials: false`, no cookies should be sent + es = new OurEventSource(`${crossOriginUrl}/authed`, { + ...esInit, + withCredentials: false, + fetch(url, init) { + expect(init).toMatchObject({credentials: 'same-origin'}) + return request(url, init) + }, + }) + onOpen = getCallCounter({name: 'onOpen'}) + es.addEventListener('open', onOpen.listener) + + await onOpen.waitForCallCount(1) + await deferClose(es) + + // With `withCredentials: undefined`, no cookies should be sent + es = new OurEventSource(`${crossOriginUrl}/authed`, esInit) + onOpen = getCallCounter({name: 'onOpen'}) + es.addEventListener('open', onOpen.listener) + + await onOpen.waitForCallCount(1) + await deferClose(es) + }, +) + +test('throws on `fetch()` that does not return web-stream', async () => { + const url = `${serverUrl}/` + + // @ts-expect-error `body` should be a ReadableStream + const faultyFetch: FetchLike = async () => ({ + body: 'not a stream', + redirected: false, + status: 200, + headers: new Headers({'content-type': 'text/event-stream'}), + url, + }) + + const onError = getCallCounter({name: 'onError'}) + const es = new OurEventSource(url, {fetch: faultyFetch}) + + es.addEventListener('error', onError.listener) + await onError.waitForCallCount(1) + + expect(onError.lastArg).toMatchObject({ + type: 'error', + defaultPrevented: false, + cancelable: false, + timeStamp: expect.any(Number), + message: 'Invalid response body, expected a web ReadableStream', + code: 200, + }) + await deferClose(es) +}) + +test('throws on `fetch()` that does not return a body', async () => { + const url = `${serverUrl}/` + + // @ts-expect-error `body` should be a ReadableStream + const faultyFetch: FetchLike = async () => ({ + redirected: false, + status: 200, + headers: new Headers({'content-type': 'text/event-stream'}), + url, + }) + + const onError = getCallCounter({name: 'onError'}) + const es = new OurEventSource(url, {fetch: faultyFetch}) + + es.addEventListener('error', onError.listener) + await onError.waitForCallCount(1) + + expect(onError.lastArg).toMatchObject({ + type: 'error', + defaultPrevented: false, + cancelable: false, + timeStamp: expect.any(Number), + message: 'Invalid response body, expected a web ReadableStream', + code: 200, + }) + await deferClose(es) +}) + +test('throws on `fetch()` yielding chunks that are not buffers', async () => { + const url = `${serverUrl}/` + + // @ts-expect-error `value` should be a buffer, which is all a `TextDecoder` accepts + const faultyFetch: FetchLike = async () => ({ + body: { + getReader: () => ({ + read: async () => ({done: false, value: 'not a buffer'}), + cancel: async () => {}, + }), + }, + redirected: false, + status: 200, + headers: new Headers({'content-type': 'text/event-stream'}), + url, + }) + + const onError = getCallCounter({name: 'onError'}) + const es = new OurEventSource(url, {fetch: faultyFetch}) + + es.addEventListener('error', onError.listener) + await onError.waitForCallCount(1) + + // The message comes from the runtime's `TextDecoder`, and differs between environments + expect(onError.lastArg).toMatchObject({type: 'error'}) + await deferClose(es) +}) + +test('[NON-SPEC] message event contains extended properties (failed connection)', async () => { + const onError = getCallCounter({name: 'onError'}) + const es = new OurEventSource(`http://127.0.0.1:9999/should-not-connect`, esInit) + + es.addEventListener('error', onError.listener) + await onError.waitForCallCount(1) + + expect(onError.lastArg).toMatchObject({ + type: 'error', + defaultPrevented: false, + cancelable: false, + timeStamp: expect.any(Number), + // Node, Deno, Bun, Chromium, Webkit, Firefox _ALL_ have different messages πŸ˜… + message: expect.stringMatching( + /fetch failed|failed to fetch|load failed|attempting to fetch|connection refused|unable to connect/i, + ), + code: undefined, + }) + await deferClose(es) +}) + +test('[NON-SPEC] message event contains extended properties (invalid http response)', async () => { + const onError = getCallCounter({name: 'onError'}) + const es = new OurEventSource(`${serverUrl}/end-after-one`, esInit) + + es.addEventListener('error', onError.listener) + await onError.waitForCallCount(2) + + expect(onError.lastArg).toMatchObject({ + type: 'error', + defaultPrevented: false, + cancelable: false, + timeStamp: expect.any(Number), + message: 'Server sent HTTP 204, not reconnecting', + code: 204, + }) + await deferClose(es) +}) + +test('[NON-SPEC] custom `maxBufferSize` fails connection on parser buffer overflow', async () => { + const url = `${serverUrl}/` + let fetchCount = 0 + + const faultyFetch: FetchLike = async () => { + fetchCount++ + return { + body: new ReadableStream({ + start(controller) { + const encoder = new TextEncoder() + controller.enqueue(encoder.encode('retry: 10\n')) + controller.enqueue(encoder.encode(`data: ${'x'.repeat(32)}\n`)) + controller.close() + }, + }), + redirected: false, + status: 200, + headers: new Headers({'content-type': 'text/event-stream'}), + url, + } + } + + const onError = getCallCounter({name: 'onError'}) + const es = new OurEventSource(url, {fetch: faultyFetch, maxBufferSize: 16}) + + es.addEventListener('error', onError.listener) + await onError.waitForCallCount(1) + + expect(onError.lastArg).toMatchObject({ + type: 'error', + defaultPrevented: false, + cancelable: false, + timeStamp: expect.any(Number), + message: expect.stringMatching(/Buffered data exceeded max buffer size/), + code: undefined, + }) + expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) + + await new Promise((resolve) => setTimeout(resolve, 50)) + expect(fetchCount).toBe(1) + await deferClose(es) +}) + +test('[NON-SPEC] unrefs the reconnection timer where supported, so it does not keep the event loop alive', async () => { + // Browsers return numeric timer handles, so there is nothing to unref there. + const probe = setTimeout(() => {}, 0) + const supportsUnref = typeof probe === 'object' && probe !== null && 'unref' in probe + clearTimeout(probe) + if (!supportsUnref) { + return + } + + // `/counter` sends `retry: 50`, then disconnects after 3 messages - so the reconnection + // timer is scheduled with a 50ms delay. Capture those specific timers and track whether + // `unref()` was called on them. + const reconnectTimers: Array<{unrefCalled: boolean}> = [] + const realSetTimeout = globalThis.setTimeout + const setTimeoutStub = ( + callback: (...args: unknown[]) => void, + ms?: number, + ...rest: unknown[] + ) => { + const handle = realSetTimeout(callback, ms, ...rest) + if (ms === 50 && typeof handle === 'object' && handle !== null && 'unref' in handle) { + const record = {unrefCalled: false} + reconnectTimers.push(record) + const realUnref = handle.unref.bind(handle) + handle.unref = () => { + record.unrefCalled = true + return realUnref() + } + } + return handle + } + vi.stubGlobal('setTimeout', setTimeoutStub) + + try { + const onError = getCallCounter({name: 'onError'}) + const es = new OurEventSource(`${serverUrl}/counter`, esInit) + es.addEventListener('error', onError.listener) + + // Wait for the disconnect, which schedules the reconnection timer. + await onError.waitForCallCount(1) + + expect(reconnectTimers.length > 0, 'a reconnection timer was scheduled').toBe(true) + expect( + reconnectTimers.every((timer) => timer.unrefCalled), + 'reconnection timer was unref-ed', + ).toBe(true) + + es.close() + } finally { + vi.unstubAllGlobals() + } +}) + +test('has CONNECTING constant', async () => { + const es = new OurEventSource(`${serverUrl}/`) + expect(es.readyState).toBe(OurEventSource.CONNECTING) + expect(es.CONNECTING).toBe(0) + expect(OurEventSource.CONNECTING).toBe(0) + await deferClose(es) +}) + +test('has OPEN constant', async () => { + const onOpen = getCallCounter({name: 'onOpen'}) + const es = new OurEventSource(`${serverUrl}/`) + es.onopen = onOpen.listener + await onOpen.waitForCallCount(1) + expect(es.readyState).toBe(OurEventSource.OPEN) + expect(es.OPEN).toBe(1) + expect(OurEventSource.OPEN).toBe(1) + await deferClose(es) +}) + +test('has CLOSED constant', async () => { + const es = new OurEventSource(`${serverUrl}/`) + es.close() + expect(es.readyState).toBe(OurEventSource.CLOSED) + expect(es.CLOSED).toBe(2) + expect(OurEventSource.CLOSED).toBe(2) + await deferClose(es) +}) + +test('has non-enumarable `eventsource.supports-fetch-override` symbol', () => { + const supportsFetchOverride = Symbol.for('eventsource.supports-fetch-override') + expect(Object.getOwnPropertySymbols(OurEventSource).includes(supportsFetchOverride)).toBe(true) + expect(Object.keys(OurEventSource).includes('supports-fetch-override')).toBe(false) + expect(supportsFetchOverride in OurEventSource).toBe(true) +}) diff --git a/test/deno/client.deno.test.ts b/test/deno/client.deno.test.ts deleted file mode 100644 index 7b0b33b5..00000000 --- a/test/deno/client.deno.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import {getServer} from '../server.ts' -import {registerTests} from '../tests.ts' -import {createRunner} from '../waffletest/index.ts' -import {nodeReporter} from '../waffletest/reporters/nodeReporter.ts' - -const DENO_TEST_PORT = 3950 - -// Run the tests in deno -;(async function run() { - const server = await getServer(DENO_TEST_PORT) - - const runner = registerTests({ - environment: 'deno', - runner: createRunner(nodeReporter), - fetch: globalThis.fetch, - port: DENO_TEST_PORT, - }) - - const result = await runner.runTests() - - // Teardown - await server.close() - - if (typeof process !== 'undefined' && 'exit' in process && typeof process.exit === 'function') { - // eslint-disable-next-line no-process-exit - process.exit(result.failures) - } else if (typeof globalThis.Deno !== 'undefined') { - globalThis.Deno.exit(result.failures) - } else if (result.failures > 0) { - throw new Error(`Tests failed: ${result.failures}`) - } -})() diff --git a/test/fixtures.ts b/test/fixtures.ts deleted file mode 100644 index d8dbc307..00000000 --- a/test/fixtures.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const unicodeLines = [ - 'πŸ¦„ are cool. 🐾 in the snow. Allyson Felix, πŸƒπŸ½β€β™€οΈ πŸ₯‡ 2012 London!', - 'Espen β™₯ Kokos', -] diff --git a/test/helpers.ts b/test/helpers.ts deleted file mode 100644 index 75c73127..00000000 --- a/test/helpers.ts +++ /dev/null @@ -1,232 +0,0 @@ -import sinon, {type SinonSpy} from 'sinon' - -import {EventSource} from '../src/EventSource.ts' - -type MessageReceiver = SinonSpy & { - waitForCallCount: (num: number, timeout?: number) => Promise -} - -const TYPE_ASSERTER = Symbol.for('waffle.type-asserter') -const PATTERN_ASSERTER = Symbol.for('waffle.pattern-asserter') - -export class ExpectationError extends Error { - type = 'ExpectationError' - - public expected: unknown - public got: unknown - - constructor(message: string, expected?: unknown, got?: unknown) { - super(message) - this.name = 'ExpectationError' - this.expected = expected - this.got = got - } -} - -interface CallCounterOptions { - name?: string - onCall?: (info: {numCalls: number}) => void -} - -export function getCallCounter({name = '', onCall}: CallCounterOptions = {}): MessageReceiver { - const listeners: [number, () => void][] = [] - - let numCalls = 0 - const spy = sinon.fake(() => { - numCalls++ - - if (onCall) { - onCall({numCalls}) - } - - listeners.forEach(([wanted, resolve]) => { - if (wanted === numCalls) { - resolve() - } - }) - }) - - const fn = spy as unknown as MessageReceiver - fn.waitForCallCount = (num: number, timeout: number = 10000) => { - return Promise.race([ - new Promise((resolve, reject) => { - if (numCalls > num) { - reject(new Error(`Already past ${name} call count of ${num}`)) - } else if (numCalls === num) { - resolve() - } else { - listeners.push([num, resolve]) - } - }), - new Promise((_, reject) => { - setTimeout(reject, timeout, new Error(`Timeout waiting for ${name} call count of ${num}`)) - }), - ]) - } - - return fn -} - -export function deferClose(es: EventSource, timeout = 25): Promise { - return new Promise((resolve) => setTimeout(() => resolve(es.close()), timeout)) -} - -export function expect( - thing: unknown, - descriptor: string = '', -): { - toBe(expected: unknown): void - notToBe(expected: unknown): void - toBeLessThan(thanNum: number): void - toMatchObject(expected: Record): void - toThrowError(expectedMessage: RegExp): void -} { - return { - toBe(expected: unknown) { - if (thing === expected) { - return - } - - if (descriptor) { - throw new ExpectationError( - `Expected ${descriptor} to be ${JSON.stringify(expected)}, got ${JSON.stringify(thing)}`, - ) - } - - throw new ExpectationError( - `Expected ${JSON.stringify(thing)} to be ${JSON.stringify(expected)}`, - ) - }, - - notToBe(expected: unknown) { - if (thing !== expected) { - return - } - - if (descriptor) { - throw new ExpectationError( - `Expected ${descriptor} NOT to be ${JSON.stringify(expected)}, got ${JSON.stringify(thing)}`, - ) - } - - throw new ExpectationError( - `Expected ${JSON.stringify(thing)} NOT to be ${JSON.stringify(expected)}`, - ) - }, - - toBeLessThan(thanNum: number) { - if (typeof thing !== 'number' || thing >= thanNum) { - throw new ExpectationError(`Expected ${thing} to be less than ${thanNum}`) - } - }, - - toMatchObject(expected: Record) { - if (!isPlainObject(thing)) { - throw new ExpectationError(`Expected an object, was... not`) - } - - Object.keys(expected).forEach((key) => { - if (!(key in thing)) { - throw new ExpectationError( - `Expected key "${key}" to be in ${descriptor || 'object'}, was not`, - expected, - thing, - ) - } - - if ( - typeof expected[key] === 'object' && - expected[key] !== null && - TYPE_ASSERTER in expected[key] - ) { - if (typeof thing[key] !== expected[key][TYPE_ASSERTER]) { - throw new ExpectationError( - `Expected key "${key}" of ${descriptor || 'object'} to be any of type ${expect[key][TYPE_ASSERTER]}, got ${typeof thing[key]}`, - ) - } - return - } - - if ( - typeof expected[key] === 'object' && - expected[key] !== null && - PATTERN_ASSERTER in expected[key] - ) { - if (typeof thing[key] !== 'string') { - throw new ExpectationError( - `Expected key "${key}" of ${descriptor || 'object'} to be a string, got ${typeof thing[key]}`, - ) - } - - if (typeof expected[key][PATTERN_ASSERTER] === 'string') { - if (!thing[key].includes(expected[key][PATTERN_ASSERTER])) { - throw new ExpectationError( - `Expected key "${key}" of ${descriptor || 'object'} to include "${expected[key][PATTERN_ASSERTER]}", got "${thing[key]}"`, - ) - } - return - } - - if (expected[key][PATTERN_ASSERTER] instanceof RegExp) { - if (!expected[key][PATTERN_ASSERTER].test(thing[key])) { - throw new ExpectationError( - `Expected key "${key}" of ${descriptor || 'object'} to match pattern ${expected[key][PATTERN_ASSERTER]}, got "${thing[key]}"`, - ) - } - return - } - - throw new Error('Invalid pattern asserter') - } - - if (thing[key] !== expected[key]) { - throw new ExpectationError( - `Expected key "${key}" of ${descriptor || 'object'} to be ${JSON.stringify(expected[key])}, was ${JSON.stringify( - thing[key], - )}`, - ) - } - }) - }, - - toThrowError(expectedMessage: RegExp) { - if (typeof thing !== 'function') { - throw new ExpectationError( - `Expected a function that was going to throw, but wasn't a function`, - ) - } - - try { - thing() - } catch (err: unknown) { - const message = err instanceof Error ? err.message : `${err}` - if (!expectedMessage.test(message)) { - throw new ExpectationError( - `Expected error message to match ${expectedMessage}, got ${message}`, - ) - } - return - } - - throw new ExpectationError('Expected function to throw error, but did not') - }, - } -} - -expect.any = ( - type: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function', -) => { - return { - [TYPE_ASSERTER]: type, - } -} - -expect.stringMatching = (expected: string | RegExp) => { - return { - [PATTERN_ASSERTER]: expected, - } -} - -function isPlainObject(obj: unknown): obj is Record { - return typeof obj === 'object' && obj !== null && !Array.isArray(obj) -} diff --git a/test/helpers/callCounter.ts b/test/helpers/callCounter.ts new file mode 100644 index 00000000..df99a261 --- /dev/null +++ b/test/helpers/callCounter.ts @@ -0,0 +1,96 @@ +import type {EventSource} from '../../src/EventSource.ts' + +/** + * A listener that records its calls and can be awaited until it has been called a given number + * of times. Most of the suite tests behaviour that only becomes observable after N events - + * a reconnect, a retry, a disconnect - so waiting on a call count is the main synchronisation + * primitive. + */ +export interface CallCounter { + /** Pass to `addEventListener`, or assign to one of the `on*` handlers. */ + readonly listener: (event: T) => void + /** Number of times the listener has been called so far. */ + readonly callCount: number + /** Argument of the most recent call. Throws if it has not been called yet. */ + readonly lastArg: T + /** + * Resolves once the listener has been called exactly `num` times. + * + * Rejects if the count is already past `num`, since waiting for an event that has already + * been and gone is a test bug rather than something that can still happen, and rejects if + * `num` is not reached within `timeout` ms. + */ + waitForCallCount(num: number, timeout?: number): Promise +} + +interface CallCounterOptions { + name?: string + onCall?: (info: {numCalls: number}) => void +} + +export function getCallCounter({ + name = '', + onCall, +}: CallCounterOptions = {}): CallCounter { + const listeners: [number, () => void][] = [] + + let callCount = 0 + // Held in a wrapper so that `lastArg` can narrow it without an assertion - `undefined` is a + // legitimate call argument, so its absence cannot stand in for "never called". + let last: {event: T} | undefined + + function listener(event: T): void { + callCount++ + last = {event} + + if (onCall) { + onCall({numCalls: callCount}) + } + + for (const [wanted, resolve] of listeners) { + if (wanted === callCount) { + resolve() + } + } + } + + return { + listener, + + get callCount() { + return callCount + }, + + get lastArg() { + if (!last) { + throw new Error(`${name || 'Counter'} has not been called`) + } + return last.event + }, + + waitForCallCount(num: number, timeout: number = 10000) { + return Promise.race([ + new Promise((resolve, reject) => { + if (callCount > num) { + reject(new Error(`Already past ${name} call count of ${num}`)) + } else if (callCount === num) { + resolve() + } else { + listeners.push([num, resolve]) + } + }), + new Promise((_, reject) => { + setTimeout(reject, timeout, new Error(`Timeout waiting for ${name} call count of ${num}`)) + }), + ]) + }, + } +} + +/** + * Closes an EventSource after a short delay, giving any in-flight reconnect the chance to + * happen - and thus be caught - before the test tears the connection down. + */ +export function deferClose(es: EventSource, timeout = 25): Promise { + return new Promise((resolve) => setTimeout(() => resolve(es.close()), timeout)) +} diff --git a/test/helpers/env.ts b/test/helpers/env.ts new file mode 100644 index 00000000..53a81124 --- /dev/null +++ b/test/helpers/env.ts @@ -0,0 +1,68 @@ +import {inject} from 'vitest' + +import type {FetchLike} from '../../src/index.ts' +import {ROUTE_PREFIX} from './routes.ts' + +/** + * Which `vitest.*.config.ts` is driving the current run. Provided by the config rather than + * sniffed at runtime, because several suites are deliberately hard to tell apart from the + * inside: happy-dom presents a `document`, and node/bun/deno all share the base config. + */ +export type Suite = 'node' | 'browser' | 'happy-dom' | 'workerd' + +declare module 'vitest' { + interface ProvidedContext { + /** Which `vitest.*.config.ts` is running. */ + suite: Suite + /** Port the test endpoints are reachable on. */ + port: number + } +} + +export const suite: Suite = inject('suite') + +/** + * Origin the test endpoints are served from. + * + * For the browser suite this is Vitest's own Vite dev server (its port is pinned in + * `vitest.browser.config.ts`), which is also the origin the test page itself is loaded from - + * so browser requests to it are same-origin, matching how the endpoints and the page used to + * be served by one and the same node server. Every other suite talks to the standalone server + * that `globalSetup.ts` starts. + */ +export const serverOrigin = `http://127.0.0.1:${inject('port')}` + +/** Base URL for the test endpoints, eg `http://127.0.0.1:3944/sse`. */ +export const serverUrl = `${serverOrigin}${ROUTE_PREFIX}` + +/** + * A second origin that resolves to the same server, for exercising CORS and cross-origin + * redirects. `localhost` and `127.0.0.1` are distinct origins to a browser, but both reach the + * server: the standalone one listens dual-stack, and Vite's is reached over the loopback the + * browser falls back to. + */ +export const crossOrigin = serverOrigin.replace('127.0.0.1', 'localhost') + +/** Cross-origin equivalent of `serverUrl`. */ +export const crossOriginUrl = `${crossOrigin}${ROUTE_PREFIX}` + +/** + * Whether the suite enforces browser semantics - CORS preflights, an origin-scoped cookie jar + * and `withCredentials`. True for happy-dom as well as real browsers, so that the tests which + * only make sense under those rules still run there. + */ +export const hasBrowserSemantics = suite === 'browser' || suite === 'happy-dom' + +/** + * `EventSource` options every test in the suite starts from. + * + * The server-side runtimes get an explicitly injected `fetch`, which is what the `fetch` option + * exists for. The browser-like suites deliberately pass nothing and let `EventSource` fall back + * to its own default, because browsers reject a `globalThis.fetch` invoked without its original + * receiver. Spread it rather than setting `fetch` to `undefined`, which `exactOptionalPropertyTypes` + * rightly rejects: absent and "present but undefined" are not the same thing here. + */ +export const esInit: {fetch?: FetchLike} = hasBrowserSemantics ? {} : {fetch: globalThis.fetch} + +/** Unconditional `fetch`, for the assertions and custom `fetch` options that call the server. */ +export const request: typeof globalThis.fetch = (...args) => globalThis.fetch(...args) diff --git a/test/helpers/fixtures.ts b/test/helpers/fixtures.ts new file mode 100644 index 00000000..e3233bd2 --- /dev/null +++ b/test/helpers/fixtures.ts @@ -0,0 +1,5 @@ +/** Typed as a tuple so the indexed reads in the server and tests are known to be present. */ +export const unicodeLines: [string, string] = [ + 'πŸ¦„ are cool. 🐾 in the snow. Allyson Felix, πŸƒπŸ½β€β™€οΈ πŸ₯‡ 2012 London!', + 'Espen β™₯ Kokos', +] diff --git a/test/helpers/globalSetup.ts b/test/helpers/globalSetup.ts new file mode 100644 index 00000000..29e51243 --- /dev/null +++ b/test/helpers/globalSetup.ts @@ -0,0 +1,32 @@ +import type {TestProject} from 'vitest/node' + +import {TEST_PORT} from './routes.ts' +import {createTestServer} from './server.ts' + +/** + * Starts the standalone test server for the suites that do not run in a browser. The browser + * suite does not use this at all - it serves the same routes from Vitest's own Vite server, to + * stay same-origin with the test page - and provides its own port instead. + */ +export default async function setup(project: TestProject): Promise<() => Promise> { + const server = await createTestServer(TEST_PORT) + project.provide('port', TEST_PORT) + + /** + * Keeps this process's event loop turning for as long as the server is up. + * + * The server runs here, in Vitest's main process, while the tests run in a worker. Under Deno + * that is not enough on its own: with only an idle listening socket pending, the main process + * stops servicing the server's timer-driven writes, so any endpoint that sends data after a + * delay stalls after the first couple of chunks - and since delays are how reconnects and + * trickling streams are tested, most of the suite hangs. A live timer keeps the loop hot. + * Harmless on the other runtimes, which do not need it. + */ + const keepAlive = setInterval(() => {}, 100) + + return async () => { + clearInterval(keepAlive) + server.closeAllConnections() + await new Promise((resolve) => server.close(() => resolve())) + } +} diff --git a/test/helpers/routes.ts b/test/helpers/routes.ts new file mode 100644 index 00000000..e712044a --- /dev/null +++ b/test/helpers/routes.ts @@ -0,0 +1,27 @@ +/** + * Constants shared by the test server, the configs and the tests themselves. + * + * Deliberately free of node imports: the tests import this module, and in the browser suite they + * are bundled for and executed in the browser, where anything reaching into `node:*` fails to + * load. The server itself lives in `server.ts`, which nothing browser-side imports. + */ + +/** + * All test endpoints live under this prefix. + * + * The browser suite mounts the endpoints onto Vitest's own Vite dev server (see `ssePlugin.ts`) + * so that the test page and the endpoints share an origin, exactly as they did when a single + * node server served both. Namespacing keeps us clear of Vite's own routes - most importantly + * `/`, which Vite serves its HTML from. + */ +export const ROUTE_PREFIX = '/sse' + +/** Port the standalone test server binds, for every suite that is not the browser one. */ +export const TEST_PORT = 3944 + +/** + * Port for Vitest's Vite server in the browser suite, which serves both the test page and the + * test endpoints. Pinning it is what lets the tests address the endpoints on the same origin the + * page was loaded from; with a random port they could not know it up front. + */ +export const BROWSER_PORT = 3883 diff --git a/test/server.ts b/test/helpers/server.ts similarity index 85% rename from test/server.ts rename to test/helpers/server.ts index fe60a8b7..ec727430 100644 --- a/test/server.ts +++ b/test/helpers/server.ts @@ -1,5 +1,4 @@ import {createHash} from 'node:crypto' -import {createReadStream} from 'node:fs' import { createServer, type IncomingMessage, @@ -7,46 +6,53 @@ import { type Server, type ServerResponse, } from 'node:http' -import {dirname, resolve as resolvePath} from 'node:path' -import {fileURLToPath} from 'node:url' -import esbuild from 'esbuild' import {encode} from 'eventsource-encoder' import {unicodeLines} from './fixtures.ts' +import {ROUTE_PREFIX} from './routes.ts' -const isDeno = typeof globalThis.Deno !== 'undefined' +const isDeno = 'Deno' in globalThis /* {[client id]: number of connects} */ const connectCounts = new Map() -export async function getServer(port: number): Promise<{close: () => Promise}> { - const server = await promServer(port) - - const closeServer = () => - new Promise((resolve, reject) => { - server.close((err) => (err ? reject(err) : resolve())) - }) - - return { - close: closeServer, - } - - function promServer(portNumber: number) { - return new Promise((resolve, reject) => { - const srv = createServer(onRequest) - .on('error', reject) - .listen(portNumber, isDeno ? '127.0.0.1' : '::', () => resolve(srv)) - }) - } +/** + * Starts a standalone server for the suites that do not run in a browser. Resolves with the + * server even if the port is already bound, so that concurrently running suites (or a + * `globalSetup` that a pool invokes more than once) do not fail the run. + */ +export function createTestServer(port: number): Promise { + return new Promise((resolve, reject) => { + const srv = createServer((req, res) => handleRequest(req, res)) + .on('error', (err: NodeJS.ErrnoException) => + err.code === 'EADDRINUSE' ? resolve(srv) : reject(err), + ) + .listen(port, isDeno ? '127.0.0.1' : '::', () => resolve(srv)) + }) } -function onRequest(req: IncomingMessage, res: ServerResponse) { +/** + * Connect-compatible request handler, so the same routes can be served either from a + * standalone `node:http` server or as Vite middleware. Requests outside `ROUTE_PREFIX` are + * passed to `next()` when it is present (Vite serves the test page and modules), and 404 when + * it is not. + */ +export function handleRequest( + req: IncomingMessage, + res: ServerResponse, + next?: () => void, +): void | Promise { // Disable Nagle's algorithm for testing if (res.socket && 'setNoDelay' in res.socket) { res.socket.setNoDelay(true) } - const path = new URL(req.url || '/', 'http://localhost').pathname + const {pathname} = new URL(req.url || '/', 'http://localhost') + if (!pathname.startsWith(ROUTE_PREFIX)) { + return next ? next() : writeFallback(req, res) + } + + const path = pathname.slice(ROUTE_PREFIX.length) || '/' switch (path) { // Server-Sent Event endpoints case '/': @@ -78,12 +84,6 @@ function onRequest(req: IncomingMessage, res: ServerResponse) { case '/redirect-target': return writeRedirectTarget(req, res) - // Browser test endpoints (HTML/JS) - case '/browser-test': - return writeBrowserTestPage(req, res) - case '/browser-test.js': - return writeBrowserTestScript(req, res) - // Fallback, eg 404 default: return writeFallback(req, res) @@ -336,7 +336,7 @@ async function writeRedirect(req: IncomingMessage, res: ServerResponse) { xOriginUrl.hostname = url.hostname === 'localhost' ? '127.0.0.1' : 'localhost' const status = parseInt(redirectUrl, 10) - const path = `/redirect-target?from=${encodeURIComponent(url.toString())}&id=${id}` + const path = `${ROUTE_PREFIX}/redirect-target?from=${encodeURIComponent(url.toString())}&id=${id}` res.writeHead(status, { 'Cache-Control': 'no-cache', @@ -488,7 +488,7 @@ function writeCookies(req: IncomingMessage, res: ServerResponse) { 'Access-Control-Allow-Credentials': 'true', 'Content-Type': 'application/json', 'Cache-Control': 'no-cache', - 'Set-Cookie': 'someSession=someValue; Path=/authed; HttpOnly; SameSite=Lax;', + 'Set-Cookie': `someSession=someValue; Path=${ROUTE_PREFIX}/authed; HttpOnly; SameSite=Lax;`, Connection: 'keep-alive', }) tryWrite(res, JSON.stringify({cookiesWritten: true})) @@ -533,38 +533,6 @@ function writeFallback(_req: IncomingMessage, res: ServerResponse) { res.end() } -function writeBrowserTestPage(_req: IncomingMessage, res: ServerResponse) { - res.writeHead(200, { - 'Content-Type': 'text/html; charset=utf-8', - 'Cache-Control': 'no-cache', - Connection: 'close', - }) - - const thisDir = dirname(fileURLToPath(import.meta.url)) - createReadStream(resolvePath(thisDir, './browser/browser-test.html')).pipe(res) -} - -async function writeBrowserTestScript(_req: IncomingMessage, res: ServerResponse) { - res.writeHead(200, { - 'Content-Type': 'text/javascript; charset=utf-8', - 'Cache-Control': 'no-cache', - Connection: 'close', - }) - - const thisDir = dirname(fileURLToPath(import.meta.url)) - const build = await esbuild.build({ - bundle: true, - target: ['chrome71', 'edge79', 'firefox105', 'safari14.1'], - entryPoints: [resolvePath(thisDir, './browser/browser-test.ts')], - sourcemap: 'inline', - write: false, - outdir: 'out', - }) - - tryWrite(res, build.outputFiles.map((file) => file.text).join('\n\n')) - res.end() -} - function delay(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)) } diff --git a/test/helpers/ssePlugin.ts b/test/helpers/ssePlugin.ts new file mode 100644 index 00000000..5c3a71c0 --- /dev/null +++ b/test/helpers/ssePlugin.ts @@ -0,0 +1,33 @@ +import type {Plugin} from 'vite' + +import {handleRequest} from './server.ts' + +/** + * Serves the test endpoints from Vitest's own Vite dev server. + * + * The browser suite loads its test page from that server, so mounting the endpoints here is what + * keeps the two same-origin - the arrangement the suite's CORS, cookie and redirect expectations + * are written against. Point the browser tests at a separately started server instead and every + * request becomes cross-origin, which quietly changes what those tests mean. + */ +export function ssePlugin(): Plugin { + return { + name: 'eventsource-test-endpoints', + configureServer(server) { + server.middlewares.use(handleRequest) + + // Move ourselves to the front of the connect stack. + // + // Vite installs its own CORS middleware ahead of plugin middleware. Firefox and WebKit + // send a CORS preflight for the second leg of a cross-origin redirect (Chromium does not), + // and Vite's middleware answers that OPTIONS request under its own policy before the test + // server ever sees it - which fails the cross-origin redirect tests in those two engines + // only. The test server owns CORS for its own routes, exactly as it did when a standalone + // node server served them, so it has to be given the request first. + const layer = server.middlewares.stack.pop() + if (layer) { + server.middlewares.stack.unshift(layer) + } + }, + } +} diff --git a/test/node/client.node.test.ts b/test/node/client.node.test.ts deleted file mode 100644 index 024f57a2..00000000 --- a/test/node/client.node.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * This module: - * - Starts a development server - * - Runs tests against them using a ducktaped simple test/assertion thing - * - Prints the test results to the console - * - * Could we use a testing library? Yes. - * Would that add a whole lot of value? No. - */ -import {getServer} from '../server.ts' -import {registerTests} from '../tests.ts' -import {nodeReporter} from '../waffletest/reporters/nodeReporter.ts' -import {createRunner} from '../waffletest/runner.ts' - -const NODE_TEST_PORT = 3944 - -// Run the tests in node.js -;(async function run() { - const server = await getServer(NODE_TEST_PORT) - - const runner = registerTests({ - environment: 'node', - runner: createRunner(nodeReporter), - fetch: globalThis.fetch, - port: NODE_TEST_PORT, - }) - - const result = await runner.runTests() - - // Teardown - await server.close() - - // eslint-disable-next-line no-process-exit - process.exit(result.failures) -})() diff --git a/test/tests.ts b/test/tests.ts deleted file mode 100644 index 50fc2c3b..00000000 --- a/test/tests.ts +++ /dev/null @@ -1,922 +0,0 @@ -import { - EventSource as OurEventSource, - type EventSourceFetchInit, - type FetchLike, -} from '../src/index.ts' -import {unicodeLines} from './fixtures.ts' -import {deferClose, expect, getCallCounter} from './helpers.ts' -import type {TestRunner} from './waffletest/index.ts' - -export function registerTests(options: { - environment: string - runner: TestRunner - port: number - fetch?: typeof fetch -}): TestRunner { - const {port, fetch, runner, environment} = options - - // eslint-disable-next-line no-empty-function - const browserTest = environment === 'browser' ? runner.registerTest : function noop() {} - const test = runner.registerTest - - const baseUrl = - typeof document === 'undefined' - ? 'http://127.0.0.1' - : `${location.protocol}//${location.hostname}` - - test('can connect, receive message, manually disconnect', async () => { - const onMessage = getCallCounter({name: 'onMessage'}) - const es = new OurEventSource(new URL(`${baseUrl}:${port}/`)) - es.addEventListener('welcome', onMessage, false) - - await onMessage.waitForCallCount(1) - - expect(onMessage.callCount).toBe(1) - expect(onMessage.lastCall.lastArg).toMatchObject({ - data: 'Hello, world!', - origin: `${baseUrl}:${port}`, - }) - - await deferClose(es) - }) - - test('`target` on open, message and error events is the EventSource instance', async () => { - const onOpen = getCallCounter({name: 'onOpen'}) - const onMessage = getCallCounter({name: 'onMessage'}) - const onError = getCallCounter({name: 'onError'}) - const es = new OurEventSource(`${baseUrl}:${port}/end-after-one`) - - es.addEventListener('open', onOpen) - es.addEventListener('progress', onMessage) - es.addEventListener('error', onError) - - await onOpen.waitForCallCount(1) - await onMessage.waitForCallCount(1) - await onError.waitForCallCount(1) - - expect(onOpen.lastCall.lastArg.target).toBe(es) - expect(onMessage.lastCall.lastArg.target).toBe(es) - expect(onError.lastCall.lastArg.target).toBe(es) - - await deferClose(es) - }) - - test('can connect using URL string only', async () => { - const es = new OurEventSource(`${baseUrl}:${port}/`) - const onMessage = getCallCounter({name: 'onMessage'}) - es.addEventListener('welcome', onMessage, false) - - await onMessage.waitForCallCount(1) - await deferClose(es) - }) - - test('passes `no-store` to `fetch`, avoiding cache', async () => { - let passedInit: EventSourceFetchInit | undefined - - const onMessage = getCallCounter({name: 'onMessage'}) - const es = new OurEventSource(new URL(`${baseUrl}:${port}/debug`), { - fetch: (url, init) => { - passedInit = init - return (fetch || globalThis.fetch)(url, init) - }, - }) - - es.addEventListener('debug', onMessage, false) - await onMessage.waitForCallCount(1) - - expect(passedInit).toMatchObject({cache: 'no-store'}) - await deferClose(es) - }) - - test('can handle unicode data correctly', async () => { - const onMessage = getCallCounter({name: 'onMessage'}) - const es = new OurEventSource(`${baseUrl}:${port}/unicode`, {fetch}) - - const messages: Array<{data: string}> = [] - es.addEventListener('unicode', (evt) => { - messages.push(evt) - onMessage() - }) - - await onMessage.waitForCallCount(2) - expect(messages[0].data).toBe(unicodeLines[0]) - expect(messages[1].data).toBe(unicodeLines[1]) - - await deferClose(es) - }) - - test('can use `es.onopen` to listen for open events, nulling it unsubscribes', async () => { - const onError = getCallCounter({name: 'onError'}) - const onOpen = getCallCounter({name: 'onOpen'}) - const es = new OurEventSource(`${baseUrl}:${port}/counter`, {fetch}) - es.addEventListener('error', onError) - es.onopen = onOpen - - await onOpen.waitForCallCount(2) - es.onopen = null - - await onError.waitForCallCount(4) // 4 disconnects - - // If `es.onopen = null` did not work, this should be 4 - expect(onOpen.callCount).toBe(2) - await deferClose(es) - }) - - test('can use `es.onerror` to listen for error events, nulling it unsubscribes', async () => { - const onError = getCallCounter({name: 'onError'}) - const onOpen = getCallCounter({name: 'onOpen'}) - const es = new OurEventSource(`${baseUrl}:${port}/counter`, {fetch}) - es.addEventListener('open', onOpen) - es.onerror = onError - - await onOpen.waitForCallCount(3) - es.onerror = null - - await onOpen.waitForCallCount(4) // 4 connects - - // If `es.onerror = null` did not work, this should be 4 - expect(onError.callCount).toBe(2) - await deferClose(es) - }) - - test('can use `es.onmessage` to listen for explicit `message` events, nulling it unsubscribes', async () => { - const onMessage = getCallCounter({name: 'onMessage'}) - const onError = getCallCounter({name: 'onError'}) - const es = new OurEventSource(`${baseUrl}:${port}/counter?event=message`, {fetch}) - es.addEventListener('error', onError) - es.onmessage = onMessage - - await onError.waitForCallCount(2) - es.onmessage = null - - await onError.waitForCallCount(3) // 3 disconnects - - // If `es.onmessage = null` did not work, this should be 9, - // since each connect emits 3 message then closes - expect(onMessage.callCount).toBe(6) - await deferClose(es) - }) - - test('can use `es.onmessage` to listen for implicit `message` events, nulling it unsubscribes', async () => { - const onMessage = getCallCounter({name: 'onMessage'}) - const onError = getCallCounter({name: 'onError'}) - const es = new OurEventSource(`${baseUrl}:${port}/counter?event=`, {fetch}) - es.addEventListener('error', onError) - es.onmessage = onMessage - - await onError.waitForCallCount(2) - es.onmessage = null - - await onError.waitForCallCount(3) // 3 disconnects - - // If `es.onmessage = null` did not work, this should be 9, - // since each connect emits 3 message then closes - expect(onMessage.callCount).toBe(6) - await deferClose(es) - }) - - test('`es.onmessage` does not fire for non-`message` events', async () => { - const onMessage = getCallCounter({name: 'onMessage'}) - const onOpen = getCallCounter({name: 'onOpen'}) - const es = new OurEventSource(`${baseUrl}:${port}/counter`, {fetch}) - es.addEventListener('open', onOpen) - es.onmessage = onMessage - - await onOpen.waitForCallCount(3) - es.onmessage = null - - // `event` was never "message" (or blank), only ever `counter` - expect(onMessage.callCount).toBe(0) - await deferClose(es) - }) - - test('`es.onmessage` does not fire for non-`message` events', async () => { - const onMessage = getCallCounter({name: 'onMessage'}) - const onOpen = getCallCounter({name: 'onOpen'}) - const es = new OurEventSource(`${baseUrl}:${port}/counter`, {fetch}) - es.addEventListener('open', onOpen) - es.onmessage = onMessage - - await onOpen.waitForCallCount(3) - es.onmessage = null - - // `event` was never "message" (or blank), only ever `counter` - expect(onMessage.callCount).toBe(0) - await deferClose(es) - }) - - test('can redeclare `es.onopen` after initial assignment', async () => { - const onError = getCallCounter({name: 'onError'}) - const onOpen = getCallCounter({name: 'onOpen'}) - const onOpenNew = getCallCounter({name: 'onOpen (new)'}) - const es = new OurEventSource(`${baseUrl}:${port}/counter`, {fetch}) - es.addEventListener('error', onError) - es.onopen = onOpen - - await onOpen.waitForCallCount(2) - es.onopen = onOpenNew - - await onError.waitForCallCount(4) // 4 disconnects - - // If `es.onopen = ` did not work, this should be 4 - expect(onOpen.callCount).toBe(2) - expect(onOpenNew.callCount).toBe(2) - await deferClose(es) - }) - - test('can redeclare `es.onerror` after initial assignment', async () => { - const onError = getCallCounter({name: 'onError'}) - const onErrorNew = getCallCounter({name: 'onError (new)'}) - const onOpen = getCallCounter({name: 'onOpen'}) - const es = new OurEventSource(`${baseUrl}:${port}/counter`, {fetch}) - es.addEventListener('open', onOpen) - es.onerror = onError - - await onOpen.waitForCallCount(3) - es.onerror = onErrorNew - - await onOpen.waitForCallCount(4) // 4 connects - - // If `es.onerror = ` did not work, this should be 4 - expect(onError.callCount).toBe(2) - expect(onErrorNew.callCount).toBe(1) - await deferClose(es) - }) - - test('can redeclare `es.onmessage` after initial assignment', async () => { - const onMessage = getCallCounter({name: 'onMessage'}) - const onMessageNew = getCallCounter({name: 'onMessage (new)'}) - const onError = getCallCounter({name: 'onError'}) - const es = new OurEventSource(`${baseUrl}:${port}/counter?event=message`, {fetch}) - es.addEventListener('error', onError) - es.onmessage = onMessage - - await onError.waitForCallCount(2) - es.onmessage = onMessageNew - - await onError.waitForCallCount(3) // 3 disconnects - - // If `es.onmessage = ` did not work, this should be 9, - // since each connect emits 3 message then closes - expect(onMessage.callCount).toBe(6) - expect(onMessageNew.callCount).toBe(3) - await deferClose(es) - }) - - test('on-handlers fire in registration order relative to `addEventListener`', async () => { - const order: string[] = [] - const onOpen = getCallCounter({name: 'onOpen'}) - const es = new OurEventSource(`${baseUrl}:${port}/`, {fetch}) - - // `addEventListener` is registered _before_ the `onopen` handler is assigned, so per spec - // the `addEventListener` callback must fire first (the event handler IDL attribute fires - // in the order it was set, relative to other listeners). - es.addEventListener('open', () => order.push('addEventListener')) - es.onopen = () => { - order.push('onopen') - onOpen() - } - - await onOpen.waitForCallCount(1) - - expect(order[0], 'first handler to fire').toBe('addEventListener') - expect(order[1], 'second handler to fire').toBe('onopen') - - await deferClose(es) - }) - - test('message event contains correct properties', async () => { - const onMessage = getCallCounter({name: 'onMessage'}) - const es = new OurEventSource(`${baseUrl}:${port}/counter`, {fetch}) - - es.addEventListener('counter', onMessage) - await onMessage.waitForCallCount(1) - - expect(onMessage.lastCall.lastArg).toMatchObject({ - data: 'Counter is at 1', - type: 'counter', - lastEventId: '1', - origin: `${baseUrl}:${port}`, - defaultPrevented: false, - cancelable: false, - timeStamp: expect.any('number'), - }) - await deferClose(es) - }) - - test('will reconnect with last received message id if server disconnects', async () => { - const onMessage = getCallCounter({name: 'onMessage'}) - const onError = getCallCounter({name: 'onError'}) - const url = `${baseUrl}:${port}/counter` - const es = new OurEventSource(url, {fetch}) - es.addEventListener('counter', onMessage) - es.addEventListener('error', onError) - - // While still receiving messages (we receive 3 at a time before it disconnects) - await onMessage.waitForCallCount(1) - expect(es.readyState, 'readyState').toBe(OurEventSource.OPEN) // Open (connected) - - // While waiting for reconnect (after 3 messages it will disconnect and reconnect) - await onError.waitForCallCount(1) - expect(es.readyState, 'readyState').toBe(OurEventSource.CONNECTING) // Connecting (reconnecting) - expect(onMessage.callCount).toBe(3) - - // Will reconnect infinitely, stop at 8 messages - await onMessage.waitForCallCount(8) - - expect(es.url).toBe(url) - expect(onMessage.lastCall.lastArg).toMatchObject({ - data: 'Counter is at 8', - type: 'counter', - lastEventId: '8', - origin: `${baseUrl}:${port}`, - }) - expect(onMessage.callCount).toBe(8) - - await deferClose(es) - }) - - test('will not reconnect after explicit `close()`', async () => { - const request = fetch || globalThis.fetch - const onMessage = getCallCounter({name: 'onMessage'}) - const onError = getCallCounter({name: 'onError'}) - const clientId = Math.random().toString(36).slice(2) - const url = `${baseUrl}:${port}/identified?client-id=${clientId}` - const es = new OurEventSource(url, {fetch}) - - es.addEventListener('message', onMessage) - es.addEventListener('error', onError) - - // Should receive a message containing the number of listeners on the given ID - await onMessage.waitForCallCount(1) - expect(onMessage.lastCall.lastArg).toMatchObject({data: '1'}) - expect(es.readyState, 'readyState').toBe(OurEventSource.OPEN) // Open (connected) - - // Explicitly disconnect. Should normally reconnect within ~250ms (server sends retry: 250) - // but we'll close it before that happens - es.close() - expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) - expect(onMessage.callCount).toBe(1) - - // After 500 ms, there should still only be a single connect with this client ID - await new Promise((resolve) => setTimeout(resolve, 500)) - expect(await request(url).then((res) => res.json())).toMatchObject({clientIdConnects: 1}) - - // Wait another 500 ms, just to be sure there are no slow reconnects - await new Promise((resolve) => setTimeout(resolve, 500)) - expect(await request(url).then((res) => res.json())).toMatchObject({clientIdConnects: 1}) - }) - - test('will not reconnect after explicit `close()` in `onError`', async () => { - const request = fetch || globalThis.fetch - const onMessage = getCallCounter({name: 'onMessage'}) - const onError = getCallCounter({name: 'onError', onCall: () => es.close()}) - const clientId = Math.random().toString(36).slice(2) - const url = `${baseUrl}:${port}/identified?client-id=${clientId}&auto-close=true` - const es = new OurEventSource(url, {fetch}) - es.addEventListener('open', () => expect(es.readyState).toBe(OurEventSource.OPEN)) - es.addEventListener('message', onMessage) - es.addEventListener('error', onError) - - // Should receive a message containing the number of listeners on the given ID - await onMessage.waitForCallCount(1) - expect(onMessage.lastCall.lastArg, 'onMessage `event` argument').toMatchObject({data: '1'}) - - await onError.waitForCallCount(1) - expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) // `onDisconnect` called first, closes ES. - - // After 50 ms, we should still be in closing state - no reconnecting - expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) - - // After 500 ms, there should be no clients connected to the given ID - await new Promise((resolve) => setTimeout(resolve, 500)) - expect(await request(url).then((res) => res.json())).toMatchObject({clientIdConnects: 1}) - expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) - - // Wait another 500 ms, just to be sure there are no slow reconnects - await new Promise((resolve) => setTimeout(resolve, 500)) - expect(await request(url).then((res) => res.json())).toMatchObject({clientIdConnects: 1}) - expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) - }) - - test('will have correct ready state throughout lifecycle', async () => { - const onMessage = getCallCounter({name: 'onMessage'}) - const onOpen = getCallCounter({name: 'onOpen'}) - const onError = getCallCounter({name: 'onError'}) - const url = `${baseUrl}:${port}/slow-connect` - const es = new OurEventSource(url, {fetch}) - - es.addEventListener('message', onMessage) - es.addEventListener('open', onOpen) - es.addEventListener('error', onError) - - // Connecting - expect(es.readyState, 'readyState').toBe(OurEventSource.CONNECTING) - - // Connected - await onOpen.waitForCallCount(1) - expect(es.readyState, 'readyState').toBe(OurEventSource.OPEN) - - // Disconnected - await onError.waitForCallCount(1) - expect(es.readyState, 'readyState').toBe(OurEventSource.CONNECTING) - - // Closed - await es.close() - expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) - }) - - test('will close stream on HTTP 204', async () => { - const onMessage = getCallCounter({name: 'onMessage'}) - const onError = getCallCounter({name: 'onError'}) - const es = new OurEventSource(`${baseUrl}:${port}/end-after-one`, {fetch}) - - es.addEventListener('progress', onMessage) - es.addEventListener('error', onError) - - // First disconnect, then reconnect and given a 204 - await onError.waitForCallCount(2) - - // Only the first connect should have given a message - await onMessage.waitForCallCount(1) - - expect(onMessage.callCount).toBe(1) - expect(onMessage.lastCall.lastArg).toMatchObject({ - data: '100%', - type: 'progress', - lastEventId: 'prct-100', - }) - expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) // CLOSED - - await deferClose(es) - }) - - /** - * Note: Browser behavior varies in what they do on non-string/URL `url`: - * - Chrome and Safari `toString()`s the value, which is obviously wrong according to spec: - * > If urlRecord is failure, then throw a "SyntaxError" DOMException. - * - Firefox throws a `DOMException` with message `An invalid or illegal string was specified` - * (correct according to spec). - * - * We choose to go with the spec (eg mirrors Firefox behavior) if `DOMException` exists, - * otherwise we throw a `SyntaxError`. - */ - test('throws if `url` is not a string/url', () => { - const onMessage = getCallCounter({name: 'onMessage'}) - try { - // @ts-expect-error Should be a string or URL - const es = new OurEventSource(123, {fetch}) - es.addEventListener('message', onMessage) - es.close() - } catch (err) { - expect(err instanceof DOMException).toBe(true) - expect(err.message).toBe('An invalid or illegal string was specified') - return - } - - throw new Error('Expected invalid URL to throw') - }) - - test('can request cross-origin', async () => { - const hostUrl = new URL(`${baseUrl}:${port}/cors`) - const url = new URL(hostUrl) - url.hostname = url.hostname === 'localhost' ? '127.0.0.1' : 'localhost' - - const onMessage = getCallCounter({name: 'onMessage'}) - const es = new OurEventSource(url, {fetch}) - es.addEventListener('origin', onMessage) - - await onMessage.waitForCallCount(1) - expect(onMessage.callCount).toBe(1) - - const lastMessage = onMessage.lastCall.lastArg - expect(lastMessage).toMatchObject({type: 'origin'}) - - if (environment === 'browser') { - expect(lastMessage).toMatchObject({data: hostUrl.origin}) - } else { - expect(lastMessage).toMatchObject({data: ''}) - } - - await deferClose(es) - }) - - // Same-origin redirect tests - ;[301, 302, 307, 308].forEach((status) => { - test(`redirects: handles ${status} to same origin`, async () => { - const request = fetch || globalThis.fetch - const id = Math.random().toString(36).slice(2) - const onMessage = getCallCounter({name: 'onMessage'}) - const onOpen = getCallCounter({name: 'onOpen'}) - const origin = `${baseUrl}:${port}` - const url = `${origin}/redirect?status=${status}&id=${id}` - const es = new OurEventSource(url, { - withCredentials: true, - fetch(dstUrl, init) { - return request(dstUrl, { - ...init, - headers: {...init?.headers, authorization: 'Bearer foo'}, - }) - }, - }) - es.addEventListener('message', onMessage) - es.addEventListener('open', onOpen) - - await onMessage.waitForCallCount(1) - - // URL should be the original connected URL, even after redirect - expect(es.url).toBe(url) - - const firstMessage = onMessage.lastCall.lastArg - expect(firstMessage).toMatchObject({origin}) - expect(JSON.parse(firstMessage.data)).toMatchObject({ - origin, - from: url, - redirects: 1, - auth: 'Bearer foo', - }) - - // Reconnected and received another message - await onOpen.waitForCallCount(2) - await onMessage.waitForCallCount(2) - - const lastMessage = onMessage.lastCall.lastArg - expect(lastMessage).toMatchObject({origin}) - expect(JSON.parse(lastMessage.data)).toMatchObject({ - origin, - from: url, - redirects: 2, - auth: 'Bearer foo', - }) - - // Deno/Bun seems to set timeStamp to `0` πŸ€·β€β™‚οΈ - if (firstMessage.timeStamp > 0) { - expect(firstMessage.timeStamp).notToBe(lastMessage.timeStamp) - } - - await deferClose(es) - }) - }) - - // Cross-origin redirect tests - ;[301, 302, 307, 308].forEach((status) => { - test(`redirects: handles ${status} to different origin`, async () => { - const request = fetch || globalThis.fetch - const id = Math.random().toString(36).slice(2) - const onMessage = getCallCounter({name: 'onMessage'}) - const onOpen = getCallCounter({name: 'onOpen'}) - const origin = `${baseUrl}:${port}` - const corsOrigin = baseUrl.includes('localhost') - ? `http://127.0.0.1:${port}` - : `http://localhost:${port}` - const url = `${origin}/redirect?status=${status}&id=${id}&cors=true` - const es = new OurEventSource(url, { - withCredentials: true, - fetch(dstUrl, init) { - return request(dstUrl, { - ...init, - headers: {...init?.headers, authorization: 'Bearer foo'}, - }) - }, - }) - es.addEventListener('message', onMessage) - es.addEventListener('open', onOpen) - - await onMessage.waitForCallCount(1) - - // URL should be the original connected URL, even after redirect - expect(es.url).toBe(url) - - const firstMessage = onMessage.lastCall.lastArg - expect(firstMessage).toMatchObject({origin: corsOrigin}) - expect(JSON.parse(firstMessage.data)).toMatchObject({ - origin: corsOrigin, - from: url, - redirects: 1, - auth: null, // Authorization header should not follow cross-origin redirects - }) - - // Reconnected and received another message - await onOpen.waitForCallCount(2) - await onMessage.waitForCallCount(2) - - const lastMessage = onMessage.lastCall.lastArg - expect(lastMessage).toMatchObject({origin: corsOrigin}) - expect(JSON.parse(lastMessage.data)).toMatchObject({ - origin: corsOrigin, - from: url, - redirects: 2, - auth: null, // Authorization header should not follow cross-origin redirects - }) - - // Deno/Bun seems to set timeStamp to `0` πŸ€·β€β™‚οΈ - if (firstMessage.timeStamp > 0) { - expect(firstMessage.timeStamp).notToBe(lastMessage.timeStamp) - } - - await deferClose(es) - }) - }) - - browserTest( - 'can use the `withCredentials` option to control cookies being sent/not sent cross-origin', - async () => { - const request = fetch || globalThis.fetch - - // `withCredentials` only applies to cross-origin requests (per spec) - const corsOrigin = baseUrl.includes('localhost') - ? `http://127.0.0.1:${port}` - : `http://localhost:${port}` - - // With `withCredentials: true`, cookies should be sent - let onOpen = getCallCounter({name: 'onOpen'}) - let es = new OurEventSource(`${corsOrigin}/authed`, { - withCredentials: true, - fetch(url, init) { - expect(init).toMatchObject({credentials: 'include'}) - return request(url, init) - }, - }) - - es.addEventListener('open', onOpen) - await onOpen.waitForCallCount(1) - await deferClose(es) - - // With `withCredentials: false`, no cookies should be sent - es = new OurEventSource(`${corsOrigin}/authed`, { - withCredentials: false, - fetch(url, init) { - expect(init).toMatchObject({credentials: 'same-origin'}) - return request(url, init) - }, - }) - onOpen = getCallCounter({name: 'onOpen'}) - es.addEventListener('open', onOpen) - - await onOpen.waitForCallCount(1) - await deferClose(es) - - // With `withCredentials: undefined`, no cookies should be sent - es = new OurEventSource(`${corsOrigin}/authed`, {fetch}) - onOpen = getCallCounter({name: 'onOpen'}) - es.addEventListener('open', onOpen) - - await onOpen.waitForCallCount(1) - await deferClose(es) - }, - ) - - test('throws on `fetch()` that does not return web-stream', async () => { - const url = `${baseUrl}:${port}/` - - // @ts-expect-error `body` should be a ReadableStream - const faultyFetch: FetchLike = async () => ({ - body: 'not a stream', - redirected: false, - status: 200, - headers: new Headers({'content-type': 'text/event-stream'}), - url, - }) - - const onError = getCallCounter({name: 'onError'}) - const es = new OurEventSource(url, {fetch: faultyFetch}) - - es.addEventListener('error', onError) - await onError.waitForCallCount(1) - - expect(onError.lastCall.lastArg).toMatchObject({ - type: 'error', - defaultPrevented: false, - cancelable: false, - timeStamp: expect.any('number'), - message: 'Invalid response body, expected a web ReadableStream', - code: 200, - }) - await deferClose(es) - }) - - test('throws on `fetch()` that does not return a body', async () => { - const url = `${baseUrl}:${port}/` - - // @ts-expect-error `body` should be a ReadableStream - const faultyFetch: FetchLike = async () => ({ - redirected: false, - status: 200, - headers: new Headers({'content-type': 'text/event-stream'}), - url, - }) - - const onError = getCallCounter({name: 'onError'}) - const es = new OurEventSource(url, {fetch: faultyFetch}) - - es.addEventListener('error', onError) - await onError.waitForCallCount(1) - - expect(onError.lastCall.lastArg).toMatchObject({ - type: 'error', - defaultPrevented: false, - cancelable: false, - timeStamp: expect.any('number'), - message: 'Invalid response body, expected a web ReadableStream', - code: 200, - }) - await deferClose(es) - }) - - test('throws on `fetch()` yielding chunks that are not buffers', async () => { - const url = `${baseUrl}:${port}/` - - // @ts-expect-error `value` should be a buffer, which is all a `TextDecoder` accepts - const faultyFetch: FetchLike = async () => ({ - body: { - getReader: () => ({ - read: async () => ({done: false, value: 'not a buffer'}), - cancel: async () => {}, - }), - }, - redirected: false, - status: 200, - headers: new Headers({'content-type': 'text/event-stream'}), - url, - }) - - const onError = getCallCounter({name: 'onError'}) - const es = new OurEventSource(url, {fetch: faultyFetch}) - - es.addEventListener('error', onError) - await onError.waitForCallCount(1) - - // The message comes from the runtime's `TextDecoder`, and differs between environments - expect(onError.lastCall.lastArg).toMatchObject({type: 'error'}) - await deferClose(es) - }) - - test('[NON-SPEC] message event contains extended properties (failed connection)', async () => { - const onError = getCallCounter({name: 'onError'}) - const es = new OurEventSource(`${baseUrl}:9999/should-not-connect`, {fetch}) - - es.addEventListener('error', onError) - await onError.waitForCallCount(1) - - expect(onError.lastCall.lastArg).toMatchObject({ - type: 'error', - defaultPrevented: false, - cancelable: false, - timeStamp: expect.any('number'), - // Node, Deno, Bun, Chromium, Webkit, Firefox _ALL_ have different messages πŸ˜… - message: expect.stringMatching( - /fetch failed|failed to fetch|load failed|attempting to fetch|connection refused|unable to connect/i, - ), - code: undefined, - }) - await deferClose(es) - }) - - test('[NON-SPEC] message event contains extended properties (invalid http response)', async () => { - const onError = getCallCounter({name: 'onError'}) - const es = new OurEventSource(`${baseUrl}:${port}/end-after-one`, {fetch}) - - es.addEventListener('error', onError) - await onError.waitForCallCount(2) - - expect(onError.lastCall.lastArg).toMatchObject({ - type: 'error', - defaultPrevented: false, - cancelable: false, - timeStamp: expect.any('number'), - message: 'Server sent HTTP 204, not reconnecting', - code: 204, - }) - await deferClose(es) - }) - - test('[NON-SPEC] custom `maxBufferSize` fails connection on parser buffer overflow', async () => { - const url = `${baseUrl}:${port}/` - let fetchCount = 0 - - const faultyFetch: FetchLike = async () => { - fetchCount++ - return { - body: new ReadableStream({ - start(controller) { - const encoder = new TextEncoder() - controller.enqueue(encoder.encode('retry: 10\n')) - controller.enqueue(encoder.encode(`data: ${'x'.repeat(32)}\n`)) - controller.close() - }, - }), - redirected: false, - status: 200, - headers: new Headers({'content-type': 'text/event-stream'}), - url, - } - } - - const onError = getCallCounter({name: 'onError'}) - const es = new OurEventSource(url, {fetch: faultyFetch, maxBufferSize: 16}) - - es.addEventListener('error', onError) - await onError.waitForCallCount(1) - - expect(onError.lastCall.lastArg).toMatchObject({ - type: 'error', - defaultPrevented: false, - cancelable: false, - timeStamp: expect.any('number'), - message: expect.stringMatching(/Buffered data exceeded max buffer size/), - code: undefined, - }) - expect(es.readyState, 'readyState').toBe(OurEventSource.CLOSED) - - await new Promise((resolve) => setTimeout(resolve, 50)) - expect(fetchCount).toBe(1) - await deferClose(es) - }) - - test('[NON-SPEC] unrefs the reconnection timer where supported, so it does not keep the event loop alive', async () => { - // Browsers return numeric timer handles, so there is nothing to unref there. - // eslint-disable-next-line no-empty-function - const probe = setTimeout(() => {}, 0) - const supportsUnref = typeof probe === 'object' && probe !== null && 'unref' in probe - clearTimeout(probe) - if (!supportsUnref) { - return - } - - // `/counter` sends `retry: 50`, then disconnects after 3 messages - so the reconnection - // timer is scheduled with a 50ms delay. Capture those specific timers and track whether - // `unref()` was called on them. - const reconnectTimers: Array<{unrefCalled: boolean}> = [] - const realSetTimeout = globalThis.setTimeout - const setTimeoutStub: typeof globalThis.setTimeout = (callback, ms, ...rest) => { - const handle = realSetTimeout(callback, ms, ...rest) - if (ms === 50 && typeof handle === 'object' && handle !== null && 'unref' in handle) { - const record = {unrefCalled: false} - reconnectTimers.push(record) - const realUnref = handle.unref.bind(handle) - handle.unref = () => { - record.unrefCalled = true - return realUnref() - } - } - return handle - } - globalThis.setTimeout = setTimeoutStub - - try { - const onError = getCallCounter({name: 'onError'}) - const es = new OurEventSource(`${baseUrl}:${port}/counter`, {fetch}) - es.addEventListener('error', onError) - - // Wait for the disconnect, which schedules the reconnection timer. - await onError.waitForCallCount(1) - - expect(reconnectTimers.length > 0, 'a reconnection timer was scheduled').toBe(true) - expect( - reconnectTimers.every((timer) => timer.unrefCalled), - 'reconnection timer was unref-ed', - ).toBe(true) - - es.close() - } finally { - globalThis.setTimeout = realSetTimeout - } - }) - - test('has CONNECTING constant', async () => { - const es = new OurEventSource(`${baseUrl}:${port}/`) - expect(es.readyState).toBe(OurEventSource.CONNECTING) - expect(es.CONNECTING).toBe(0) - expect(OurEventSource.CONNECTING).toBe(0) - await deferClose(es) - }) - - test('has OPEN constant', async () => { - const onOpen = getCallCounter({name: 'onOpen'}) - const es = new OurEventSource(`${baseUrl}:${port}/`) - es.onopen = onOpen - await onOpen.waitForCallCount(1) - expect(es.readyState).toBe(OurEventSource.OPEN) - expect(es.OPEN).toBe(1) - expect(OurEventSource.OPEN).toBe(1) - await deferClose(es) - }) - - test('has CLOSED constant', async () => { - const es = new OurEventSource(`${baseUrl}:${port}/`) - es.close() - expect(es.readyState).toBe(OurEventSource.CLOSED) - expect(es.CLOSED).toBe(2) - expect(OurEventSource.CLOSED).toBe(2) - await deferClose(es) - }) - - test('has non-enumarable `eventsource.supports-fetch-override` symbol', async () => { - const supportsFetchOverride = Symbol.for('eventsource.supports-fetch-override') - expect(Object.getOwnPropertySymbols(OurEventSource).includes(supportsFetchOverride)).toBe(true) - expect(Object.keys(OurEventSource).includes('supports-fetch-override')).toBe(false) - expect(Symbol.for('eventsource.supports-fetch-override') in OurEventSource) - }) - - return runner -} diff --git a/test/waffletest/index.ts b/test/waffletest/index.ts deleted file mode 100644 index ce81da10..00000000 --- a/test/waffletest/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './runner.ts' -export * from './types.ts' diff --git a/test/waffletest/reporters/defaultReporter.ts b/test/waffletest/reporters/defaultReporter.ts deleted file mode 100644 index 452fb435..00000000 --- a/test/waffletest/reporters/defaultReporter.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* eslint-disable no-process-env, no-console */ -import type { - TestEndEvent, - TestFailEvent, - TestPassEvent, - TestReporter, - TestStartEvent, -} from '../types.ts' -import {getEndText, getFailText, getPassText, getStartText} from './helpers.ts' - -export const defaultReporter: Required> = { - onStart: reportStart, - onEnd: reportEnd, - onPass: reportPass, - onFail: reportFail, -} - -export function reportStart(event: TestStartEvent): void { - console.log(getStartText(event)) -} - -export function reportPass(event: TestPassEvent): void { - console.log(getPassText(event)) -} - -export function reportFail(event: TestFailEvent): void { - console.log(getFailText(event)) -} - -export function reportEnd(event: TestEndEvent): void { - console.log(getEndText(event)) -} diff --git a/test/waffletest/reporters/helpers.ts b/test/waffletest/reporters/helpers.ts deleted file mode 100644 index 9bf78b11..00000000 --- a/test/waffletest/reporters/helpers.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type {TestEndEvent, TestFailEvent, TestPassEvent, TestStartEvent} from '../types.ts' - -export function indent(str: string, spaces: number): string { - return str - .split('\n') - .map((line) => ' '.repeat(spaces) + line) - .join('\n') -} - -export function getStartText(event: TestStartEvent): string { - return `Running ${event.tests} tests…` -} - -export function getPassText(event: TestPassEvent): string { - return `βœ… ${event.title} (${event.duration}ms)` -} - -export function getFailText(event: TestFailEvent): string { - return `❌ ${event.title} (${event.duration}ms)\n${indent(event.error, 3)}` -} - -export function getEndText(event: TestEndEvent): string { - const {failures, passes, tests} = event - return `Ran ${tests} tests, ${passes} passed, ${failures} failed` -} diff --git a/test/waffletest/reporters/nodeReporter.ts b/test/waffletest/reporters/nodeReporter.ts deleted file mode 100644 index 682675a5..00000000 --- a/test/waffletest/reporters/nodeReporter.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* eslint-disable no-process-env, no-console */ -import {platform} from 'node:os' -import {isatty} from 'node:tty' - -import type { - TestEndEvent, - TestFailEvent, - TestPassEvent, - TestReporter, - TestStartEvent, -} from '../types.ts' -import {getEndText, getFailText, getPassText, getStartText} from './helpers.ts' - -const CAN_USE_COLORS = canUseColors() - -export const nodeReporter: Required> = { - onStart: reportStart, - onEnd: reportEnd, - onPass: reportPass, - onFail: reportFail, -} - -export function reportStart(event: TestStartEvent): void { - console.log(`${getStartText(event)}\n`) -} - -export function reportPass(event: TestPassEvent): void { - console.log(green(getPassText(event))) -} - -export function reportFail(event: TestFailEvent): void { - console.log(red(getFailText(event))) -} - -export function reportEnd(event: TestEndEvent): void { - console.log(`\n${getEndText(event)}`) -} - -function red(str: string): string { - return CAN_USE_COLORS ? `\x1b[31m${str}\x1b[39m` : str -} - -function green(str: string): string { - return CAN_USE_COLORS ? `\x1b[32m${str}\x1b[39m` : str -} - -function getEnv(envVar: string): string | undefined { - if (typeof process !== 'undefined' && 'env' in process && typeof process.env === 'object') { - return process.env[envVar] - } - - if (typeof globalThis.Deno !== 'undefined') { - return globalThis.Deno.env.get(envVar) - } - - throw new Error('Unable to find environment variables') -} - -function hasEnv(envVar: string): boolean { - return typeof getEnv(envVar) !== 'undefined' -} - -function canUseColors(): boolean { - const isWindows = platform() === 'win32' - const isDumbTerminal = getEnv('TERM') === 'dumb' - const isCompatibleTerminal = isatty(1) && getEnv('TERM') && !isDumbTerminal - const isCI = - hasEnv('CI') && (hasEnv('GITHUB_ACTIONS') || hasEnv('GITLAB_CI') || hasEnv('CIRCLECI')) - return (isWindows && !isDumbTerminal) || isCompatibleTerminal || isCI -} diff --git a/test/waffletest/runner.ts b/test/waffletest/runner.ts deleted file mode 100644 index d20db957..00000000 --- a/test/waffletest/runner.ts +++ /dev/null @@ -1,156 +0,0 @@ -import {ExpectationError} from '../helpers.ts' -import type { - TestEndEvent, - TestFailEvent, - TestFn, - TestPassEvent, - TestRunner, - TestRunnerOptions, - TestStartEvent, -} from './types.ts' - -interface TestDefinition { - title: string - timeout: number - action: TestFn - only?: boolean -} - -const DEFAULT_TIMEOUT = 15000 - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const noop = (_event: unknown) => { - /* intentional noop */ -} - -export function createRunner(options: TestRunnerOptions = {}): TestRunner { - const {onEvent = noop, onStart = noop, onPass = noop, onFail = noop, onEnd = noop} = options - const tests: TestDefinition[] = [] - - let hasOnlyTest = false - let running = false - let passes = 0 - let failures = 0 - let suiteStart = 0 - - function registerTest(title: string, fn: TestFn, timeout?: number, only?: boolean): void { - if (running) { - throw new Error('Cannot register a test while tests are running') - } - - if (only && !hasOnlyTest) { - // Clear the current tests - hasOnlyTest = true - while (tests.length > 0) { - tests.pop() - } - } - - if (!hasOnlyTest || only) { - tests.push({ - title, - timeout: timeout ?? DEFAULT_TIMEOUT, - action: fn, - only, - }) - } - } - - registerTest.skip = (...args: unknown[]): void => noop(args) - - registerTest.only = (title: string, fn: TestFn, timeout?: number): void => { - return registerTest(title, fn, timeout, true) - } - - async function runTests(): Promise { - running = true - suiteStart = Date.now() - - const start: TestStartEvent = { - event: 'start', - tests: tests.length, - } - - onStart(start) - onEvent(start) - - for (const test of tests) { - const startTime = Date.now() - try { - await Promise.race([test.action(), getTimeoutPromise(test.timeout)]) - passes++ - const pass: TestPassEvent = { - event: 'pass', - duration: Date.now() - startTime, - title: test.title, - } - onPass(pass) - onEvent(pass) - } catch (err: unknown) { - failures++ - - let error: string - if (err instanceof ExpectationError) { - error = err.message - if (typeof err.expected !== 'undefined' || typeof err.got !== 'undefined') { - error += `\n\nExpected: ${inspect(err.expected)}\nGot: ${inspect(err.got)}` - } - } else if (err instanceof Error) { - const stack = (err.stack || '').toString() - error = stack.includes(err.message) ? stack : `${err.message}\n\n${stack}` - } else { - error = `${err}` - } - - const fail: TestFailEvent = { - event: 'fail', - title: test.title, - duration: Date.now() - startTime, - error, - } - onFail(fail) - onEvent(fail) - } - } - - const end: TestEndEvent = { - event: 'end', - success: failures === 0, - failures, - passes, - tests: tests.length, - duration: Date.now() - suiteStart, - } - onEnd(end) - onEvent(end) - - running = false - - return end - } - - function getTestCount() { - return tests.length - } - - function isRunning() { - return running - } - - return { - isRunning, - getTestCount, - registerTest, - runTests, - } -} - -function getTimeoutPromise(ms: number) { - return new Promise((_resolve, reject) => { - setTimeout(reject, ms, new Error(`Test timed out after ${ms} ms`)) - }) -} - -function inspect(thing: unknown) { - return JSON.stringify(thing, null, 2) -} diff --git a/test/waffletest/types.ts b/test/waffletest/types.ts deleted file mode 100644 index e894a8ad..00000000 --- a/test/waffletest/types.ts +++ /dev/null @@ -1,58 +0,0 @@ -export type TestFn = () => void | Promise - -export interface TestReporter { - onEvent?: (event: TestEvent) => void - onStart?: (event: TestStartEvent) => void - onPass?: (event: TestPassEvent) => void - onFail?: (event: TestFailEvent) => void - onEnd?: (event: TestEndEvent) => void -} - -// Equal for now, but might extend -export type TestRunnerOptions = TestReporter - -export type RegisterTest = (( - title: string, - fn: TestFn, - timeout?: number, - only?: boolean, -) => void) & { - skip: (...args: unknown[]) => void - only: (title: string, fn: TestFn, timeout?: number) => void -} - -export interface TestRunner { - isRunning(): boolean - getTestCount(): number - registerTest: RegisterTest - runTests: () => Promise -} - -export type TestEvent = TestStartEvent | TestPassEvent | TestFailEvent | TestEndEvent - -export interface TestStartEvent { - event: 'start' - tests: number -} - -export interface TestPassEvent { - event: 'pass' - title: string - duration: number -} - -export interface TestFailEvent { - event: 'fail' - title: string - duration: number - error: string -} - -export interface TestEndEvent { - event: 'end' - success: boolean - tests: number - passes: number - failures: number - duration: number -} diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 00000000..cb4c2371 --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,16 @@ +{ + "extends": "./tsconfig.settings", + "include": ["./src", "./test", "./vitest.config.ts", "./vitest.*.config.ts"], + + // `type-compatible.ts` is checked by `tsconfig.types.json` instead, via `npm run test:types`. + // It imports the built `dist` output, so it can only be checked after a build - which is not + // something `npm run lint` should require. + "exclude": ["./test/type-compatible.ts"], + "compilerOptions": { + "noEmit": true, + + // The tests run in browsers as well as on the server, so they use DOM globals + // (`location`, `DOMException`, `MessageEvent`) that the library build must not rely on. + "lib": ["ES2023", "DOM"] + } +} diff --git a/vitest.browser.config.ts b/vitest.browser.config.ts new file mode 100644 index 00000000..ee09533f --- /dev/null +++ b/vitest.browser.config.ts @@ -0,0 +1,27 @@ +import {playwright} from '@vitest/browser-playwright' +import {defineConfig} from 'vitest/config' + +import {BROWSER_PORT} from './test/helpers/routes.ts' +import {ssePlugin} from './test/helpers/ssePlugin.ts' +import {sharedConfig} from './vitest.config.ts' + +export default defineConfig({ + plugins: [ssePlugin()], + test: { + ...sharedConfig, + // No `globalSetup`: the endpoints are served by the plugin above, not a standalone server. + provide: {port: BROWSER_PORT, suite: 'browser'}, + browser: { + enabled: true, + provider: playwright(), + // `127.0.0.1` rather than `localhost`, so that `localhost` is left over to serve as the + // second origin the CORS and cross-origin redirect tests need. + api: {host: '127.0.0.1', port: BROWSER_PORT}, + instances: [ + {browser: 'chromium', headless: true}, + {browser: 'firefox', headless: true}, + {browser: 'webkit', headless: true}, + ], + }, + }, +}) diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 00000000..caa3478f --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,34 @@ +import {defineConfig, type ViteUserConfig} from 'vitest/config' + +import {TEST_PORT} from './test/helpers/routes.ts' + +/** + * Starts the standalone test server. Used by every suite except the browser one, which serves + * the same routes from Vitest's own Vite server instead so that the test page and the endpoints + * share an origin (see `test/helpers/ssePlugin.ts`). + */ +export const standaloneServer = ['./test/helpers/globalSetup.ts'] + +/** + * Shared by every `vitest.*.config.ts`. The same suite - `test/client.test.ts` - runs under all + * of them; what differs is the runtime it executes in, and where the test endpoints are served + * from. Which config is running gets passed to the tests through `provide`, because several of + * these environments cannot reliably be told apart from the inside: happy-dom presents a + * `document`, and node, bun and deno all share this base config. + */ +export const sharedConfig = { + include: ['test/client.test.ts'], + // Several tests wait out multiple reconnects against a 250ms retry, so the 5s default is tight. + testTimeout: 15000, + reporters: process.env['GITHUB_ACTIONS'] ? ['default', 'github-actions'] : 'default', +} satisfies ViteUserConfig['test'] + +// Base config: node, and the same file run under `bun run vitest` and `deno run -A npm:vitest`. +export default defineConfig({ + test: { + ...sharedConfig, + environment: 'node', + globalSetup: standaloneServer, + provide: {port: TEST_PORT, suite: 'node'}, + }, +}) diff --git a/vitest.happy-dom.config.ts b/vitest.happy-dom.config.ts new file mode 100644 index 00000000..09a85cfd --- /dev/null +++ b/vitest.happy-dom.config.ts @@ -0,0 +1,27 @@ +import {defineConfig} from 'vitest/config' + +import {TEST_PORT} from './test/helpers/routes.ts' +import {sharedConfig, standaloneServer} from './vitest.config.ts' + +/** + * happy-dom presents a browser-like global environment on top of node, so the suite runs its + * browser-semantics tests here (CORS, cookies, `withCredentials`) while still talking to the + * standalone server. + * + * This suite is expected to fail for now: happy-dom's CORS handling does not yet line up with a + * real browser's, which is being worked through separately. It runs non-blocking in CI so the + * failures stay visible without gating the other environments. + */ +export default defineConfig({ + test: { + ...sharedConfig, + environment: 'happy-dom', + // happy-dom otherwise defaults `location` to `http://localhost:3000`, so give it the server's + // origin - that is the split the browser suite is written against. Note that happy-dom still + // reports these requests as cross-origin and blocks them, which is part of what is being + // worked through separately. + environmentOptions: {happyDom: {url: `http://127.0.0.1:${TEST_PORT}`}}, + globalSetup: standaloneServer, + provide: {port: TEST_PORT, suite: 'happy-dom'}, + }, +}) diff --git a/vitest.workerd.config.ts b/vitest.workerd.config.ts new file mode 100644 index 00000000..dcd04559 --- /dev/null +++ b/vitest.workerd.config.ts @@ -0,0 +1,33 @@ +import {cloudflareTest} from '@cloudflare/vitest-pool-workers' +import {defineConfig} from 'vitest/config' + +import {TEST_PORT} from './test/helpers/routes.ts' +import {sharedConfig, standaloneServer} from './vitest.config.ts' + +/** + * Runs the suite on workerd, the runtime behind Cloudflare Workers, through miniflare. Unlike + * the browser suites this is a server-side environment, so it neither enforces CORS nor keeps a + * cookie jar - it should behave like node. + * + * `nodejs_compat` is deliberately not enabled: the client has to work on bare workerd, and the + * flag would let the resolver match the `node` export condition. `compatibilityDate` is + * required, as workerd refuses to start without one. + * + * This suite is expected to fail for now, and runs non-blocking in CI so the failures stay + * visible without gating the other environments. + */ +export default defineConfig({ + plugins: [ + cloudflareTest({ + miniflare: { + compatibilityDate: '2026-06-01', + compatibilityFlags: [], + }, + }), + ], + test: { + ...sharedConfig, + globalSetup: standaloneServer, + provide: {port: TEST_PORT, suite: 'workerd'}, + }, +}) From e349a392af34b0af8b3578b2aa58e99990f6fd21 Mon Sep 17 00:00:00 2001 From: Espen Hovlandsdal Date: Thu, 13 Aug 2026 13:49:53 -0700 Subject: [PATCH 2/4] fix: set `MessageEvent` origin and lastEventId on runtimes that drop them --- .changeset/workerd-message-event-props.md | 7 ++++ .github/workflows/test.yml | 6 ++-- CONTRIBUTING.md | 2 +- src/EventSource.ts | 44 +++++++++++++++++++++-- 4 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 .changeset/workerd-message-event-props.md diff --git a/.changeset/workerd-message-event-props.md b/.changeset/workerd-message-event-props.md new file mode 100644 index 00000000..aa519352 --- /dev/null +++ b/.changeset/workerd-message-event-props.md @@ -0,0 +1,7 @@ +--- +'eventsource': patch +--- + +Fixed `origin` and `lastEventId` being empty on Cloudflare Workers + +workerd accepts `data` from the `MessageEvent` constructor's init dictionary but silently drops `origin` and `lastEventId`, so message events dispatched on Cloudflare Workers arrived with `origin` set to `null` and `lastEventId` to an empty string. Both are now assigned explicitly when the constructor did not take them, which leaves every other runtime untouched. diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 40587c0c..416e6937 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -108,9 +108,9 @@ jobs: # Known-failing environments. These run so the failures stay visible, but they do not gate the # rest of the matrix: happy-dom reports the test server's requests as cross-origin and blocks - # them, and workerd has its own set of issues (a null `MessageEvent.origin`, on-handlers firing - # twice, and handler ordering that differs from every other runtime). Both are being worked - # through separately - drop `continue-on-error` once they are green. + # them, and workerd's remaining failures all trace to cloudflare/workerd#6022, where its + # `EventTarget` dispatches `on` handler properties itself and so fires our `on*` handlers + # twice. Drop `continue-on-error` once they are green. testHappyDom: name: 'Test: happy-dom (allowed to fail)' timeout-minutes: 15 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7fd534f0..573616b2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,7 +35,7 @@ The suite in `test/client.test.ts` runs against a real HTTP server in every supp The browser tests need Playwright's browsers installed once, with `npx playwright install chromium firefox webkit`. -The happy-dom and workerd suites are expected to fail today and do not gate CI: happy-dom reports the test server's requests as cross-origin and blocks them, and workerd returns a null `MessageEvent.origin`, fires the `on*` handlers twice, and orders handlers differently from every other runtime. +The happy-dom and workerd suites are expected to fail today and do not gate CI. happy-dom reports the test server's requests as cross-origin and blocks them. workerd's remaining failures all come from [cloudflare/workerd#6022](https://github.com/cloudflare/workerd/issues/6022): its `EventTarget` dispatches `on` handler properties itself, on top of the `addEventListener` call our `on*` setters make, so those handlers fire twice, assigning `null` only removes one registration, and they fire ahead of listeners registered before them. The browser suite is the one place where the endpoints are not served by a standalone server. Vitest serves the test page from its own Vite server, so the endpoints are mounted onto that same server (`test/helpers/ssePlugin.ts`) to keep the page and the endpoints same-origin. Serving them separately would make every request cross-origin and silently change what the CORS, cookie and redirect tests actually assert. diff --git a/src/EventSource.ts b/src/EventSource.ts index b423d861..b878b43f 100644 --- a/src/EventSource.ts +++ b/src/EventSource.ts @@ -593,12 +593,27 @@ class EventSourceImpl extends EventTarget implements EventSource { this.#lastEventId = event.id } + const origin = this.#redirectUrl ? this.#redirectUrl.origin : this.#url.origin + const lastEventId = event.id || '' + const messageEvent = new MessageEvent(event.event || 'message', { data: event.data, - origin: this.#redirectUrl ? this.#redirectUrl.origin : this.#url.origin, - lastEventId: event.id || '', + origin, + lastEventId, }) + // workerd (Cloudflare Workers) accepts `data` but silently drops `origin` and `lastEventId` + // from the constructor init, yielding `null` and `''`. Both are plain own properties there + // rather than prototype getters, so they can be assigned after the fact. Elsewhere the + // constructor honours them and this is skipped, so no runtime pays for it unnecessarily. + if (messageEvent.origin !== origin) { + defineEventProperty(messageEvent, 'origin', origin) + } + + if (messageEvent.lastEventId !== lastEventId) { + defineEventProperty(messageEvent, 'lastEventId', lastEventId) + } + // The `onmessage` property only triggers on messages without an `event` field, or ones that // explicitly set `message`. This is handled automatically: the event is dispatched with type // `event.event || 'message'`, and `onmessage` is registered as a `message` event listener. @@ -754,3 +769,28 @@ function getBaseURL(): string | undefined { ? doc.baseURI : undefined } + +/** + * Assigns a `MessageEvent` property that the constructor's init dictionary was supposed to have + * set, for runtimes that ignore it. + * + * Defined rather than assigned because on the runtimes that do implement the property as a + * prototype getter, a plain assignment would throw in strict mode. `enumerable` and + * `configurable` mirror how a spec-compliant implementation exposes it. + * + * @param event - The message event to define the property on + * @param property - The property to define + * @param value - The value the constructor should have set + * @internal + */ +function defineEventProperty( + event: MessageEvent, + property: 'origin' | 'lastEventId', + value: string, +): void { + Object.defineProperty(event, property, { + value, + enumerable: true, + configurable: true, + }) +} From 87e5e6bfc9fea5e894652d6a06fb7330f45f20d8 Mon Sep 17 00:00:00 2001 From: Espen Hovlandsdal Date: Thu, 13 Aug 2026 13:54:42 -0700 Subject: [PATCH 3/4] docs: note partial Cloudflare Workers support --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 0c42e0fb..a78c1ace 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ npm install --save eventsource - Edge >= 84 - Deno >= 2 - Bun >= 1.1.23 +- Cloudflare Workers: [partial](#cloudflare-workers) Basically, any environment that supports: @@ -97,6 +98,22 @@ error TS2304: Cannot find name 'EventTarget'. error TS2304: Cannot find name 'MessageEvent'. ``` +### Cloudflare Workers + +Cloudflare Workers are supported, with one caveat: use `addEventListener()` rather than the `onmessage`, `onopen` and `onerror` properties. + +workerd's `EventTarget` dispatches `on` handler properties itself, on top of the listener this module registers, so a handler assigned that way is called twice per event - and assigning `null` only removes one of the two registrations, so it does not unsubscribe ([workerd#6022](https://github.com/cloudflare/workerd/issues/6022)). + +```js +// Called twice per message on Cloudflare Workers +eventSource.onmessage = (event) => console.log(event.data) + +// Use this instead +eventSource.addEventListener('message', (event) => console.log(event.data)) +``` + +workerd also drops `origin` and `lastEventId` from the `MessageEvent` constructor. This module assigns them itself, so both are correct on Workers today; the workaround goes away once [workerd#6995](https://github.com/cloudflare/workerd/pull/6995) lands. + ## Migrating from v1 / v2 See [MIGRATION.md](MIGRATION.md#v2-to-v3) for a detailed migration guide. From 739e89cfeae9d59673e783d8ede70f7330880a3c Mon Sep 17 00:00:00 2001 From: Espen Hovlandsdal Date: Thu, 13 Aug 2026 14:10:44 -0700 Subject: [PATCH 4/4] ci: stop known-failing suites from marking commits red --- .github/workflows/test.yml | 69 +++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 416e6937..ff712d8e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -106,31 +106,25 @@ jobs: - name: Run tests run: npm run test:bun - # Known-failing environments. These run so the failures stay visible, but they do not gate the - # rest of the matrix: happy-dom reports the test server's requests as cross-origin and blocks - # them, and workerd's remaining failures all trace to cloudflare/workerd#6022, where its - # `EventTarget` dispatches `on` handler properties itself and so fires our `on*` handlers - # twice. Drop `continue-on-error` once they are green. - testHappyDom: - name: 'Test: happy-dom (allowed to fail)' + # Known-failing environments, reported but never gating. + # + # happy-dom reports the test server's requests as cross-origin and blocks them. workerd's + # remaining failures all trace to cloudflare/workerd#6022, where its `EventTarget` dispatches + # `on` handler properties itself and so fires our `on*` handlers twice. + # + # `continue-on-error` is deliberately on the *step* rather than the job. At job level it keeps + # the overall run green but the job still reports a check run with a `failure` conclusion, which + # is what puts a red X on the commit. At step level the job itself succeeds, so the commit stays + # green, and the outcome is written to the run summary to keep the result visible. Move + # `continue-on-error` up to the job (or drop it) once these are expected to pass. + testKnownFailing: + name: 'Test: ${{ matrix.suite }} (informational)' timeout-minutes: 15 runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v7 - - uses: actions/setup-node@v7 - with: - node-version: 24 - - name: Install dependencies - run: npm ci - - name: Run tests - run: npm run test:happy-dom - - testWorkerd: - name: 'Test: Cloudflare Workers (allowed to fail)' - timeout-minutes: 15 - runs-on: ubuntu-latest - continue-on-error: true + strategy: + fail-fast: false + matrix: + suite: ['happy-dom', 'workerd'] steps: - uses: actions/checkout@v7 - uses: actions/setup-node@v7 @@ -139,4 +133,31 @@ jobs: - name: Install dependencies run: npm ci - name: Run tests - run: npm run test:workerd + id: tests + continue-on-error: true + run: | + # `pipefail` is not set in the default shell, so without it `tee` swallows the exit + # code and the step reports success no matter what the suite did. + set -o pipefail + npm run test:${{ matrix.suite }} 2>&1 | tee /tmp/${{ matrix.suite }}.log + - name: Summarise + if: always() + run: | + # Vitest forces colour on in CI, so the escape sequences have to come off before + # anything can be matched at the start of a line. + sed -E 's/\x1b\[[0-9;]*[mGKH]//g' '/tmp/${{ matrix.suite }}.log' > /tmp/plain.log + { + if [ '${{ steps.tests.outcome }}' = 'success' ]; then + echo '### ${{ matrix.suite }}: passing πŸŽ‰' + echo + echo 'This environment is no longer failing. It can be promoted to a gating job.' + else + echo '### ${{ matrix.suite }}: failing, as expected' + echo + echo '```' + grep -E '^ +(Tests|Test Files) ' /tmp/plain.log || true + echo '```' + echo + grep -E '^ FAIL ' /tmp/plain.log | sed 's/^ FAIL /- /' || true + fi + } | tee -a "$GITHUB_STEP_SUMMARY"