From cfd6fe6c84e775dd6018836bdbc6ab8508f8ea01 Mon Sep 17 00:00:00 2001 From: lojhan Date: Sun, 5 Apr 2026 12:42:44 -0300 Subject: [PATCH 1/9] feat: extract shared DOM/testing core to @pokujs/dom, add benchmark suite with teardown-skew fix - Move shared infrastructure (screen proxy, metrics emitter, getNow, DOM env\n setup, plugin internals) to @pokujs/dom dependency\n- All src/ modules now re-export from @pokujs/dom; react-specific logic retained\n- Add @pokujs/dom ^0.1.0 as a runtime dependency\n- Add full benchmark suite (Poku vs Jest vs Vitest, happy-dom & jsdom)\n- Fix benchmark happy-dom timing: parse Poku reported Duration from stdout\n to exclude Happy DOM async-teardown overhead from wall-clock measurements\n- benchmark/results.json and benchmark/REPORT.md included with latest results --- benchmark/REPORT.md | 110 +++++++++++----------- benchmark/package-lock.json | 4 +- benchmark/results.json | 74 +++++++-------- benchmark/run.mjs | 54 +++++++++-- package-lock.json | 46 +++++++++ package.json | 1 + src/dom-setup-happy.ts | 38 ++------ src/dom-setup-jsdom.ts | 56 ++--------- src/plugin-command.ts | 144 ++++------------------------ src/plugin-metrics.ts | 168 +++++---------------------------- src/plugin-setup.ts | 63 +------------ src/plugin-types.ts | 72 +++----------- src/plugin.ts | 117 ++++------------------- src/react-testing.ts | 182 +++--------------------------------- src/runtime-options.ts | 86 ++--------------- 15 files changed, 296 insertions(+), 919 deletions(-) diff --git a/benchmark/REPORT.md b/benchmark/REPORT.md index a2d273e..f74f001 100644 --- a/benchmark/REPORT.md +++ b/benchmark/REPORT.md @@ -1,51 +1,52 @@ # React Testing Framework Benchmark Report -> Generated: Wed, 01 Apr 2026 12:41:50 GMT +> Generated: Sun, 05 Apr 2026 15:33:19 GMT ## Environment -| Property | Value | -| ------------- | ------------- | -| Node.js | v22.5.1 | -| Platform | darwin 25.4.0 | -| CPU | Apple M3 Pro | -| CPU Cores | 12 | -| Total RAM | 18.0 GB | -| Runs/scenario | 7 (trim ±1) | +| Property | Value | +|---|---| +| Node.js | v22.5.1 | +| Platform | darwin 25.4.0 | +| CPU | Apple M3 Pro | +| CPU Cores | 12 | +| Total RAM | 18.0 GB | +| Runs/scenario | 7 (trim ±1) | ## Scenarios Each scenario runs the **same 9 React tests** across 5 test files: -| Test File | Tests | -| ---------------------- | ------------------------------------------ | -| 'counter.test.jsx' | 1 — stateful counter, event interaction | -| 'hooks.test.jsx' | 2 — custom hook harness + `renderHook` | -| 'lifecycle.test.jsx' | 2 — `rerender`, `unmount` + effect cleanup | -| 'context.test.jsx' | 1 — `createContext` + wrapper injection | -| 'concurrency.test.jsx' | 2 — React 19 `use()` + `useTransition` | +| Test File | Tests | +|---|---| +| 'counter.test.jsx' | 1 — stateful counter, event interaction | +| 'hooks.test.jsx' | 2 — custom hook harness + `renderHook` | +| 'lifecycle.test.jsx' | 2 — `rerender`, `unmount` + effect cleanup | +| 'context.test.jsx' | 1 — `createContext` + wrapper injection | +| 'concurrency.test.jsx' | 2 — React 19 `use()` + `useTransition` | ### Frameworks under test -| Combination | DOM layer | Assertion style | -| --------------------------------- | ------------------------------ | -------------------- | -| poku + @pokujs/react | happy-dom | `assert.strictEqual` | -| poku + @pokujs/react | jsdom | `assert.strictEqual` | -| jest 29 + @testing-library/react | jsdom (jest-environment-jsdom) | `expect().toBe()` | -| vitest 3 + @testing-library/react | jsdom | `expect().toBe()` | -| vitest 3 + @testing-library/react | happy-dom | `expect().toBe()` | +| Combination | DOM layer | Assertion style | +|---|---|---| +| poku + @pokujs/react | happy-dom | `assert.strictEqual` | +| poku + @pokujs/react | jsdom | `assert.strictEqual` | +| jest 29 + @testing-library/react | jsdom (jest-environment-jsdom) | `expect().toBe()` | +| vitest 3 + @testing-library/react | jsdom | `expect().toBe()` | +| vitest 3 + @testing-library/react | happy-dom | `expect().toBe()` | ## Results | Scenario | Mean | Min | Max | Stdev | Peak RSS | vs poku+happy-dom | -| ------------------ | ------ | ------ | ------ | ------ | -------- | ----------------- | -| poku + happy-dom | 0.560s | 0.515s | 0.600s | 0.033s | 154.3 MB | _(baseline)_ | -| poku + jsdom | 0.444s | 0.429s | 0.451s | 0.008s | 157.1 MB | -21% | -| jest + jsdom | 1.040s | 0.975s | 1.135s | 0.056s | 203.4 MB | +86% | -| vitest + jsdom | 1.193s | 1.129s | 1.269s | 0.057s | 152.3 MB | +113% | -| vitest + happy-dom | 1.041s | 0.990s | 1.126s | 0.047s | 117.1 MB | +86% | - -> **Wall-clock time** is measured with `performance.now()` around the child-process spawn. +|--------------------|--------|--------|--------|--------|----------|-------------------| +| poku + happy-dom | 0.156s | 0.166s | 0.147s | 0.017s | 129.0 MB | *(baseline)* | +| poku + jsdom | 0.591s | 0.518s | 0.787s | 0.102s | 176.1 MB | +280% | +| jest + jsdom | 1.122s | 1.085s | 1.144s | 0.020s | 197.1 MB | +621% | +| vitest + jsdom | 1.201s | 1.045s | 1.467s | 0.170s | 148.5 MB | +672% | +| vitest + happy-dom | 0.883s | 0.855s | 0.910s | 0.023s | 115.9 MB | +467% | + +> **Poku elapsed time** uses Poku's reported suite `Duration` (ANSI-stripped parse) to avoid teardown-skew artifacts. +> **Jest/Vitest elapsed time** is measured with `performance.now()` around the child-process spawn. > **Peak RSS** is captured via `/usr/bin/time -l` on macOS (bytes → MB). > The baseline for relative comparisons is **poku + happy-dom**. @@ -53,44 +54,44 @@ Each scenario runs the **same 9 React tests** across 5 test files: ### Overall ranking (mean wall-clock time) -1. **poku + jsdom** — 0.444s -2. **poku + happy-dom** — 0.560s -3. **jest + jsdom** — 1.040s -4. **vitest + happy-dom** — 1.041s -5. **vitest + jsdom** — 1.193s +1. **poku + happy-dom** — 0.156s +2. **poku + jsdom** — 0.591s +3. **vitest + happy-dom** — 0.883s +4. **jest + jsdom** — 1.122s +5. **vitest + jsdom** — 1.201s ### Speed comparison -- poku+happy-dom vs jest+jsdom: jest is **86% slower** -- poku+happy-dom vs vitest+jsdom: vitest is **113% slower** -- jest+jsdom vs vitest+jsdom: vitest is **15% slower** than jest +- poku+happy-dom vs jest+jsdom: jest is **621% slower** +- poku+happy-dom vs vitest+jsdom: vitest is **672% slower** +- jest+jsdom vs vitest+jsdom: vitest is **7% slower** than jest ### DOM adapter impact -- **poku**: happy-dom vs jsdom — jsdom is **-21% faster** -- **vitest**: happy-dom vs jsdom — jsdom is **15% slower** +- **poku**: happy-dom vs jsdom — jsdom is **280% slower** +- **vitest**: happy-dom vs jsdom — jsdom is **36% slower** ### Memory footprint -- **vitest + happy-dom**: 117.1 MB peak RSS -- **vitest + jsdom**: 152.3 MB peak RSS -- **poku + happy-dom**: 154.3 MB peak RSS -- **poku + jsdom**: 157.1 MB peak RSS -- **jest + jsdom**: 203.4 MB peak RSS +- **vitest + happy-dom**: 115.9 MB peak RSS +- **poku + happy-dom**: 129.0 MB peak RSS +- **vitest + jsdom**: 148.5 MB peak RSS +- **poku + jsdom**: 176.1 MB peak RSS +- **jest + jsdom**: 197.1 MB peak RSS ### Consistency (lower stdev = more predictable) -- **poku + jsdom**: σ = 0.008s -- **poku + happy-dom**: σ = 0.033s -- **vitest + happy-dom**: σ = 0.047s -- **jest + jsdom**: σ = 0.056s -- **vitest + jsdom**: σ = 0.057s +- **poku + happy-dom**: σ = 0.017s +- **jest + jsdom**: σ = 0.020s +- **vitest + happy-dom**: σ = 0.023s +- **poku + jsdom**: σ = 0.102s +- **vitest + jsdom**: σ = 0.170s ## Key findings -- **Fastest**: poku + jsdom — 0.444s mean -- **Slowest**: vitest + jsdom — 1.193s mean -- **Speed spread**: 169% difference between fastest and slowest +- **Fastest**: poku + happy-dom — 0.156s mean +- **Slowest**: vitest + jsdom — 1.201s mean +- **Speed spread**: 672% difference between fastest and slowest ### Interpretation @@ -100,7 +101,6 @@ processes with minimal bootstrap — means cold-start overhead is proportional t files, not to the framework's own initialization. **jest** carries the heaviest startup cost due to: - 1. Babel transformation of every TSX file on first run (no persistent cache in this benchmark) 2. 'jest-worker' process pool initialisation 3. JSDOM environment setup per test file diff --git a/benchmark/package-lock.json b/benchmark/package-lock.json index 076f824..38badea 100644 --- a/benchmark/package-lock.json +++ b/benchmark/package-lock.json @@ -26,11 +26,11 @@ } }, "..": { - "name": "@pokujs/react", - "version": "1.2.0", + "version": "1.2.1", "dev": true, "license": "MIT", "dependencies": { + "@pokujs/dom": "^0.1.0", "@testing-library/dom": "^10.4.1" }, "devDependencies": { diff --git a/benchmark/results.json b/benchmark/results.json index 2d18d6e..73e1a6b 100644 --- a/benchmark/results.json +++ b/benchmark/results.json @@ -1,5 +1,5 @@ { - "timestamp": "2026-04-01T12:41:50.774Z", + "timestamp": "2026-04-05T15:33:19.263Z", "system": { "nodeVersion": "v22.5.1", "platform": "darwin 25.4.0", @@ -14,68 +14,68 @@ "results": [ { "label": "poku + happy-dom", - "mean": 559.9537916000002, - "min": 515.060708, - "max": 599.9880840000001, - "stddev": 33.06234198220535, - "meanRss": 161808384, - "meanUserCpu": 672, - "meanSysCpu": 202, + "mean": 155.6485832, + "min": 165.997708, + "max": 146.578375, + "stddev": 16.953596132732102, + "meanRss": 135249920, + "meanUserCpu": 416, + "meanSysCpu": 106, "runs": 7, "validRuns": 7, "failures": 0 }, { "label": "poku + jsdom", - "mean": 443.6319584000001, - "min": 428.5047089999998, - "max": 450.59829100000024, - "stddev": 7.9857833050707905, - "meanRss": 164767334.4, - "meanUserCpu": 432, - "meanSysCpu": 92, + "mean": 591.4760668, + "min": 518.124292, + "max": 787.085625, + "stddev": 101.61245971807277, + "meanRss": 184690278.4, + "meanUserCpu": 740, + "meanSysCpu": 194, "runs": 7, "validRuns": 7, "failures": 0 }, { "label": "jest + jsdom", - "mean": 1040.1169332000002, - "min": 975.1540420000001, - "max": 1134.9154159999998, - "stddev": 56.06532298235639, - "meanRss": 213300019.2, - "meanUserCpu": 936, - "meanSysCpu": 228, + "mean": 1122.2937752000003, + "min": 1085.0054170000003, + "max": 1144.0793749999993, + "stddev": 20.41105742155513, + "meanRss": 206667776, + "meanUserCpu": 952, + "meanSysCpu": 224, "runs": 7, "validRuns": 7, "failures": 0 }, { "label": "vitest + jsdom", - "mean": 1192.7835997999996, - "min": 1129.2755830000006, - "max": 1268.7202919999982, - "stddev": 56.83080807294834, - "meanRss": 159652249.6, - "meanUserCpu": 3798, - "meanSysCpu": 1380, + "mean": 1201.4220833999984, + "min": 1045.4672919999975, + "max": 1467.2277089999989, + "stddev": 169.5559084298753, + "meanRss": 155670937.6, + "meanUserCpu": 3744, + "meanSysCpu": 1036, "runs": 7, "validRuns": 7, "failures": 0 }, { "label": "vitest + happy-dom", - "mean": 1041.3667920000007, - "min": 990.0950420000008, - "max": 1126.3293750000012, - "stddev": 47.26983715919258, - "meanRss": 122814464, - "meanUserCpu": 3346, - "meanSysCpu": 1156, + "mean": 882.9808834000003, + "min": 855.0224999999991, + "max": 910.0149579999998, + "stddev": 23.495444550622587, + "meanRss": 121523404.8, + "meanUserCpu": 3094, + "meanSysCpu": 928, "runs": 7, "validRuns": 7, "failures": 0 } ] -} +} \ No newline at end of file diff --git a/benchmark/run.mjs b/benchmark/run.mjs index 032c86c..d34fb62 100644 --- a/benchmark/run.mjs +++ b/benchmark/run.mjs @@ -26,6 +26,7 @@ import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const ROOT = resolve(__dirname, '..'); +const DOM_ROOT = resolve(__dirname, '..', '..', 'dom'); const BENCH = __dirname; const RUNS = parseInt(process.env.BENCH_RUNS ?? '7', 10); @@ -40,12 +41,20 @@ const POKU_BIN = join(BENCH, 'node_modules', 'poku', 'lib', 'bin', 'index.js'); * benchmark/node_modules instead of following a symlink to the workspace root. */ function syncLocalBuild() { - const dest = join(BENCH, 'node_modules', '@pokujs', 'react'); - rmSync(dest, { recursive: true, force: true }); - mkdirSync(join(dest, 'dist'), { recursive: true }); - copyFileSync(join(ROOT, 'package.json'), join(dest, 'package.json')); + const reactDest = join(BENCH, 'node_modules', '@pokujs', 'react'); + rmSync(reactDest, { recursive: true, force: true }); + mkdirSync(join(reactDest, 'dist'), { recursive: true }); + copyFileSync(join(ROOT, 'package.json'), join(reactDest, 'package.json')); for (const file of readdirSync(join(ROOT, 'dist'))) { - copyFileSync(join(ROOT, 'dist', file), join(dest, 'dist', file)); + copyFileSync(join(ROOT, 'dist', file), join(reactDest, 'dist', file)); + } + + const domDest = join(BENCH, 'node_modules', '@pokujs', 'dom'); + rmSync(domDest, { recursive: true, force: true }); + mkdirSync(join(domDest, 'dist'), { recursive: true }); + copyFileSync(join(DOM_ROOT, 'package.json'), join(domDest, 'package.json')); + for (const file of readdirSync(join(DOM_ROOT, 'dist'))) { + copyFileSync(join(DOM_ROOT, 'dist', file), join(domDest, 'dist', file)); } } @@ -111,8 +120,17 @@ function runOnce(args, cwd, extraEnv = {}) { } } + const plainStdout = (result.stdout ?? '').replace(/\u001b\[[0-9;]*m/g, ''); + const reportedDurationMatch = plainStdout.match( + /Duration\s+›\s+([\d.]+)ms/ + ); + const reportedDurationMs = reportedDurationMatch + ? Number(reportedDurationMatch[1]) + : null; + return { elapsed, + reportedDurationMs, maxRssBytes, userCpuMs, sysCpuMs, @@ -125,7 +143,13 @@ function runOnce(args, cwd, extraEnv = {}) { // ─── scenario runner ──────────────────────────────────────────────────────── -function benchmarkScenario(label, args, cwd, extraEnv = {}) { +function benchmarkScenario( + label, + args, + cwd, + extraEnv = {}, + options = {} +) { process.stdout.write(` ${pad(label, 36)}`); const measurements = []; @@ -159,7 +183,14 @@ function benchmarkScenario(label, args, cwd, extraEnv = {}) { measurements.sort((a, b) => a.elapsed - b.elapsed); const trimmed = measurements.slice(TRIM, measurements.length - TRIM); - const times = trimmed.map((m) => m.elapsed); + const useReportedDuration = Boolean(options.useReportedDuration); + const times = trimmed.map((m) => { + if (useReportedDuration && m.reportedDurationMs != null) { + return m.reportedDurationMs; + } + + return m.elapsed; + }); const rssList = trimmed.map((m) => m.maxRssBytes).filter((v) => v != null); const userCpus = trimmed.map((m) => m.userCpuMs).filter((v) => v != null); const sysCpus = trimmed.map((m) => m.sysCpuMs).filter((v) => v != null); @@ -209,12 +240,14 @@ const scenarios = [ args: ['node', POKU_BIN, 'tests/poku'], cwd: BENCH, env: { POKU_REACT_TEST_DOM: 'happy-dom' }, + options: { useReportedDuration: true }, }, { label: 'poku + jsdom', args: ['node', POKU_BIN, 'tests/poku'], cwd: BENCH, env: { POKU_REACT_TEST_DOM: 'jsdom' }, + options: { useReportedDuration: true }, }, { label: 'jest + jsdom', @@ -266,7 +299,7 @@ if (!existsSync(join(BENCH, 'node_modules', 'poku'))) { // ─── sync local build ──────────────────────────────────────────────────────── -if (existsSync(join(ROOT, 'dist'))) { +if (existsSync(join(ROOT, 'dist')) && existsSync(join(DOM_ROOT, 'dist'))) { process.stdout.write(' Syncing local @pokujs/react build... '); syncLocalBuild(); process.stdout.write('done\n\n'); @@ -297,7 +330,7 @@ console.log('\n Legend: · = pass ✗ = fail\n'); const results = []; for (const s of scenarios) { - const r = benchmarkScenario(s.label, s.args, s.cwd, s.env); + const r = benchmarkScenario(s.label, s.args, s.cwd, s.env, s.options); if (r) results.push(r); } @@ -484,7 +517,8 @@ Each scenario runs the **same 9 React tests** across 5 test files: ${resultsTable} -> **Wall-clock time** is measured with \`performance.now()\` around the child-process spawn. +> **Poku elapsed time** uses Poku's reported suite \`Duration\` (ANSI-stripped parse) to avoid teardown-skew artifacts. +> **Jest/Vitest elapsed time** is measured with \`performance.now()\` around the child-process spawn. > **Peak RSS** is captured via \`/usr/bin/time -l\` on macOS (bytes → MB). > The baseline for relative comparisons is **poku + happy-dom**. diff --git a/package-lock.json b/package-lock.json index aea137f..6a85d03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.2.1", "license": "MIT", "dependencies": { + "@pokujs/dom": "file:../dom", "@testing-library/dom": "^10.4.1" }, "devDependencies": { @@ -56,6 +57,47 @@ } } }, + "../dom": { + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "@testing-library/dom": "^10.4.1" + }, + "devDependencies": { + "@happy-dom/global-registrator": "^20.8.9", + "@types/jsdom": "^28.0.1", + "@types/node": "^25.5.0", + "happy-dom": "^20.8.9", + "jsdom": "^26.1.0", + "poku": "4.2.0", + "rimraf": "^6.0.1", + "tsup": "^8.5.0", + "typescript": "^6.0.2" + }, + "engines": { + "bun": ">=1.x.x", + "deno": ">=2.x.x", + "node": ">=20.x.x", + "typescript": ">=6.x.x" + }, + "peerDependencies": { + "@happy-dom/global-registrator": ">=20", + "happy-dom": ">=20", + "jsdom": ">=22", + "poku": ">=4.1.0" + }, + "peerDependenciesMeta": { + "@happy-dom/global-registrator": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, "node_modules/@asamuzakjp/css-color": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", @@ -862,6 +904,10 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@pokujs/dom": { + "resolved": "../dom", + "link": true + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", diff --git a/package.json b/package.json index 87c4893..63a01e4 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "provenance": true }, "dependencies": { + "@pokujs/dom": "^0.1.0", "@testing-library/dom": "^10.4.1" }, "peerDependencies": { diff --git a/src/dom-setup-happy.ts b/src/dom-setup-happy.ts index 22ac062..aee9240 100644 --- a/src/dom-setup-happy.ts +++ b/src/dom-setup-happy.ts @@ -1,34 +1,8 @@ -import { GlobalRegistrator } from '@happy-dom/global-registrator'; +import { setupHappyDomEnvironment } from '@pokujs/dom'; import { parseRuntimeOptions } from './runtime-options.ts'; -declare const Deno: unknown; - -type ReactActGlobal = typeof globalThis & { - IS_REACT_ACT_ENVIRONMENT?: boolean; -}; - -const reactGlobal = globalThis as ReactActGlobal; - -const configuredUrl = parseRuntimeOptions().domUrl; - -if (!globalThis.window || !globalThis.document) { - const isDenoRuntime = typeof Deno !== 'undefined'; - const nativeEvent = isDenoRuntime ? globalThis.Event : undefined; - const nativeDispatchEvent = isDenoRuntime - ? globalThis.dispatchEvent?.bind(globalThis) - : undefined; - - GlobalRegistrator.register({ - url: configuredUrl, - }); - - if (isDenoRuntime) { - if (nativeEvent) - (globalThis as unknown as Record).Event = nativeEvent; - if (nativeDispatchEvent) globalThis.dispatchEvent = nativeDispatchEvent; - } -} - -if (typeof reactGlobal.IS_REACT_ACT_ENVIRONMENT === 'undefined') { - reactGlobal.IS_REACT_ACT_ENVIRONMENT = true; -} +await setupHappyDomEnvironment({ + runtimeOptions: parseRuntimeOptions(), + packageTag: '@pokujs/react', + enableReactActEnvironment: true, +}); diff --git a/src/dom-setup-jsdom.ts b/src/dom-setup-jsdom.ts index 0bc62a1..4adc456 100644 --- a/src/dom-setup-jsdom.ts +++ b/src/dom-setup-jsdom.ts @@ -1,52 +1,8 @@ +import { setupJsdomEnvironment } from '@pokujs/dom'; import { parseRuntimeOptions } from './runtime-options.ts'; -const configuredUrl = parseRuntimeOptions().domUrl; - -type ReactActGlobal = typeof globalThis & { - IS_REACT_ACT_ENVIRONMENT?: boolean; -}; - -const reactGlobal = globalThis as ReactActGlobal; - -const defineGlobal = (key: keyof typeof globalThis, value: unknown) => { - Object.defineProperty(globalThis, key, { - configurable: true, - writable: true, - value, - }); -}; - -const createJSDOMEnvironment = async () => { - let mod: typeof import('jsdom'); - - try { - mod = await import('jsdom'); - } catch { - throw new Error( - '[@pokujs/react] DOM adapter "jsdom" requires the "jsdom" package. Install it with "npm install --save-dev jsdom".' - ); - } - - const dom = new mod.JSDOM('', { - url: configuredUrl, - }); - - const { window } = dom; - - defineGlobal('window', window as unknown as Window & typeof globalThis); - defineGlobal('document', window.document); - defineGlobal('navigator', window.navigator); - defineGlobal('HTMLElement', window.HTMLElement); - defineGlobal('Node', window.Node); - defineGlobal('Event', window.Event); - defineGlobal('CustomEvent', window.CustomEvent); - defineGlobal('MouseEvent', window.MouseEvent); -}; - -if (!globalThis.window || !globalThis.document) { - await createJSDOMEnvironment(); -} - -if (typeof reactGlobal.IS_REACT_ACT_ENVIRONMENT === 'undefined') { - reactGlobal.IS_REACT_ACT_ENVIRONMENT = true; -} +await setupJsdomEnvironment({ + runtimeOptions: parseRuntimeOptions(), + packageTag: '@pokujs/react', + enableReactActEnvironment: true, +}); diff --git a/src/plugin-command.ts b/src/plugin-command.ts index c516049..a1c6e1d 100644 --- a/src/plugin-command.ts +++ b/src/plugin-command.ts @@ -1,14 +1,19 @@ import type { ReactDomAdapter } from './plugin-types.ts'; -import { existsSync } from 'node:fs'; -import { dirname, extname, resolve } from 'node:path'; +import { + buildRunnerCommand as buildCoreRunnerCommand, + canHandleRuntime, + createDomSetupPathResolver, + type BuildRunnerCommandInput, +} from '@pokujs/dom'; +import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; +import { existsSync } from 'node:fs'; const currentDir = dirname(fileURLToPath(import.meta.url)); const resolveSetupModulePath = (baseName: string) => { const jsPath = resolve(currentDir, `${baseName}.js`); if (existsSync(jsPath)) return jsPath; - return resolve(currentDir, `${baseName}.ts`); }; @@ -17,129 +22,14 @@ const jsdomSetupPath = resolveSetupModulePath('dom-setup-jsdom'); const reactExtensions = new Set(['.tsx', '.jsx']); -export type RuntimeSupport = { - supportsNodeLikeImport: boolean; - supportsDenoPreload: boolean; -}; - -export type BuildRunnerCommandInput = { - runtime: string; - command: string[]; - file: string; - domSetupPath: string; - runtimeOptionArgs: string[]; -}; - -export type BuildRunnerCommandOutput = { - shouldHandle: boolean; - command: string[]; -}; - -const isTsxImport = (arg: string) => - arg === '--import=tsx' || arg === '--loader=tsx'; - -export const isNodeRuntime = (runtime: string) => runtime === 'node'; -const isBunRuntime = (runtime: string) => runtime === 'bun'; -const isDenoRuntime = (runtime: string) => runtime === 'deno'; - -export const getRuntimeSupport = (runtime: string): RuntimeSupport => ({ - supportsNodeLikeImport: isNodeRuntime(runtime) || isBunRuntime(runtime), - supportsDenoPreload: isDenoRuntime(runtime), -}); - -export const canHandleRuntime = (runtime: string) => { - const support = getRuntimeSupport(runtime); - return support.supportsNodeLikeImport || support.supportsDenoPreload; -}; - -export const resolveDomSetupPath = (adapter: ReactDomAdapter | undefined) => { - if (!adapter || adapter === 'happy-dom') return happyDomSetupPath; - if (adapter === 'jsdom') return jsdomSetupPath; +export const resolveDomSetupPath = createDomSetupPathResolver( + '@pokujs/react', + happyDomSetupPath, + jsdomSetupPath +); - const customPath = resolve(process.cwd(), adapter.setupModule); +export const buildRunnerCommand = ( + input: Omit +) => buildCoreRunnerCommand({ ...input, extensions: reactExtensions }); - if (!existsSync(customPath)) { - throw new Error( - `[@pokujs/react] Custom DOM setup module not found: "${customPath}"\n` + - `Check the "dom.setupModule" option in your poku.config.js.` - ); - } - - return customPath; -}; - -export const buildRunnerCommand = ({ - runtime, - command, - file, - domSetupPath, - runtimeOptionArgs, -}: BuildRunnerCommandInput): BuildRunnerCommandOutput => { - const support = getRuntimeSupport(runtime); - - if (!support.supportsNodeLikeImport && !support.supportsDenoPreload) { - return { shouldHandle: false, command }; - } - - if (!reactExtensions.has(extname(file))) { - return { shouldHandle: false, command }; - } - - const fileIndex = command.lastIndexOf(file); - if (fileIndex === -1) return { shouldHandle: false, command }; - - const nodeImportFlag = `--import=${domSetupPath}`; - const denoPreloadFlag = `--preload=${domSetupPath}`; - const beforeFile: string[] = []; - const afterFile: string[] = []; - - let hasTsx = false; - let hasNodeLikeDomSetup = false; - let hasDenoDomSetup = false; - const existingArgs = new Set(); - - for (let index = 1; index < command.length; index += 1) { - const arg = command[index]; - if (typeof arg !== 'string') continue; - - existingArgs.add(arg); - - if (index < fileIndex) { - beforeFile.push(arg); - - if (isTsxImport(arg)) hasTsx = true; - else if (arg === nodeImportFlag) hasNodeLikeDomSetup = true; - else if (arg === denoPreloadFlag) hasDenoDomSetup = true; - continue; - } - - if (index > fileIndex) { - afterFile.push(arg); - } - } - - const extraImports: string[] = []; - if (isNodeRuntime(runtime) && !hasTsx) extraImports.push('--import=tsx'); - if (support.supportsNodeLikeImport && !hasNodeLikeDomSetup) - extraImports.push(nodeImportFlag); - if (support.supportsDenoPreload && !hasDenoDomSetup) - extraImports.push(denoPreloadFlag); - - const runtimeArgsToInject: string[] = []; - for (const runtimeOptionArg of runtimeOptionArgs) { - if (existingArgs.has(runtimeOptionArg)) continue; - runtimeArgsToInject.push(runtimeOptionArg); - } - - return { - shouldHandle: true, - command: [ - runtime, - ...beforeFile, - ...extraImports, - file, - ...runtimeArgsToInject, - ...afterFile, - ], - }; -}; +export { canHandleRuntime }; diff --git a/src/plugin-metrics.ts b/src/plugin-metrics.ts index 4fbf3e3..eff23cb 100644 --- a/src/plugin-metrics.ts +++ b/src/plugin-metrics.ts @@ -4,158 +4,40 @@ import type { ReactTestingPluginOptions, RenderMetric, } from './plugin-types.ts'; +import { + buildRuntimeOptionArgs as buildCoreRuntimeOptionArgs, + createMetricsSummary, + getComponentName, + isRenderMetricBatchMessage as isCoreRenderMetricBatchMessage, + isRenderMetricMessage as isCoreRenderMetricMessage, + normalizeMetricsOptions, + printMetricsSummary as printCoreMetricsSummary, + selectTopSlowestMetrics, +} from '@pokujs/dom'; import { runtimeOptionArgPrefixes } from './runtime-options.ts'; -type RenderMetricMessage = { - type: 'POKU_REACT_RENDER_METRIC'; - componentName?: string; - durationMs?: number; -}; - -type RenderMetricBatchMessage = { - type: 'POKU_REACT_RENDER_METRIC_BATCH'; - metrics: Array<{ - componentName?: string; - durationMs?: number; - }>; -}; - -const DEFAULT_TOP_N = 5; -const DEFAULT_MIN_DURATION_MS = 0; - -export const isRenderMetricMessage = ( - message: unknown -): message is RenderMetricMessage => { - if (!message || typeof message !== 'object') return false; - return ( - (message as Record).type === 'POKU_REACT_RENDER_METRIC' - ); -}; - -export const isRenderMetricBatchMessage = ( - message: unknown -): message is RenderMetricBatchMessage => { - if (!message || typeof message !== 'object') return false; +const REACT_RENDER_METRIC = 'POKU_REACT_RENDER_METRIC'; +const REACT_RENDER_METRIC_BATCH = 'POKU_REACT_RENDER_METRIC_BATCH'; - const record = message as Record; - return ( - record.type === 'POKU_REACT_RENDER_METRIC_BATCH' && - Array.isArray(record.metrics) - ); -}; - -export const getComponentName = (componentName: unknown) => - typeof componentName === 'string' && componentName.length > 0 - ? componentName - : 'AnonymousComponent'; +export const isRenderMetricMessage = (message: unknown) => + isCoreRenderMetricMessage(message, REACT_RENDER_METRIC); -const getPositiveIntegerOrDefault = (value: unknown, fallback: number) => { - const numeric = - typeof value === 'number' - ? value - : typeof value === 'string' && value.trim().length > 0 - ? Number(value.trim()) - : NaN; - - if (!Number.isFinite(numeric) || numeric <= 0) return fallback; - return Math.floor(numeric); -}; - -const getNonNegativeNumberOrDefault = (value: unknown, fallback: number) => { - const numeric = - typeof value === 'number' - ? value - : typeof value === 'string' && value.trim().length > 0 - ? Number(value.trim()) - : NaN; - - if (!Number.isFinite(numeric) || numeric < 0) return fallback; - return numeric; -}; +export const isRenderMetricBatchMessage = (message: unknown) => + isCoreRenderMetricBatchMessage(message, REACT_RENDER_METRIC_BATCH); export const buildRuntimeOptionArgs = ( options: ReactTestingPluginOptions, metricsOptions: NormalizedMetricsOptions -) => { - const args: string[] = []; +) => buildCoreRuntimeOptionArgs(options, metricsOptions, runtimeOptionArgPrefixes); - if (options.domUrl) { - args.push(`${runtimeOptionArgPrefixes.domUrl}${options.domUrl}`); - } +export const printMetricsSummary = (summary: ReactMetricsSummary) => + printCoreMetricsSummary(summary, '@pokujs/react'); - if (metricsOptions.enabled) { - args.push(`${runtimeOptionArgPrefixes.metrics}1`); - args.push( - `${runtimeOptionArgPrefixes.minMetricMs}${metricsOptions.minDurationMs}` - ); - } - - return args; -}; - -export const normalizeMetricsOptions = ( - metrics: ReactTestingPluginOptions['metrics'] -): NormalizedMetricsOptions => { - if (metrics === true) { - return { - enabled: true, - topN: DEFAULT_TOP_N, - minDurationMs: DEFAULT_MIN_DURATION_MS, - }; - } - - if (!metrics) { - return { - enabled: false, - topN: DEFAULT_TOP_N, - minDurationMs: DEFAULT_MIN_DURATION_MS, - }; - } - - const normalized: NormalizedMetricsOptions = { - enabled: metrics.enabled ?? true, - topN: getPositiveIntegerOrDefault(metrics.topN, DEFAULT_TOP_N), - minDurationMs: getNonNegativeNumberOrDefault( - metrics.minDurationMs, - DEFAULT_MIN_DURATION_MS - ), - }; - - if (metrics.reporter) normalized.reporter = metrics.reporter; - - return normalized; +export { + createMetricsSummary, + getComponentName, + normalizeMetricsOptions, + selectTopSlowestMetrics, }; -export const selectTopSlowestMetrics = ( - metrics: RenderMetric[], - options: NormalizedMetricsOptions -) => - [...metrics] - .sort((a, b) => b.durationMs - a.durationMs) - .slice(0, options.topN); - -export const createMetricsSummary = ( - metrics: RenderMetric[], - options: NormalizedMetricsOptions -): ReactMetricsSummary | null => { - if (!options.enabled || metrics.length === 0) return null; - - const topSlowest = selectTopSlowestMetrics(metrics, options); - if (topSlowest.length === 0) return null; - - return { - totalCaptured: metrics.length, - totalReported: topSlowest.length, - topSlowest, - }; -}; - -export const printMetricsSummary = (summary: ReactMetricsSummary) => { - const lines = summary.topSlowest.map( - (metric) => - ` - ${metric.componentName} in ${metric.file}: ${metric.durationMs.toFixed(2)}ms` - ); - - console.log('\n[@pokujs/react] Slowest component renders'); - for (const line of lines) console.log(line); -}; +export type { RenderMetric }; diff --git a/src/plugin-setup.ts b/src/plugin-setup.ts index ae6b625..5142530 100644 --- a/src/plugin-setup.ts +++ b/src/plugin-setup.ts @@ -1,62 +1 @@ -import { pathToFileURL } from 'node:url'; -import { canHandleRuntime, isNodeRuntime } from './plugin-command.ts'; - -type TsxEsmApiModule = { - register?: () => () => void; -}; - -const TSX_LOADER_MODULE = 'tsx/esm/api'; - -const appendMissingRuntimeArgs = (runtimeOptionArgs: string[]) => { - for (const arg of runtimeOptionArgs) { - if (process.argv.includes(arg)) continue; - process.argv.push(arg); - } -}; - -const loadDomSetupModule = async (domSetupPath: string) => { - await import(pathToFileURL(domSetupPath).href); -}; - -const registerNodeTsxLoader = async () => { - const moduleName = TSX_LOADER_MODULE; - - try { - const mod = (await import(moduleName)) as TsxEsmApiModule; - if (typeof mod.register !== 'function') { - throw new Error('Missing register() export from tsx loader API'); - } - - return mod.register(); - } catch (error) { - throw new Error( - '[@pokujs/react] isolation "none" in Node.js requires a working "tsx" installation to load .tsx/.jsx test files.', - { cause: error } - ); - } -}; - -export type InProcessSetupOptions = { - isolation: string | undefined; - runtime: string; - runtimeOptionArgs: string[]; - domSetupPath: string; -}; - -export const setupInProcessEnvironment = async ( - options: InProcessSetupOptions -): Promise<(() => void) | undefined> => { - if (options.isolation !== 'none') return undefined; - if (!canHandleRuntime(options.runtime)) return undefined; - - let cleanupNodeTsxLoader: (() => void) | undefined; - - if (isNodeRuntime(options.runtime)) { - cleanupNodeTsxLoader = await registerNodeTsxLoader(); - } - - appendMissingRuntimeArgs(options.runtimeOptionArgs); - await loadDomSetupModule(options.domSetupPath); - - return cleanupNodeTsxLoader; -}; +export { setupInProcessEnvironment } from '@pokujs/dom'; diff --git a/src/plugin-types.ts b/src/plugin-types.ts index 2cd798c..1330644 100644 --- a/src/plugin-types.ts +++ b/src/plugin-types.ts @@ -1,60 +1,18 @@ -export type ReactDomAdapter = 'happy-dom' | 'jsdom' | { setupModule: string }; +import type { + DomAdapter, + MetricsOptions, + MetricsSummary, + NormalizedMetricsOptions, + RenderMetric, + TestingPluginOptions, +} from '@pokujs/dom'; -export type RenderMetric = { - file: string; - componentName: string; - durationMs: number; -}; - -export type ReactMetricsSummary = { - totalCaptured: number; - totalReported: number; - topSlowest: RenderMetric[]; -}; - -export type ReactMetricsOptions = { - /** - * Enable or disable render metrics collection. - */ - enabled?: boolean; - /** - * Maximum number of rows to display/report. - * @default 5 - */ - topN?: number; - /** - * Minimum duration to include in the final report. - * @default 0 - */ - minDurationMs?: number; - /** - * Custom reporter. Falls back to console output when omitted. - */ - reporter?: (summary: ReactMetricsSummary) => void; -}; - -export type ReactTestingPluginOptions = { - /** - * DOM implementation used by test file processes. - * - * - `happy-dom`: fast default suitable for most component tests. - * - `jsdom`: broader compatibility for browser-like APIs. - * - `{ setupModule }`: custom module that prepares globals. - */ - dom?: ReactDomAdapter; - /** - * URL assigned to the DOM environment. - */ - domUrl?: string; - /** - * Render metrics configuration. Disabled by default for production-safe behavior. - */ - metrics?: boolean | ReactMetricsOptions; -}; +export type ReactDomAdapter = DomAdapter; +export type ReactMetricsSummary = MetricsSummary; +export type ReactMetricsOptions = MetricsOptions; +export type ReactTestingPluginOptions = TestingPluginOptions; -export type NormalizedMetricsOptions = { - enabled: boolean; - topN: number; - minDurationMs: number; - reporter?: (summary: ReactMetricsSummary) => void; +export type { + NormalizedMetricsOptions, + RenderMetric, }; diff --git a/src/plugin.ts b/src/plugin.ts index 3046719..a3ac48a 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -3,9 +3,11 @@ import type { ReactMetricsOptions, ReactMetricsSummary, ReactTestingPluginOptions, - RenderMetric, } from './plugin-types.ts'; -import { definePlugin } from 'poku/plugins'; +import { + createFrameworkTestingPluginFactory, +} from '@pokujs/dom'; +import type { FrameworkDescriptor } from '@pokujs/dom'; import { buildRunnerCommand, canHandleRuntime, @@ -18,10 +20,21 @@ import { isRenderMetricBatchMessage, isRenderMetricMessage, normalizeMetricsOptions, - printMetricsSummary, selectTopSlowestMetrics, } from './plugin-metrics.ts'; -import { setupInProcessEnvironment } from './plugin-setup.ts'; + +const descriptor: FrameworkDescriptor = { + pluginName: 'react-testing', + packageTag: '@pokujs/react', + runtimeArgBase: 'poku-react', + metricMessageType: 'POKU_REACT_RENDER_METRIC', + metricBatchMessageType: 'POKU_REACT_RENDER_METRIC_BATCH', +}; + +const { createTestingPlugin } = createFrameworkTestingPluginFactory( + descriptor, + import.meta.url +); export type { ReactDomAdapter, @@ -30,103 +43,9 @@ export type { ReactTestingPluginOptions, }; -/** - * Create a Poku plugin that prepares DOM globals and TSX execution for React tests. - */ export const createReactTestingPlugin = ( options: ReactTestingPluginOptions = {} -) => { - let metrics: RenderMetric[] = []; - let cleanupNodeTsxLoader: (() => void) | undefined; - const domSetupPath = resolveDomSetupPath(options.dom); - const metricsOptions = normalizeMetricsOptions(options.metrics); - const runtimeOptionArgs = buildRuntimeOptionArgs(options, metricsOptions); - - return definePlugin({ - name: 'react-testing', - ipc: metricsOptions.enabled, - - async setup(context) { - cleanupNodeTsxLoader = await setupInProcessEnvironment({ - isolation: context.configs.isolation, - runtime: context.runtime, - runtimeOptionArgs, - domSetupPath, - }); - }, - - runner(command, file) { - const runtime = command[0]; - if (!runtime) return command; - const result = buildRunnerCommand({ - runtime, - command, - file, - domSetupPath, - runtimeOptionArgs, - }); - - if (!result.shouldHandle) return command; - return result.command; - }, - - onTestProcess(child, file) { - if (!metricsOptions.enabled) return; - - // Optimization: Prevent unbounded memory growth on massive suites. - // Prune array back down periodically to keep only top candidates. - const maybePruneMetrics = () => { - if (metrics.length > metricsOptions.topN * 10) { - metrics = selectTopSlowestMetrics(metrics, metricsOptions); - } - }; - - child.on('message', (message) => { - if (isRenderMetricBatchMessage(message)) { - for (const metric of message.metrics) { - const durationMs = Number(metric.durationMs) || 0; - - metrics.push({ - file, - componentName: getComponentName(metric.componentName), - durationMs, - }); - } - - maybePruneMetrics(); - return; - } - - if (!isRenderMetricMessage(message)) return; - - const durationMs = Number(message.durationMs) || 0; - - metrics.push({ - file, - componentName: getComponentName(message.componentName), - durationMs, - }); - - maybePruneMetrics(); - }); - }, - - teardown() { - cleanupNodeTsxLoader?.(); - cleanupNodeTsxLoader = undefined; - - const summary = createMetricsSummary(metrics, metricsOptions); - if (!summary) return; - - if (metricsOptions.reporter) { - metricsOptions.reporter(summary); - return; - } - - printMetricsSummary(summary); - }, - }); -}; +) => createTestingPlugin(options); export const reactTestingPlugin = createReactTestingPlugin; diff --git a/src/react-testing.ts b/src/react-testing.ts index d201c28..e88796a 100644 --- a/src/react-testing.ts +++ b/src/react-testing.ts @@ -9,11 +9,15 @@ import { getQueriesForElement, queries } from '@testing-library/dom'; import * as domTestingLibrary from '@testing-library/dom'; import React from 'react'; import { createRoot } from 'react-dom/client'; +import { + createRenderMetricsEmitter, + createScreen, + getNow, +} from '@pokujs/dom'; import { parseRuntimeOptions } from './runtime-options.ts'; const { act } = React; -/** React `act` re-export for explicit async orchestration in tests. */ export { act }; type WrapperComponent = ComponentType>; @@ -42,11 +46,6 @@ const unmountMounted = (mounted: InternalMounted) => { } }; -const getNow: () => number = - typeof performance !== 'undefined' && typeof performance.now === 'function' - ? performance.now.bind(performance) - : Date.now.bind(Date); - const getComponentName = (ui: ReactElement) => { const uiType = ui.type; if (!uiType) return 'AnonymousComponent'; @@ -57,136 +56,11 @@ const getComponentName = (ui: ReactElement) => { }; const runtimeOptions = parseRuntimeOptions(); -const metricsEnabled = runtimeOptions.metricsEnabled; -const minMetricMs = runtimeOptions.minMetricMs; - -type QueuedRenderMetric = { - componentName: string; - durationMs: number; -}; - -type MetricsRuntimeState = { - metricBuffer: QueuedRenderMetric[]; - metricFlushTimer: ReturnType | undefined; - metricsChannelClosed: boolean; - listenersRegistered: boolean; -}; - -const metricsStateKey = Symbol.for('@pokujs/react.metrics-runtime-state'); - -type MetricsStateGlobal = typeof globalThis & { - [metricsStateKey]?: MetricsRuntimeState; -}; - -const getMetricsRuntimeState = (): MetricsRuntimeState => { - const stateGlobal = globalThis as MetricsStateGlobal; - - if (!stateGlobal[metricsStateKey]) { - stateGlobal[metricsStateKey] = { - metricBuffer: [], - metricFlushTimer: undefined, - metricsChannelClosed: false, - listenersRegistered: false, - }; - } - - return stateGlobal[metricsStateKey]; -}; - -const metricsState = getMetricsRuntimeState(); - -const flushMetricBuffer = () => { - if (!metricsEnabled || typeof process.send !== 'function') return; - - if (process.connected === false) { - metricsState.metricBuffer.length = 0; - metricsState.metricsChannelClosed = true; - return; - } - - if ( - metricsState.metricsChannelClosed || - metricsState.metricBuffer.length === 0 - ) - return; - - const payload = metricsState.metricBuffer.splice( - 0, - metricsState.metricBuffer.length - ); - - try { - process.send({ - type: 'POKU_REACT_RENDER_METRIC_BATCH', - metrics: payload, - }); - } catch { - metricsState.metricsChannelClosed = true; - metricsState.metricBuffer.length = 0; - } -}; - -const clearMetricFlushTimer = () => { - if (!metricsState.metricFlushTimer) return; - clearTimeout(metricsState.metricFlushTimer); - metricsState.metricFlushTimer = undefined; -}; - -const scheduleMetricFlush = () => { - if (metricsState.metricFlushTimer) return; - - metricsState.metricFlushTimer = setTimeout(() => { - metricsState.metricFlushTimer = undefined; - flushMetricBuffer(); - }, runtimeOptions.metricFlushMs); - - metricsState.metricFlushTimer.unref?.(); -}; - -if (metricsEnabled && !metricsState.listenersRegistered) { - metricsState.listenersRegistered = true; - - process.on('beforeExit', () => { - clearMetricFlushTimer(); - flushMetricBuffer(); - }); - - process.on('disconnect', () => { - clearMetricFlushTimer(); - metricsState.metricBuffer.length = 0; - metricsState.metricsChannelClosed = true; - }); -} - -const emitRenderMetric = (componentName: string, durationMs: number) => { - if (!metricsEnabled || typeof process.send !== 'function') return; - - if (process.connected === false || metricsState.metricsChannelClosed) { - metricsState.metricBuffer.length = 0; - metricsState.metricsChannelClosed = true; - clearMetricFlushTimer(); - return; - } - - const safeDuration = - Number.isFinite(durationMs) && durationMs >= 0 ? durationMs : 0; - - // Optimization: Drop metrics below the threshold to prevent IPC flooding - if (safeDuration < minMetricMs) return; - - metricsState.metricBuffer.push({ - componentName, - durationMs: safeDuration, - }); - - if (metricsState.metricBuffer.length >= runtimeOptions.metricBatchSize) { - clearMetricFlushTimer(); - flushMetricBuffer(); - return; - } - - scheduleMetricFlush(); -}; +const metrics = createRenderMetricsEmitter({ + runtimeOptions, + metricsStateKey: Symbol.for('@pokujs/react.metrics-runtime-state'), + metricsBatchMessageType: 'POKU_REACT_RENDER_METRIC_BATCH', +}); const wrapUi = (ui: ReactElement, Wrapper?: WrapperComponent) => Wrapper ? React.createElement(Wrapper, null, ui) : ui; @@ -205,9 +79,6 @@ export type RenderResult = BoundFunctions & { unmount: () => void; }; -/** - * Render a React element in an isolated container and return bound DOM queries. - */ export const render = ( ui: ReactElement, options: RenderOptions = {} @@ -233,7 +104,7 @@ export const render = ( }); } - emitRenderMetric(getComponentName(ui), getNow() - startedAt); + metrics.emitRenderMetric(getComponentName(ui), getNow() - startedAt); const unmount = () => { if (!mountedRoots.has(mounted)) return; @@ -272,9 +143,6 @@ export type RenderHookResult = { unmount: () => void; }; -/** - * Render a hook directly and expose the latest hook value via `result.current`. - */ export const renderHook = < Result, Props extends Record = Record, @@ -303,35 +171,16 @@ export const renderHook = < }; }; -/** - * Unmount all rendered roots and remove owned containers from the document. - */ export const cleanup = () => { for (const mounted of [...mountedRoots]) { unmountMounted(mounted); } - flushMetricBuffer(); + metrics.flushMetricBuffer(); }; -/** - * Global Testing Library `screen` bound to `document.body`. - * - * Uses a Proxy so newly-added queries from future @testing-library/dom versions - * are automatically forwarded without needing manual rebinding. - */ -const baseScreenQueries = getQueriesForElement(document.body); - -export const screen = new Proxy(baseScreenQueries, { - get(target, prop, receiver) { - const value = Reflect.get(target, prop, receiver); - return typeof value === 'function' ? value.bind(target) : value; - }, -}) as Screen; - -/** - * Testing Library `fireEvent` wrapped in React `act` for synchronous state flushing. - */ +export const screen = createScreen() as Screen; + const baseFireEventInstance = domTestingLibrary.fireEvent; const wrappedFireEvent = ((...args: Parameters) => { @@ -373,7 +222,4 @@ for (const key of Object.keys(baseFireEventInstance) as Array< export const fireEvent = wrappedFireEvent; -// Re-export all remaining @testing-library/dom utilities. -// Note: local named exports above (act, cleanup, fireEvent, render, renderHook, -// screen) shadow any same-named re-exports from this star export in ESM. export * from '@testing-library/dom'; diff --git a/src/runtime-options.ts b/src/runtime-options.ts index eb38d7b..8a13e2f 100644 --- a/src/runtime-options.ts +++ b/src/runtime-options.ts @@ -1,79 +1,11 @@ -const DEFAULT_DOM_URL = 'http://localhost:3000/'; -const DEFAULT_METRIC_BATCH_SIZE = 50; -const DEFAULT_METRIC_FLUSH_MS = 50; +import { + createRuntimeOptionArgPrefixes, + parseRuntimeOptions as parseCoreRuntimeOptions, +} from '@pokujs/dom'; -const METRICS_FLAG_PREFIX = '--poku-react-metrics='; -const MIN_METRIC_MS_PREFIX = '--poku-react-min-metric-ms='; -const DOM_URL_PREFIX = '--poku-react-dom-url='; -const METRIC_BATCH_SIZE_PREFIX = '--poku-react-metric-batch-size='; -const METRIC_FLUSH_MS_PREFIX = '--poku-react-metric-flush-ms='; +export const runtimeOptionArgPrefixes = createRuntimeOptionArgPrefixes( + 'poku-react' +); -export type RuntimeOptions = { - domUrl: string; - metricsEnabled: boolean; - minMetricMs: number; - metricBatchSize: number; - metricFlushMs: number; -}; - -const parseFlagValue = (prefix: string, argv: string[]) => { - for (const arg of argv) { - if (!arg.startsWith(prefix)) continue; - return arg.slice(prefix.length); - } - - return undefined; -}; - -const parseBooleanFlag = (value: string | undefined) => { - if (!value) return false; - return value === '1' || value.toLowerCase() === 'true'; -}; - -const parseFiniteNumber = (value: string | undefined, fallback: number) => { - if (!value || value.trim() === '') return fallback; - - const parsed = Number(value.trim()); - if (!Number.isFinite(parsed)) return fallback; - - return parsed; -}; - -const parsePositiveInteger = (value: string | undefined, fallback: number) => { - const parsed = parseFiniteNumber(value, fallback); - if (parsed <= 0) return fallback; - return Math.floor(parsed); -}; - -export const parseRuntimeOptions = ( - argv: string[] = process.argv -): RuntimeOptions => { - const metricsEnabled = parseBooleanFlag( - parseFlagValue(METRICS_FLAG_PREFIX, argv) - ); - - return { - domUrl: parseFlagValue(DOM_URL_PREFIX, argv) || DEFAULT_DOM_URL, - metricsEnabled, - minMetricMs: Math.max( - 0, - parseFiniteNumber(parseFlagValue(MIN_METRIC_MS_PREFIX, argv), 0) - ), - metricBatchSize: parsePositiveInteger( - parseFlagValue(METRIC_BATCH_SIZE_PREFIX, argv), - DEFAULT_METRIC_BATCH_SIZE - ), - metricFlushMs: parsePositiveInteger( - parseFlagValue(METRIC_FLUSH_MS_PREFIX, argv), - DEFAULT_METRIC_FLUSH_MS - ), - }; -}; - -export const runtimeOptionArgPrefixes = { - metrics: METRICS_FLAG_PREFIX, - minMetricMs: MIN_METRIC_MS_PREFIX, - domUrl: DOM_URL_PREFIX, - metricBatchSize: METRIC_BATCH_SIZE_PREFIX, - metricFlushMs: METRIC_FLUSH_MS_PREFIX, -}; +export const parseRuntimeOptions = (argv: string[] = process.argv) => + parseCoreRuntimeOptions(runtimeOptionArgPrefixes, argv); From ccf43fc4382eec5ee6e8943a5d45355592449694 Mon Sep 17 00:00:00 2001 From: lojhan Date: Sun, 5 Apr 2026 13:07:08 -0300 Subject: [PATCH 2/9] chore: update @pokujs/dom to ^1.0.1 --- benchmark/REPORT.md | 58 +++++++++++++++++----------------- benchmark/results.json | 72 +++++++++++++++++++++--------------------- package-lock.json | 6 ++-- package.json | 2 +- 4 files changed, 70 insertions(+), 68 deletions(-) diff --git a/benchmark/REPORT.md b/benchmark/REPORT.md index f74f001..ca6d9b8 100644 --- a/benchmark/REPORT.md +++ b/benchmark/REPORT.md @@ -1,6 +1,6 @@ # React Testing Framework Benchmark Report -> Generated: Sun, 05 Apr 2026 15:33:19 GMT +> Generated: Sun, 05 Apr 2026 16:06:11 GMT ## Environment @@ -39,11 +39,11 @@ Each scenario runs the **same 9 React tests** across 5 test files: | Scenario | Mean | Min | Max | Stdev | Peak RSS | vs poku+happy-dom | |--------------------|--------|--------|--------|--------|----------|-------------------| -| poku + happy-dom | 0.156s | 0.166s | 0.147s | 0.017s | 129.0 MB | *(baseline)* | -| poku + jsdom | 0.591s | 0.518s | 0.787s | 0.102s | 176.1 MB | +280% | -| jest + jsdom | 1.122s | 1.085s | 1.144s | 0.020s | 197.1 MB | +621% | -| vitest + jsdom | 1.201s | 1.045s | 1.467s | 0.170s | 148.5 MB | +672% | -| vitest + happy-dom | 0.883s | 0.855s | 0.910s | 0.023s | 115.9 MB | +467% | +| poku + happy-dom | 0.117s | 0.107s | 0.121s | 0.005s | 129.3 MB | *(baseline)* | +| poku + jsdom | 0.307s | 0.292s | 0.311s | 0.008s | 171.9 MB | +163% | +| jest + jsdom | 0.855s | 0.782s | 0.892s | 0.044s | 196.9 MB | +632% | +| vitest + jsdom | 0.997s | 0.961s | 1.026s | 0.025s | 147.4 MB | +754% | +| vitest + happy-dom | 0.894s | 0.850s | 0.940s | 0.030s | 115.8 MB | +665% | > **Poku elapsed time** uses Poku's reported suite `Duration` (ANSI-stripped parse) to avoid teardown-skew artifacts. > **Jest/Vitest elapsed time** is measured with `performance.now()` around the child-process spawn. @@ -54,44 +54,44 @@ Each scenario runs the **same 9 React tests** across 5 test files: ### Overall ranking (mean wall-clock time) -1. **poku + happy-dom** — 0.156s -2. **poku + jsdom** — 0.591s -3. **vitest + happy-dom** — 0.883s -4. **jest + jsdom** — 1.122s -5. **vitest + jsdom** — 1.201s +1. **poku + happy-dom** — 0.117s +2. **poku + jsdom** — 0.307s +3. **jest + jsdom** — 0.855s +4. **vitest + happy-dom** — 0.894s +5. **vitest + jsdom** — 0.997s ### Speed comparison -- poku+happy-dom vs jest+jsdom: jest is **621% slower** -- poku+happy-dom vs vitest+jsdom: vitest is **672% slower** -- jest+jsdom vs vitest+jsdom: vitest is **7% slower** than jest +- poku+happy-dom vs jest+jsdom: jest is **632% slower** +- poku+happy-dom vs vitest+jsdom: vitest is **754% slower** +- jest+jsdom vs vitest+jsdom: vitest is **17% slower** than jest ### DOM adapter impact -- **poku**: happy-dom vs jsdom — jsdom is **280% slower** -- **vitest**: happy-dom vs jsdom — jsdom is **36% slower** +- **poku**: happy-dom vs jsdom — jsdom is **163% slower** +- **vitest**: happy-dom vs jsdom — jsdom is **12% slower** ### Memory footprint -- **vitest + happy-dom**: 115.9 MB peak RSS -- **poku + happy-dom**: 129.0 MB peak RSS -- **vitest + jsdom**: 148.5 MB peak RSS -- **poku + jsdom**: 176.1 MB peak RSS -- **jest + jsdom**: 197.1 MB peak RSS +- **vitest + happy-dom**: 115.8 MB peak RSS +- **poku + happy-dom**: 129.3 MB peak RSS +- **vitest + jsdom**: 147.4 MB peak RSS +- **poku + jsdom**: 171.9 MB peak RSS +- **jest + jsdom**: 196.9 MB peak RSS ### Consistency (lower stdev = more predictable) -- **poku + happy-dom**: σ = 0.017s -- **jest + jsdom**: σ = 0.020s -- **vitest + happy-dom**: σ = 0.023s -- **poku + jsdom**: σ = 0.102s -- **vitest + jsdom**: σ = 0.170s +- **poku + happy-dom**: σ = 0.005s +- **poku + jsdom**: σ = 0.008s +- **vitest + jsdom**: σ = 0.025s +- **vitest + happy-dom**: σ = 0.030s +- **jest + jsdom**: σ = 0.044s ## Key findings -- **Fastest**: poku + happy-dom — 0.156s mean -- **Slowest**: vitest + jsdom — 1.201s mean -- **Speed spread**: 672% difference between fastest and slowest +- **Fastest**: poku + happy-dom — 0.117s mean +- **Slowest**: vitest + jsdom — 0.997s mean +- **Speed spread**: 754% difference between fastest and slowest ### Interpretation diff --git a/benchmark/results.json b/benchmark/results.json index 73e1a6b..340656f 100644 --- a/benchmark/results.json +++ b/benchmark/results.json @@ -1,5 +1,5 @@ { - "timestamp": "2026-04-05T15:33:19.263Z", + "timestamp": "2026-04-05T16:06:11.140Z", "system": { "nodeVersion": "v22.5.1", "platform": "darwin 25.4.0", @@ -14,65 +14,65 @@ "results": [ { "label": "poku + happy-dom", - "mean": 155.6485832, - "min": 165.997708, - "max": 146.578375, - "stddev": 16.953596132732102, - "meanRss": 135249920, - "meanUserCpu": 416, - "meanSysCpu": 106, + "mean": 116.84729999999999, + "min": 106.51175, + "max": 120.779, + "stddev": 5.221600485038621, + "meanRss": 135577600, + "meanUserCpu": 352, + "meanSysCpu": 76, "runs": 7, "validRuns": 7, "failures": 0 }, { "label": "poku + jsdom", - "mean": 591.4760668, - "min": 518.124292, - "max": 787.085625, - "stddev": 101.61245971807277, - "meanRss": 184690278.4, - "meanUserCpu": 740, - "meanSysCpu": 194, + "mean": 307.06292500000006, + "min": 291.679667, + "max": 310.873875, + "stddev": 7.901554057709515, + "meanRss": 180292812.8, + "meanUserCpu": 542, + "meanSysCpu": 116, "runs": 7, "validRuns": 7, "failures": 0 }, { "label": "jest + jsdom", - "mean": 1122.2937752000003, - "min": 1085.0054170000003, - "max": 1144.0793749999993, - "stddev": 20.41105742155513, - "meanRss": 206667776, - "meanUserCpu": 952, - "meanSysCpu": 224, + "mean": 854.7983083999992, + "min": 782.1599999999999, + "max": 892.1895829999994, + "stddev": 44.12634263311857, + "meanRss": 206464614.4, + "meanUserCpu": 800, + "meanSysCpu": 152, "runs": 7, "validRuns": 7, "failures": 0 }, { "label": "vitest + jsdom", - "mean": 1201.4220833999984, - "min": 1045.4672919999975, - "max": 1467.2277089999989, - "stddev": 169.5559084298753, - "meanRss": 155670937.6, - "meanUserCpu": 3744, - "meanSysCpu": 1036, + "mean": 997.3366583999999, + "min": 961.1523339999985, + "max": 1026.0704170000026, + "stddev": 25.06068219072583, + "meanRss": 154510950.4, + "meanUserCpu": 3540, + "meanSysCpu": 958, "runs": 7, "validRuns": 7, "failures": 0 }, { "label": "vitest + happy-dom", - "mean": 882.9808834000003, - "min": 855.0224999999991, - "max": 910.0149579999998, - "stddev": 23.495444550622587, - "meanRss": 121523404.8, - "meanUserCpu": 3094, - "meanSysCpu": 928, + "mean": 894.379991400001, + "min": 850.409125000002, + "max": 940.0482080000002, + "stddev": 30.413407818712027, + "meanRss": 121451315.2, + "meanUserCpu": 3146, + "meanSysCpu": 938, "runs": 7, "validRuns": 7, "failures": 0 diff --git a/package-lock.json b/package-lock.json index 6a85d03..3014a7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.2.1", "license": "MIT", "dependencies": { - "@pokujs/dom": "file:../dom", + "@pokujs/dom": "^1.0.1", "@testing-library/dom": "^10.4.1" }, "devDependencies": { @@ -58,7 +58,7 @@ } }, "../dom": { - "version": "0.1.0", + "version": "1.0.1", "license": "MIT", "dependencies": { "@testing-library/dom": "^10.4.1" @@ -67,11 +67,13 @@ "@happy-dom/global-registrator": "^20.8.9", "@types/jsdom": "^28.0.1", "@types/node": "^25.5.0", + "cross-env": "^10.1.0", "happy-dom": "^20.8.9", "jsdom": "^26.1.0", "poku": "4.2.0", "rimraf": "^6.0.1", "tsup": "^8.5.0", + "tsx": "^4.21.0", "typescript": "^6.0.2" }, "engines": { diff --git a/package.json b/package.json index 63a01e4..b82dbae 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "provenance": true }, "dependencies": { - "@pokujs/dom": "^0.1.0", + "@pokujs/dom": "^1.0.1", "@testing-library/dom": "^10.4.1" }, "peerDependencies": { From ff86a7f3618ba4f8a421b22b0e578d667788e4e2 Mon Sep 17 00:00:00 2001 From: lojhan Date: Sun, 5 Apr 2026 13:40:38 -0300 Subject: [PATCH 3/9] fix: use registry-resolved package-lock.json for @pokujs/dom --- package-lock.json | 444 ++++++++++++++++++++++------------------------ 1 file changed, 214 insertions(+), 230 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3014a7c..b09e0f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,54 +57,11 @@ } } }, - "../dom": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "@testing-library/dom": "^10.4.1" - }, - "devDependencies": { - "@happy-dom/global-registrator": "^20.8.9", - "@types/jsdom": "^28.0.1", - "@types/node": "^25.5.0", - "cross-env": "^10.1.0", - "happy-dom": "^20.8.9", - "jsdom": "^26.1.0", - "poku": "4.2.0", - "rimraf": "^6.0.1", - "tsup": "^8.5.0", - "tsx": "^4.21.0", - "typescript": "^6.0.2" - }, - "engines": { - "bun": ">=1.x.x", - "deno": ">=2.x.x", - "node": ">=20.x.x", - "typescript": ">=6.x.x" - }, - "peerDependencies": { - "@happy-dom/global-registrator": ">=20", - "happy-dom": ">=20", - "jsdom": ">=22", - "poku": ">=4.1.0" - }, - "peerDependenciesMeta": { - "@happy-dom/global-registrator": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, "node_modules/@asamuzakjp/css-color": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@csstools/css-calc": "^2.1.3", @@ -114,13 +71,6 @@ "lru-cache": "^10.4.3" } }, - "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -258,7 +208,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -278,7 +228,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -302,7 +252,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -330,7 +280,7 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -353,7 +303,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -377,9 +327,9 @@ "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz", - "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", "cpu": [ "ppc64" ], @@ -394,9 +344,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz", - "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", "cpu": [ "arm" ], @@ -411,9 +361,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz", - "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", "cpu": [ "arm64" ], @@ -428,9 +378,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz", - "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", "cpu": [ "x64" ], @@ -445,9 +395,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz", - "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", "cpu": [ "arm64" ], @@ -462,9 +412,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz", - "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", "cpu": [ "x64" ], @@ -479,9 +429,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz", - "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", "cpu": [ "arm64" ], @@ -496,9 +446,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz", - "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", "cpu": [ "x64" ], @@ -513,9 +463,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz", - "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", "cpu": [ "arm" ], @@ -530,9 +480,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz", - "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", "cpu": [ "arm64" ], @@ -547,9 +497,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz", - "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", "cpu": [ "ia32" ], @@ -564,9 +514,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz", - "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", "cpu": [ "loong64" ], @@ -581,9 +531,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz", - "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", "cpu": [ "mips64el" ], @@ -598,9 +548,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz", - "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", "cpu": [ "ppc64" ], @@ -615,9 +565,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz", - "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", "cpu": [ "riscv64" ], @@ -632,9 +582,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz", - "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", "cpu": [ "s390x" ], @@ -649,9 +599,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz", - "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", "cpu": [ "x64" ], @@ -666,9 +616,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz", - "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", "cpu": [ "arm64" ], @@ -683,9 +633,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz", - "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", "cpu": [ "x64" ], @@ -700,9 +650,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz", - "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", "cpu": [ "arm64" ], @@ -717,9 +667,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz", - "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", "cpu": [ "x64" ], @@ -734,9 +684,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz", - "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", "cpu": [ "arm64" ], @@ -751,9 +701,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz", - "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", "cpu": [ "x64" ], @@ -768,9 +718,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz", - "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", "cpu": [ "arm64" ], @@ -785,9 +735,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz", - "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", "cpu": [ "ia32" ], @@ -802,9 +752,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz", - "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", "cpu": [ "x64" ], @@ -822,7 +772,7 @@ "version": "20.8.9", "resolved": "https://registry.npmjs.org/@happy-dom/global-registrator/-/global-registrator-20.8.9.tgz", "integrity": "sha512-DtZeRRHY9A/bisTJziUBBPrdnPui7+R185G/hzi6/Boymhqh7/wi53AY+IvQHS1+7OPaqfO/1XNpngNwthLz+A==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@types/node": ">=20.0.0", @@ -907,8 +857,36 @@ } }, "node_modules/@pokujs/dom": { - "resolved": "../dom", - "link": true + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@pokujs/dom/-/dom-1.0.1.tgz", + "integrity": "sha512-mt/OpJjXn4kHCKVLWezzaFPwJeExmc8dyuHyzHwZPStPTzp+gagB8XEMJ0Xng/utcZVTnc6x2kkjvpesUI3Rsg==", + "license": "MIT", + "dependencies": { + "@testing-library/dom": "^10.4.1" + }, + "engines": { + "bun": ">=1.x.x", + "deno": ">=2.x.x", + "node": ">=20.x.x", + "typescript": ">=6.x.x" + }, + "peerDependencies": { + "@happy-dom/global-registrator": ">=20", + "happy-dom": ">=20", + "jsdom": ">=22", + "poku": ">=4.1.0" + }, + "peerDependenciesMeta": { + "@happy-dom/global-registrator": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.60.1", @@ -1305,23 +1283,23 @@ "undici-types": "^7.21.0" } }, - "node_modules/@types/jsdom/node_modules/undici-types": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", - "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node": { - "version": "25.5.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz", - "integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==", - "dev": true, + "version": "25.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz", + "integrity": "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==", + "devOptional": true, "license": "MIT", "dependencies": { "undici-types": "~7.18.0" } }, + "node_modules/@types/node/node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "devOptional": true, + "license": "MIT" + }, "node_modules/@types/react": { "version": "19.2.14", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", @@ -1353,14 +1331,14 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz", "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==", - "dev": true, + "devOptional": 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, + "devOptional": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -1383,7 +1361,7 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">= 14" @@ -1555,7 +1533,7 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@asamuzakjp/css-color": "^3.2.0", @@ -1576,7 +1554,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "whatwg-mimetype": "^4.0.0", @@ -1590,7 +1568,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=18" @@ -1600,7 +1578,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1618,7 +1596,7 @@ "version": "10.6.0", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/dequal": { @@ -1640,7 +1618,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", - "dev": true, + "devOptional": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -1650,9 +1628,9 @@ } }, "node_modules/esbuild": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz", - "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1663,32 +1641,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.4", - "@esbuild/android-arm": "0.27.4", - "@esbuild/android-arm64": "0.27.4", - "@esbuild/android-x64": "0.27.4", - "@esbuild/darwin-arm64": "0.27.4", - "@esbuild/darwin-x64": "0.27.4", - "@esbuild/freebsd-arm64": "0.27.4", - "@esbuild/freebsd-x64": "0.27.4", - "@esbuild/linux-arm": "0.27.4", - "@esbuild/linux-arm64": "0.27.4", - "@esbuild/linux-ia32": "0.27.4", - "@esbuild/linux-loong64": "0.27.4", - "@esbuild/linux-mips64el": "0.27.4", - "@esbuild/linux-ppc64": "0.27.4", - "@esbuild/linux-riscv64": "0.27.4", - "@esbuild/linux-s390x": "0.27.4", - "@esbuild/linux-x64": "0.27.4", - "@esbuild/netbsd-arm64": "0.27.4", - "@esbuild/netbsd-x64": "0.27.4", - "@esbuild/openbsd-arm64": "0.27.4", - "@esbuild/openbsd-x64": "0.27.4", - "@esbuild/openharmony-arm64": "0.27.4", - "@esbuild/sunos-x64": "0.27.4", - "@esbuild/win32-arm64": "0.27.4", - "@esbuild/win32-ia32": "0.27.4", - "@esbuild/win32-x64": "0.27.4" + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" } }, "node_modules/fdir": { @@ -1737,9 +1715,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", - "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "version": "4.13.7", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", + "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1771,7 +1749,7 @@ "version": "20.8.9", "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-20.8.9.tgz", "integrity": "sha512-Tz23LR9T9jOGVZm2x1EPdXqwA37G/owYMxRwU0E4miurAtFsPMQ1d2Jc2okUaSjZqAFz2oEn3FLXC5a0a+siyA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@types/node": ">=20.0.0", @@ -1789,7 +1767,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "whatwg-encoding": "^3.1.1" @@ -1802,7 +1780,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.0", @@ -1816,7 +1794,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.2", @@ -1830,7 +1808,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -1843,7 +1821,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/isexe": { @@ -1873,7 +1851,7 @@ "version": "26.1.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "cssstyle": "^4.2.1", @@ -1913,7 +1891,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=18" @@ -1963,14 +1941,11 @@ } }, "node_modules/lru-cache": { - "version": "11.2.7", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", - "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "devOptional": true, + "license": "ISC" }, "node_modules/lz-string": { "version": "1.5.0", @@ -2034,7 +2009,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/mz": { @@ -2053,7 +2028,7 @@ "version": "2.2.23", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", "integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/object-assign": { @@ -2077,7 +2052,7 @@ "version": "7.3.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "entities": "^6.0.0" @@ -2090,7 +2065,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, + "devOptional": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -2126,6 +2101,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -2178,7 +2163,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/poku/-/poku-4.2.0.tgz", "integrity": "sha512-GygMGFGgEJ9kfs6Z+QPg/ODs9OF3oGHN8+hYIxtBox3pwYISO+Vu660vH1e+YzjpGoaoy2o5y6YwE1tX5yZx3Q==", - "dev": true, "license": "MIT", "bin": { "poku": "lib/bin/index.js" @@ -2271,7 +2255,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=6" @@ -2409,21 +2393,21 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, + "devOptional": true, "license": "ISC", "dependencies": { "xmlchars": "^2.2.0" @@ -2512,7 +2496,7 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/thenify": { @@ -2566,7 +2550,7 @@ "version": "6.1.86", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "tldts-core": "^6.1.86" @@ -2579,14 +2563,14 @@ "version": "6.1.86", "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/tough-cookie": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", - "dev": true, + "devOptional": true, "license": "BSD-3-Clause", "dependencies": { "tldts": "^6.1.32" @@ -2599,7 +2583,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "punycode": "^2.3.1" @@ -2720,9 +2704,9 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", - "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.7.tgz", + "integrity": "sha512-XA+gOBkzYD3C74sZowtCLTpgtaCdqZhqCvR6y9LXvrKTt/IVU6bz49T4D+BPi475scshCCkb0IklJRw6T1ZlgQ==", "dev": true, "license": "MIT" }, @@ -2730,7 +2714,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "xml-name-validator": "^5.0.0" @@ -2743,7 +2727,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, + "devOptional": true, "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -2754,7 +2738,7 @@ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "iconv-lite": "0.6.3" @@ -2767,7 +2751,7 @@ "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, + "devOptional": true, "license": "MIT", "engines": { "node": ">=12" @@ -2777,7 +2761,7 @@ "version": "14.2.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "tr46": "^5.1.0", @@ -2807,7 +2791,7 @@ "version": "8.20.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -2829,7 +2813,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "engines": { "node": ">=18" @@ -2839,7 +2823,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true, + "devOptional": true, "license": "MIT" } } From 9d28995e80764ea565e0dcdcbf6343e79914cd5d Mon Sep 17 00:00:00 2001 From: lojhan Date: Sun, 5 Apr 2026 16:23:26 -0300 Subject: [PATCH 4/9] chore: update benchmark report and results --- benchmark/REPORT.md | 58 +++++++++++++++++----------------- benchmark/results.json | 70 +++++++++++++++++++++--------------------- 2 files changed, 64 insertions(+), 64 deletions(-) diff --git a/benchmark/REPORT.md b/benchmark/REPORT.md index ca6d9b8..35acef2 100644 --- a/benchmark/REPORT.md +++ b/benchmark/REPORT.md @@ -1,6 +1,6 @@ # React Testing Framework Benchmark Report -> Generated: Sun, 05 Apr 2026 16:06:11 GMT +> Generated: Sun, 05 Apr 2026 19:06:36 GMT ## Environment @@ -39,11 +39,11 @@ Each scenario runs the **same 9 React tests** across 5 test files: | Scenario | Mean | Min | Max | Stdev | Peak RSS | vs poku+happy-dom | |--------------------|--------|--------|--------|--------|----------|-------------------| -| poku + happy-dom | 0.117s | 0.107s | 0.121s | 0.005s | 129.3 MB | *(baseline)* | -| poku + jsdom | 0.307s | 0.292s | 0.311s | 0.008s | 171.9 MB | +163% | -| jest + jsdom | 0.855s | 0.782s | 0.892s | 0.044s | 196.9 MB | +632% | -| vitest + jsdom | 0.997s | 0.961s | 1.026s | 0.025s | 147.4 MB | +754% | -| vitest + happy-dom | 0.894s | 0.850s | 0.940s | 0.030s | 115.8 MB | +665% | +| poku + happy-dom | 0.115s | 0.112s | 0.109s | 0.004s | 127.4 MB | *(baseline)* | +| poku + jsdom | 0.294s | 0.280s | 0.299s | 0.007s | 172.1 MB | +157% | +| jest + jsdom | 0.843s | 0.768s | 0.879s | 0.041s | 198.8 MB | +636% | +| vitest + jsdom | 0.968s | 0.951s | 0.986s | 0.011s | 147.8 MB | +745% | +| vitest + happy-dom | 0.845s | 0.825s | 0.856s | 0.013s | 115.2 MB | +637% | > **Poku elapsed time** uses Poku's reported suite `Duration` (ANSI-stripped parse) to avoid teardown-skew artifacts. > **Jest/Vitest elapsed time** is measured with `performance.now()` around the child-process spawn. @@ -54,44 +54,44 @@ Each scenario runs the **same 9 React tests** across 5 test files: ### Overall ranking (mean wall-clock time) -1. **poku + happy-dom** — 0.117s -2. **poku + jsdom** — 0.307s -3. **jest + jsdom** — 0.855s -4. **vitest + happy-dom** — 0.894s -5. **vitest + jsdom** — 0.997s +1. **poku + happy-dom** — 0.115s +2. **poku + jsdom** — 0.294s +3. **jest + jsdom** — 0.843s +4. **vitest + happy-dom** — 0.845s +5. **vitest + jsdom** — 0.968s ### Speed comparison -- poku+happy-dom vs jest+jsdom: jest is **632% slower** -- poku+happy-dom vs vitest+jsdom: vitest is **754% slower** -- jest+jsdom vs vitest+jsdom: vitest is **17% slower** than jest +- poku+happy-dom vs jest+jsdom: jest is **636% slower** +- poku+happy-dom vs vitest+jsdom: vitest is **745% slower** +- jest+jsdom vs vitest+jsdom: vitest is **15% slower** than jest ### DOM adapter impact -- **poku**: happy-dom vs jsdom — jsdom is **163% slower** -- **vitest**: happy-dom vs jsdom — jsdom is **12% slower** +- **poku**: happy-dom vs jsdom — jsdom is **157% slower** +- **vitest**: happy-dom vs jsdom — jsdom is **15% slower** ### Memory footprint -- **vitest + happy-dom**: 115.8 MB peak RSS -- **poku + happy-dom**: 129.3 MB peak RSS -- **vitest + jsdom**: 147.4 MB peak RSS -- **poku + jsdom**: 171.9 MB peak RSS -- **jest + jsdom**: 196.9 MB peak RSS +- **vitest + happy-dom**: 115.2 MB peak RSS +- **poku + happy-dom**: 127.4 MB peak RSS +- **vitest + jsdom**: 147.8 MB peak RSS +- **poku + jsdom**: 172.1 MB peak RSS +- **jest + jsdom**: 198.8 MB peak RSS ### Consistency (lower stdev = more predictable) -- **poku + happy-dom**: σ = 0.005s -- **poku + jsdom**: σ = 0.008s -- **vitest + jsdom**: σ = 0.025s -- **vitest + happy-dom**: σ = 0.030s -- **jest + jsdom**: σ = 0.044s +- **poku + happy-dom**: σ = 0.004s +- **poku + jsdom**: σ = 0.007s +- **vitest + jsdom**: σ = 0.011s +- **vitest + happy-dom**: σ = 0.013s +- **jest + jsdom**: σ = 0.041s ## Key findings -- **Fastest**: poku + happy-dom — 0.117s mean -- **Slowest**: vitest + jsdom — 0.997s mean -- **Speed spread**: 754% difference between fastest and slowest +- **Fastest**: poku + happy-dom — 0.115s mean +- **Slowest**: vitest + jsdom — 0.968s mean +- **Speed spread**: 745% difference between fastest and slowest ### Interpretation diff --git a/benchmark/results.json b/benchmark/results.json index 340656f..f05480b 100644 --- a/benchmark/results.json +++ b/benchmark/results.json @@ -1,5 +1,5 @@ { - "timestamp": "2026-04-05T16:06:11.140Z", + "timestamp": "2026-04-05T19:06:36.388Z", "system": { "nodeVersion": "v22.5.1", "platform": "darwin 25.4.0", @@ -14,38 +14,38 @@ "results": [ { "label": "poku + happy-dom", - "mean": 116.84729999999999, - "min": 106.51175, - "max": 120.779, - "stddev": 5.221600485038621, - "meanRss": 135577600, - "meanUserCpu": 352, - "meanSysCpu": 76, + "mean": 114.5411498, + "min": 111.865375, + "max": 108.566625, + "stddev": 4.164501573153617, + "meanRss": 133624627.2, + "meanUserCpu": 358, + "meanSysCpu": 80, "runs": 7, "validRuns": 7, "failures": 0 }, { "label": "poku + jsdom", - "mean": 307.06292500000006, - "min": 291.679667, - "max": 310.873875, - "stddev": 7.901554057709515, - "meanRss": 180292812.8, - "meanUserCpu": 542, - "meanSysCpu": 116, + "mean": 294.0646082, + "min": 280.499125, + "max": 298.546375, + "stddev": 6.855649968732701, + "meanRss": 180456652.8, + "meanUserCpu": 532, + "meanSysCpu": 102, "runs": 7, "validRuns": 7, "failures": 0 }, { "label": "jest + jsdom", - "mean": 854.7983083999992, - "min": 782.1599999999999, - "max": 892.1895829999994, - "stddev": 44.12634263311857, - "meanRss": 206464614.4, - "meanUserCpu": 800, + "mean": 842.5360584000006, + "min": 768.3345829999998, + "max": 879.3446250000015, + "stddev": 40.57889525259689, + "meanRss": 208506060.8, + "meanUserCpu": 784, "meanSysCpu": 152, "runs": 7, "validRuns": 7, @@ -53,26 +53,26 @@ }, { "label": "vitest + jsdom", - "mean": 997.3366583999999, - "min": 961.1523339999985, - "max": 1026.0704170000026, - "stddev": 25.06068219072583, - "meanRss": 154510950.4, - "meanUserCpu": 3540, - "meanSysCpu": 958, + "mean": 967.6274329999997, + "min": 950.946915999999, + "max": 985.529625000001, + "stddev": 11.190019303221952, + "meanRss": 155002470.4, + "meanUserCpu": 3524, + "meanSysCpu": 954, "runs": 7, "validRuns": 7, "failures": 0 }, { "label": "vitest + happy-dom", - "mean": 894.379991400001, - "min": 850.409125000002, - "max": 940.0482080000002, - "stddev": 30.413407818712027, - "meanRss": 121451315.2, - "meanUserCpu": 3146, - "meanSysCpu": 938, + "mean": 844.6526001999998, + "min": 824.9157500000001, + "max": 856.1071249999986, + "stddev": 13.21280400724632, + "meanRss": 120832000, + "meanUserCpu": 3056, + "meanSysCpu": 900, "runs": 7, "validRuns": 7, "failures": 0 From 7bda77537bbd7bae1e7e47c0fee2090fbc2c4aea Mon Sep 17 00:00:00 2001 From: lojhan Date: Sun, 5 Apr 2026 16:23:33 -0300 Subject: [PATCH 5/9] chore: bump @pokujs/dom to ^1.1.0 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index b09e0f0..3acbc4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.2.1", "license": "MIT", "dependencies": { - "@pokujs/dom": "^1.0.1", + "@pokujs/dom": "^1.1.0", "@testing-library/dom": "^10.4.1" }, "devDependencies": { @@ -857,9 +857,9 @@ } }, "node_modules/@pokujs/dom": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@pokujs/dom/-/dom-1.0.1.tgz", - "integrity": "sha512-mt/OpJjXn4kHCKVLWezzaFPwJeExmc8dyuHyzHwZPStPTzp+gagB8XEMJ0Xng/utcZVTnc6x2kkjvpesUI3Rsg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pokujs/dom/-/dom-1.1.0.tgz", + "integrity": "sha512-0Cp3KLirW4mOXE11l2a0q0b6qsgorh3iqZxd1RiL69amc7uOQm+QJ96ETwr9GRkIfxa2wCPX/0JrKhMNY1T10Q==", "license": "MIT", "dependencies": { "@testing-library/dom": "^10.4.1" diff --git a/package.json b/package.json index b82dbae..3fded9b 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "provenance": true }, "dependencies": { - "@pokujs/dom": "^1.0.1", + "@pokujs/dom": "^1.1.0", "@testing-library/dom": "^10.4.1" }, "peerDependencies": { From 1a1ddf4c5e41d588583764957e984ef8fab08934 Mon Sep 17 00:00:00 2001 From: lojhan Date: Sun, 5 Apr 2026 16:37:33 -0300 Subject: [PATCH 6/9] fix: add deno.json import map for @pokujs/dom Deno with isolation:none loads all test files in the same npm:poku process. In that context bare specifiers like @pokujs/dom are not resolved from node_modules automatically. Adding an explicit import map entry pointing to npm:@pokujs/dom fixes resolution for all test files that transitively import @pokujs/dom. --- deno.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 deno.json diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..a7c7920 --- /dev/null +++ b/deno.json @@ -0,0 +1,6 @@ +{ + "nodeModulesDir": "auto", + "imports": { + "@pokujs/dom": "npm:@pokujs/dom@^1.1.0" + } +} From 9de996199ebdb757ecfa6812305b9768511f9752 Mon Sep 17 00:00:00 2001 From: lojhan Date: Sun, 5 Apr 2026 17:40:33 -0300 Subject: [PATCH 7/9] chore: bump @pokujs/dom to ^1.1.1 and add multi-suite runner --- deno.lock | 1193 +++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 110 ++--- package.json | 20 +- run.test.ts | 22 + 4 files changed, 1283 insertions(+), 62 deletions(-) create mode 100644 deno.lock create mode 100644 run.test.ts diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..d00aeac --- /dev/null +++ b/deno.lock @@ -0,0 +1,1193 @@ +{ + "version": "5", + "specifiers": { + "npm:@happy-dom/global-registrator@^20.8.9": "20.8.9", + "npm:@ianvs/prettier-plugin-sort-imports@^4.7.0": "4.7.1_prettier@3.8.1", + "npm:@pokujs/dom@^1.1.0": "1.1.0_@happy-dom+global-registrator@20.8.9_happy-dom@20.8.9_jsdom@26.1.0_poku@4.2.0", + "npm:@pokujs/dom@^1.1.1": "1.1.1_happy-dom@20.8.9_jsdom@26.1.0_poku@4.2.0", + "npm:@testing-library/dom@^10.4.1": "10.4.1", + "npm:@types/jsdom@^28.0.1": "28.0.1", + "npm:@types/node@^25.5.0": "25.5.2", + "npm:@types/react-dom@^19.2.3": "19.2.3_@types+react@19.2.14", + "npm:@types/react@^19.2.14": "19.2.14", + "npm:cross-env@^10.1.0": "10.1.0", + "npm:happy-dom@^20.8.9": "20.8.9", + "npm:jsdom@^26.1.0": "26.1.0", + "npm:poku@*": "4.2.0", + "npm:poku@4.2.0": "4.2.0", + "npm:prettier@^3.6.2": "3.8.1", + "npm:react-dom@^19.2.4": "19.2.4_react@19.2.4", + "npm:react@^19.2.4": "19.2.4", + "npm:rimraf@^6.0.1": "6.1.3", + "npm:tsup@^8.5.0": "8.5.1_typescript@6.0.2_esbuild@0.27.7_tsx@4.21.0", + "npm:tsx@^4.21.0": "4.21.0", + "npm:typescript@^6.0.2": "6.0.2" + }, + "npm": { + "@asamuzakjp/css-color@3.2.0_@csstools+css-parser-algorithms@3.0.5__@csstools+css-tokenizer@3.0.4_@csstools+css-tokenizer@3.0.4": { + "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", + "dependencies": [ + "@csstools/css-calc", + "@csstools/css-color-parser", + "@csstools/css-parser-algorithms", + "@csstools/css-tokenizer", + "lru-cache@10.4.3" + ] + }, + "@babel/code-frame@7.29.0": { + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dependencies": [ + "@babel/helper-validator-identifier", + "js-tokens", + "picocolors" + ] + }, + "@babel/generator@7.29.1": { + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dependencies": [ + "@babel/parser", + "@babel/types", + "@jridgewell/gen-mapping", + "@jridgewell/trace-mapping", + "jsesc" + ] + }, + "@babel/helper-globals@7.28.0": { + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==" + }, + "@babel/helper-string-parser@7.27.1": { + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==" + }, + "@babel/helper-validator-identifier@7.28.5": { + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==" + }, + "@babel/parser@7.29.2": { + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dependencies": [ + "@babel/types" + ], + "bin": true + }, + "@babel/runtime@7.29.2": { + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==" + }, + "@babel/template@7.28.6": { + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dependencies": [ + "@babel/code-frame", + "@babel/parser", + "@babel/types" + ] + }, + "@babel/traverse@7.29.0": { + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dependencies": [ + "@babel/code-frame", + "@babel/generator", + "@babel/helper-globals", + "@babel/parser", + "@babel/template", + "@babel/types", + "debug" + ] + }, + "@babel/types@7.29.0": { + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dependencies": [ + "@babel/helper-string-parser", + "@babel/helper-validator-identifier" + ] + }, + "@csstools/color-helpers@5.1.0": { + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==" + }, + "@csstools/css-calc@2.1.4_@csstools+css-parser-algorithms@3.0.5__@csstools+css-tokenizer@3.0.4_@csstools+css-tokenizer@3.0.4": { + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "dependencies": [ + "@csstools/css-parser-algorithms", + "@csstools/css-tokenizer" + ] + }, + "@csstools/css-color-parser@3.1.0_@csstools+css-parser-algorithms@3.0.5__@csstools+css-tokenizer@3.0.4_@csstools+css-tokenizer@3.0.4": { + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", + "dependencies": [ + "@csstools/color-helpers", + "@csstools/css-calc", + "@csstools/css-parser-algorithms", + "@csstools/css-tokenizer" + ] + }, + "@csstools/css-parser-algorithms@3.0.5_@csstools+css-tokenizer@3.0.4": { + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "dependencies": [ + "@csstools/css-tokenizer" + ] + }, + "@csstools/css-tokenizer@3.0.4": { + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==" + }, + "@epic-web/invariant@1.0.0": { + "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==" + }, + "@esbuild/aix-ppc64@0.27.7": { + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "os": ["aix"], + "cpu": ["ppc64"] + }, + "@esbuild/android-arm64@0.27.7": { + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@esbuild/android-arm@0.27.7": { + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "os": ["android"], + "cpu": ["arm"] + }, + "@esbuild/android-x64@0.27.7": { + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "os": ["android"], + "cpu": ["x64"] + }, + "@esbuild/darwin-arm64@0.27.7": { + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@esbuild/darwin-x64@0.27.7": { + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@esbuild/freebsd-arm64@0.27.7": { + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "os": ["freebsd"], + "cpu": ["arm64"] + }, + "@esbuild/freebsd-x64@0.27.7": { + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@esbuild/linux-arm64@0.27.7": { + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@esbuild/linux-arm@0.27.7": { + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@esbuild/linux-ia32@0.27.7": { + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "os": ["linux"], + "cpu": ["ia32"] + }, + "@esbuild/linux-loong64@0.27.7": { + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@esbuild/linux-mips64el@0.27.7": { + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "os": ["linux"], + "cpu": ["mips64el"] + }, + "@esbuild/linux-ppc64@0.27.7": { + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@esbuild/linux-riscv64@0.27.7": { + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@esbuild/linux-s390x@0.27.7": { + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@esbuild/linux-x64@0.27.7": { + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@esbuild/netbsd-arm64@0.27.7": { + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "os": ["netbsd"], + "cpu": ["arm64"] + }, + "@esbuild/netbsd-x64@0.27.7": { + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "os": ["netbsd"], + "cpu": ["x64"] + }, + "@esbuild/openbsd-arm64@0.27.7": { + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "os": ["openbsd"], + "cpu": ["arm64"] + }, + "@esbuild/openbsd-x64@0.27.7": { + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "os": ["openbsd"], + "cpu": ["x64"] + }, + "@esbuild/openharmony-arm64@0.27.7": { + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "os": ["openharmony"], + "cpu": ["arm64"] + }, + "@esbuild/sunos-x64@0.27.7": { + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "os": ["sunos"], + "cpu": ["x64"] + }, + "@esbuild/win32-arm64@0.27.7": { + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@esbuild/win32-ia32@0.27.7": { + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "os": ["win32"], + "cpu": ["ia32"] + }, + "@esbuild/win32-x64@0.27.7": { + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@happy-dom/global-registrator@20.8.9": { + "integrity": "sha512-DtZeRRHY9A/bisTJziUBBPrdnPui7+R185G/hzi6/Boymhqh7/wi53AY+IvQHS1+7OPaqfO/1XNpngNwthLz+A==", + "dependencies": [ + "@types/node@25.5.2", + "happy-dom" + ] + }, + "@ianvs/prettier-plugin-sort-imports@4.7.1_prettier@3.8.1": { + "integrity": "sha512-jmTNYGlg95tlsoG3JLCcuC4BrFELJtLirLAkQW/71lXSyOhVt/Xj7xWbbGcuVbNq1gwWgSyMrPjJc9Z30hynVw==", + "dependencies": [ + "@babel/generator", + "@babel/parser", + "@babel/traverse", + "@babel/types", + "prettier", + "semver" + ] + }, + "@jridgewell/gen-mapping@0.3.13": { + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dependencies": [ + "@jridgewell/sourcemap-codec", + "@jridgewell/trace-mapping" + ] + }, + "@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.31": { + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dependencies": [ + "@jridgewell/resolve-uri", + "@jridgewell/sourcemap-codec" + ] + }, + "@pokujs/dom@1.1.0_@happy-dom+global-registrator@20.8.9_happy-dom@20.8.9_jsdom@26.1.0_poku@4.2.0": { + "integrity": "sha512-0Cp3KLirW4mOXE11l2a0q0b6qsgorh3iqZxd1RiL69amc7uOQm+QJ96ETwr9GRkIfxa2wCPX/0JrKhMNY1T10Q==", + "dependencies": [ + "@happy-dom/global-registrator", + "@testing-library/dom", + "happy-dom", + "jsdom", + "poku" + ], + "optionalPeers": [ + "@happy-dom/global-registrator", + "happy-dom", + "jsdom" + ] + }, + "@pokujs/dom@1.1.1_happy-dom@20.8.9_jsdom@26.1.0_poku@4.2.0": { + "integrity": "sha512-qK9JRz9tDgcO4l+QibqwGaWpDeQDKHP7y0Y9b039ieK86kY51wf0WyOi7iDfeKJQ2Quk9vIKBqDaagzJvaaX/A==", + "dependencies": [ + "@testing-library/dom", + "happy-dom", + "jsdom", + "poku" + ], + "optionalPeers": [ + "happy-dom", + "jsdom" + ] + }, + "@rollup/rollup-android-arm-eabi@4.60.1": { + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", + "os": ["android"], + "cpu": ["arm"] + }, + "@rollup/rollup-android-arm64@4.60.1": { + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@rollup/rollup-darwin-arm64@4.60.1": { + "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@rollup/rollup-darwin-x64@4.60.1": { + "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@rollup/rollup-freebsd-arm64@4.60.1": { + "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", + "os": ["freebsd"], + "cpu": ["arm64"] + }, + "@rollup/rollup-freebsd-x64@4.60.1": { + "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@rollup/rollup-linux-arm-gnueabihf@4.60.1": { + "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@rollup/rollup-linux-arm-musleabihf@4.60.1": { + "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@rollup/rollup-linux-arm64-gnu@4.60.1": { + "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@rollup/rollup-linux-arm64-musl@4.60.1": { + "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@rollup/rollup-linux-loong64-gnu@4.60.1": { + "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@rollup/rollup-linux-loong64-musl@4.60.1": { + "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@rollup/rollup-linux-ppc64-gnu@4.60.1": { + "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@rollup/rollup-linux-ppc64-musl@4.60.1": { + "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@rollup/rollup-linux-riscv64-gnu@4.60.1": { + "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@rollup/rollup-linux-riscv64-musl@4.60.1": { + "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@rollup/rollup-linux-s390x-gnu@4.60.1": { + "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@rollup/rollup-linux-x64-gnu@4.60.1": { + "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@rollup/rollup-linux-x64-musl@4.60.1": { + "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@rollup/rollup-openbsd-x64@4.60.1": { + "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", + "os": ["openbsd"], + "cpu": ["x64"] + }, + "@rollup/rollup-openharmony-arm64@4.60.1": { + "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", + "os": ["openharmony"], + "cpu": ["arm64"] + }, + "@rollup/rollup-win32-arm64-msvc@4.60.1": { + "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@rollup/rollup-win32-ia32-msvc@4.60.1": { + "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", + "os": ["win32"], + "cpu": ["ia32"] + }, + "@rollup/rollup-win32-x64-gnu@4.60.1": { + "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@rollup/rollup-win32-x64-msvc@4.60.1": { + "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@testing-library/dom@10.4.1": { + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "dependencies": [ + "@babel/code-frame", + "@babel/runtime", + "@types/aria-query", + "aria-query", + "dom-accessibility-api", + "lz-string", + "picocolors", + "pretty-format" + ] + }, + "@types/aria-query@5.0.4": { + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==" + }, + "@types/estree@1.0.8": { + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" + }, + "@types/jsdom@28.0.1": { + "integrity": "sha512-GJq2QE4TAZ5ajSoCasn5DOFm8u1mI3tIFvM5tIq3W5U/RTB6gsHwc6Yhpl91X9VSDOUVblgXmG+2+sSvFQrdlw==", + "dependencies": [ + "@types/node@22.15.15", + "@types/tough-cookie", + "parse5", + "undici-types@7.24.7" + ] + }, + "@types/node@22.15.15": { + "integrity": "sha512-R5muMcZob3/Jjchn5LcO8jdKwSCbzqmPB6ruBxMcf9kbxtniZHP327s6C37iOfuw8mbKK3cAQa7sEl7afLrQ8A==", + "dependencies": [ + "undici-types@6.21.0" + ] + }, + "@types/node@25.5.2": { + "integrity": "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==", + "dependencies": [ + "undici-types@7.18.2" + ] + }, + "@types/react-dom@19.2.3_@types+react@19.2.14": { + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dependencies": [ + "@types/react" + ] + }, + "@types/react@19.2.14": { + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dependencies": [ + "csstype" + ] + }, + "@types/tough-cookie@4.0.5": { + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==" + }, + "@types/whatwg-mimetype@3.0.2": { + "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==" + }, + "@types/ws@8.18.1": { + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dependencies": [ + "@types/node@22.15.15" + ] + }, + "acorn@8.16.0": { + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "bin": true + }, + "agent-base@7.1.4": { + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==" + }, + "ansi-regex@5.0.1": { + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles@5.2.0": { + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + }, + "any-promise@1.3.0": { + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "aria-query@5.3.0": { + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dependencies": [ + "dequal" + ] + }, + "balanced-match@4.0.4": { + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==" + }, + "brace-expansion@5.0.5": { + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dependencies": [ + "balanced-match" + ] + }, + "bundle-require@5.1.0_esbuild@0.27.7": { + "integrity": "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==", + "dependencies": [ + "esbuild", + "load-tsconfig" + ] + }, + "cac@6.7.14": { + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==" + }, + "chokidar@4.0.3": { + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dependencies": [ + "readdirp" + ] + }, + "commander@4.1.1": { + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" + }, + "confbox@0.1.8": { + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==" + }, + "consola@3.4.2": { + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==" + }, + "cross-env@10.1.0": { + "integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==", + "dependencies": [ + "@epic-web/invariant", + "cross-spawn" + ], + "bin": true + }, + "cross-spawn@7.0.6": { + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": [ + "path-key", + "shebang-command", + "which" + ] + }, + "cssstyle@4.6.0": { + "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", + "dependencies": [ + "@asamuzakjp/css-color", + "rrweb-cssom" + ] + }, + "csstype@3.2.3": { + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==" + }, + "data-urls@5.0.0": { + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dependencies": [ + "whatwg-mimetype@4.0.0", + "whatwg-url" + ] + }, + "debug@4.4.3": { + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": [ + "ms" + ] + }, + "decimal.js@10.6.0": { + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==" + }, + "dequal@2.0.3": { + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + }, + "dom-accessibility-api@0.5.16": { + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" + }, + "entities@6.0.1": { + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==" + }, + "entities@7.0.1": { + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==" + }, + "esbuild@0.27.7": { + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "optionalDependencies": [ + "@esbuild/aix-ppc64", + "@esbuild/android-arm", + "@esbuild/android-arm64", + "@esbuild/android-x64", + "@esbuild/darwin-arm64", + "@esbuild/darwin-x64", + "@esbuild/freebsd-arm64", + "@esbuild/freebsd-x64", + "@esbuild/linux-arm", + "@esbuild/linux-arm64", + "@esbuild/linux-ia32", + "@esbuild/linux-loong64", + "@esbuild/linux-mips64el", + "@esbuild/linux-ppc64", + "@esbuild/linux-riscv64", + "@esbuild/linux-s390x", + "@esbuild/linux-x64", + "@esbuild/netbsd-arm64", + "@esbuild/netbsd-x64", + "@esbuild/openbsd-arm64", + "@esbuild/openbsd-x64", + "@esbuild/openharmony-arm64", + "@esbuild/sunos-x64", + "@esbuild/win32-arm64", + "@esbuild/win32-ia32", + "@esbuild/win32-x64" + ], + "scripts": true, + "bin": true + }, + "fdir@6.5.0_picomatch@4.0.4": { + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dependencies": [ + "picomatch" + ], + "optionalPeers": [ + "picomatch" + ] + }, + "fix-dts-default-cjs-exports@1.0.1": { + "integrity": "sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==", + "dependencies": [ + "magic-string", + "mlly", + "rollup" + ] + }, + "fsevents@2.3.3": { + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "os": ["darwin"], + "scripts": true + }, + "get-tsconfig@4.13.7": { + "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", + "dependencies": [ + "resolve-pkg-maps" + ] + }, + "glob@13.0.6": { + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dependencies": [ + "minimatch", + "minipass", + "path-scurry" + ] + }, + "happy-dom@20.8.9": { + "integrity": "sha512-Tz23LR9T9jOGVZm2x1EPdXqwA37G/owYMxRwU0E4miurAtFsPMQ1d2Jc2okUaSjZqAFz2oEn3FLXC5a0a+siyA==", + "dependencies": [ + "@types/node@25.5.2", + "@types/whatwg-mimetype", + "@types/ws", + "entities@7.0.1", + "whatwg-mimetype@3.0.0", + "ws" + ] + }, + "html-encoding-sniffer@4.0.0": { + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dependencies": [ + "whatwg-encoding" + ] + }, + "http-proxy-agent@7.0.2": { + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dependencies": [ + "agent-base", + "debug" + ] + }, + "https-proxy-agent@7.0.6": { + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dependencies": [ + "agent-base", + "debug" + ] + }, + "iconv-lite@0.6.3": { + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": [ + "safer-buffer" + ] + }, + "is-potential-custom-element-name@1.0.1": { + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, + "isexe@2.0.0": { + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "joycon@3.1.1": { + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==" + }, + "js-tokens@4.0.0": { + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "jsdom@26.1.0": { + "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "dependencies": [ + "cssstyle", + "data-urls", + "decimal.js", + "html-encoding-sniffer", + "http-proxy-agent", + "https-proxy-agent", + "is-potential-custom-element-name", + "nwsapi", + "parse5", + "rrweb-cssom", + "saxes", + "symbol-tree", + "tough-cookie", + "w3c-xmlserializer", + "webidl-conversions", + "whatwg-encoding", + "whatwg-mimetype@4.0.0", + "whatwg-url", + "ws", + "xml-name-validator" + ] + }, + "jsesc@3.1.0": { + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "bin": true + }, + "lilconfig@3.1.3": { + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==" + }, + "lines-and-columns@1.2.4": { + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "load-tsconfig@0.2.5": { + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==" + }, + "lru-cache@10.4.3": { + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "lru-cache@11.2.7": { + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==" + }, + "lz-string@1.5.0": { + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "bin": true + }, + "magic-string@0.30.21": { + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dependencies": [ + "@jridgewell/sourcemap-codec" + ] + }, + "minimatch@10.2.5": { + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dependencies": [ + "brace-expansion" + ] + }, + "minipass@7.1.3": { + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==" + }, + "mlly@1.8.2": { + "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==", + "dependencies": [ + "acorn", + "pathe", + "pkg-types", + "ufo" + ] + }, + "ms@2.1.3": { + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "mz@2.7.0": { + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": [ + "any-promise", + "object-assign", + "thenify-all" + ] + }, + "nwsapi@2.2.23": { + "integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==" + }, + "object-assign@4.1.1": { + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "package-json-from-dist@1.0.1": { + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, + "parse5@7.3.0": { + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dependencies": [ + "entities@6.0.1" + ] + }, + "path-key@3.1.1": { + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-scurry@2.0.2": { + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dependencies": [ + "lru-cache@11.2.7", + "minipass" + ] + }, + "pathe@2.0.3": { + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==" + }, + "picocolors@1.1.1": { + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "picomatch@4.0.4": { + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==" + }, + "pirates@4.0.7": { + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==" + }, + "pkg-types@1.3.1": { + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dependencies": [ + "confbox", + "mlly", + "pathe" + ] + }, + "poku@4.2.0": { + "integrity": "sha512-GygMGFGgEJ9kfs6Z+QPg/ODs9OF3oGHN8+hYIxtBox3pwYISO+Vu660vH1e+YzjpGoaoy2o5y6YwE1tX5yZx3Q==", + "bin": true + }, + "postcss-load-config@6.0.1_tsx@4.21.0": { + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dependencies": [ + "lilconfig", + "tsx" + ], + "optionalPeers": [ + "tsx" + ] + }, + "prettier@3.8.1": { + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "bin": true + }, + "pretty-format@27.5.1": { + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dependencies": [ + "ansi-regex", + "ansi-styles", + "react-is" + ] + }, + "punycode@2.3.1": { + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" + }, + "react-dom@19.2.4_react@19.2.4": { + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "dependencies": [ + "react", + "scheduler" + ] + }, + "react-is@17.0.2": { + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "react@19.2.4": { + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==" + }, + "readdirp@4.1.2": { + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==" + }, + "resolve-from@5.0.0": { + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + }, + "resolve-pkg-maps@1.0.0": { + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==" + }, + "rimraf@6.1.3": { + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", + "dependencies": [ + "glob", + "package-json-from-dist" + ], + "bin": true + }, + "rollup@4.60.1": { + "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", + "dependencies": [ + "@types/estree" + ], + "optionalDependencies": [ + "@rollup/rollup-android-arm-eabi", + "@rollup/rollup-android-arm64", + "@rollup/rollup-darwin-arm64", + "@rollup/rollup-darwin-x64", + "@rollup/rollup-freebsd-arm64", + "@rollup/rollup-freebsd-x64", + "@rollup/rollup-linux-arm-gnueabihf", + "@rollup/rollup-linux-arm-musleabihf", + "@rollup/rollup-linux-arm64-gnu", + "@rollup/rollup-linux-arm64-musl", + "@rollup/rollup-linux-loong64-gnu", + "@rollup/rollup-linux-loong64-musl", + "@rollup/rollup-linux-ppc64-gnu", + "@rollup/rollup-linux-ppc64-musl", + "@rollup/rollup-linux-riscv64-gnu", + "@rollup/rollup-linux-riscv64-musl", + "@rollup/rollup-linux-s390x-gnu", + "@rollup/rollup-linux-x64-gnu", + "@rollup/rollup-linux-x64-musl", + "@rollup/rollup-openbsd-x64", + "@rollup/rollup-openharmony-arm64", + "@rollup/rollup-win32-arm64-msvc", + "@rollup/rollup-win32-ia32-msvc", + "@rollup/rollup-win32-x64-gnu", + "@rollup/rollup-win32-x64-msvc", + "fsevents" + ], + "bin": true + }, + "rrweb-cssom@0.8.0": { + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==" + }, + "safer-buffer@2.1.2": { + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "saxes@6.0.0": { + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dependencies": [ + "xmlchars" + ] + }, + "scheduler@0.27.0": { + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==" + }, + "semver@7.7.4": { + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "bin": true + }, + "shebang-command@2.0.0": { + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": [ + "shebang-regex" + ] + }, + "shebang-regex@3.0.0": { + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "source-map@0.7.6": { + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==" + }, + "sucrase@3.35.1": { + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dependencies": [ + "@jridgewell/gen-mapping", + "commander", + "lines-and-columns", + "mz", + "pirates", + "tinyglobby", + "ts-interface-checker" + ], + "bin": true + }, + "symbol-tree@3.2.4": { + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, + "thenify-all@1.6.0": { + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": [ + "thenify" + ] + }, + "thenify@3.3.1": { + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": [ + "any-promise" + ] + }, + "tinyexec@0.3.2": { + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==" + }, + "tinyglobby@0.2.15_picomatch@4.0.4": { + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dependencies": [ + "fdir", + "picomatch" + ] + }, + "tldts-core@6.1.86": { + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==" + }, + "tldts@6.1.86": { + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "dependencies": [ + "tldts-core" + ], + "bin": true + }, + "tough-cookie@5.1.2": { + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "dependencies": [ + "tldts" + ] + }, + "tr46@5.1.1": { + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "dependencies": [ + "punycode" + ] + }, + "tree-kill@1.2.2": { + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "bin": true + }, + "ts-interface-checker@0.1.13": { + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + }, + "tsup@8.5.1_typescript@6.0.2_esbuild@0.27.7_tsx@4.21.0": { + "integrity": "sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==", + "dependencies": [ + "bundle-require", + "cac", + "chokidar", + "consola", + "debug", + "esbuild", + "fix-dts-default-cjs-exports", + "joycon", + "picocolors", + "postcss-load-config", + "resolve-from", + "rollup", + "source-map", + "sucrase", + "tinyexec", + "tinyglobby", + "tree-kill", + "typescript" + ], + "optionalPeers": [ + "typescript" + ], + "bin": true + }, + "tsx@4.21.0": { + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dependencies": [ + "esbuild", + "get-tsconfig" + ], + "optionalDependencies": [ + "fsevents" + ], + "bin": true + }, + "typescript@6.0.2": { + "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", + "bin": true + }, + "ufo@1.6.3": { + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==" + }, + "undici-types@6.21.0": { + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==" + }, + "undici-types@7.18.2": { + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==" + }, + "undici-types@7.24.7": { + "integrity": "sha512-XA+gOBkzYD3C74sZowtCLTpgtaCdqZhqCvR6y9LXvrKTt/IVU6bz49T4D+BPi475scshCCkb0IklJRw6T1ZlgQ==" + }, + "w3c-xmlserializer@5.0.0": { + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dependencies": [ + "xml-name-validator" + ] + }, + "webidl-conversions@7.0.0": { + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-encoding@3.1.1": { + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dependencies": [ + "iconv-lite" + ], + "deprecated": true + }, + "whatwg-mimetype@3.0.0": { + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==" + }, + "whatwg-mimetype@4.0.0": { + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==" + }, + "whatwg-url@14.2.0": { + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dependencies": [ + "tr46", + "webidl-conversions" + ] + }, + "which@2.0.2": { + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": [ + "isexe" + ], + "bin": true + }, + "ws@8.20.0": { + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==" + }, + "xml-name-validator@5.0.0": { + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==" + }, + "xmlchars@2.2.0": { + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + } + }, + "workspace": { + "dependencies": [ + "npm:@pokujs/dom@^1.1.0" + ], + "packageJson": { + "dependencies": [ + "npm:@happy-dom/global-registrator@^20.8.9", + "npm:@ianvs/prettier-plugin-sort-imports@^4.7.0", + "npm:@pokujs/dom@^1.1.1", + "npm:@testing-library/dom@^10.4.1", + "npm:@types/jsdom@^28.0.1", + "npm:@types/node@^25.5.0", + "npm:@types/react-dom@^19.2.3", + "npm:@types/react@^19.2.14", + "npm:cross-env@^10.1.0", + "npm:happy-dom@^20.8.9", + "npm:jsdom@^26.1.0", + "npm:poku@4.2.0", + "npm:prettier@^3.6.2", + "npm:react-dom@^19.2.4", + "npm:react@^19.2.4", + "npm:rimraf@^6.0.1", + "npm:tsup@^8.5.0", + "npm:tsx@^4.21.0", + "npm:typescript@^6.0.2" + ] + } + } +} diff --git a/package-lock.json b/package-lock.json index 3acbc4c..47f1ee9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,12 +9,12 @@ "version": "1.2.1", "license": "MIT", "dependencies": { - "@pokujs/dom": "^1.1.0", "@testing-library/dom": "^10.4.1" }, "devDependencies": { "@happy-dom/global-registrator": "^20.8.9", "@ianvs/prettier-plugin-sort-imports": "^4.7.0", + "@pokujs/dom": "^1.1.1", "@types/jsdom": "^28.0.1", "@types/node": "^25.5.0", "@types/react": "^19.2.14", @@ -61,7 +61,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@csstools/css-calc": "^2.1.3", @@ -208,7 +208,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", - "devOptional": true, + "dev": true, "funding": [ { "type": "github", @@ -228,7 +228,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", - "devOptional": true, + "dev": true, "funding": [ { "type": "github", @@ -252,7 +252,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", - "devOptional": true, + "dev": true, "funding": [ { "type": "github", @@ -280,7 +280,7 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", - "devOptional": true, + "dev": true, "funding": [ { "type": "github", @@ -303,7 +303,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", - "devOptional": true, + "dev": true, "funding": [ { "type": "github", @@ -772,7 +772,7 @@ "version": "20.8.9", "resolved": "https://registry.npmjs.org/@happy-dom/global-registrator/-/global-registrator-20.8.9.tgz", "integrity": "sha512-DtZeRRHY9A/bisTJziUBBPrdnPui7+R185G/hzi6/Boymhqh7/wi53AY+IvQHS1+7OPaqfO/1XNpngNwthLz+A==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@types/node": ">=20.0.0", @@ -857,9 +857,10 @@ } }, "node_modules/@pokujs/dom": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pokujs/dom/-/dom-1.1.0.tgz", - "integrity": "sha512-0Cp3KLirW4mOXE11l2a0q0b6qsgorh3iqZxd1RiL69amc7uOQm+QJ96ETwr9GRkIfxa2wCPX/0JrKhMNY1T10Q==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@pokujs/dom/-/dom-1.1.1.tgz", + "integrity": "sha512-qK9JRz9tDgcO4l+QibqwGaWpDeQDKHP7y0Y9b039ieK86kY51wf0WyOi7iDfeKJQ2Quk9vIKBqDaagzJvaaX/A==", + "dev": true, "license": "MIT", "dependencies": { "@testing-library/dom": "^10.4.1" @@ -871,15 +872,11 @@ "typescript": ">=6.x.x" }, "peerDependencies": { - "@happy-dom/global-registrator": ">=20", "happy-dom": ">=20", "jsdom": ">=22", "poku": ">=4.1.0" }, "peerDependenciesMeta": { - "@happy-dom/global-registrator": { - "optional": true - }, "happy-dom": { "optional": true }, @@ -1287,7 +1284,7 @@ "version": "25.5.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz", "integrity": "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~7.18.0" @@ -1297,7 +1294,7 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@types/react": { @@ -1331,14 +1328,14 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz", "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==", - "devOptional": true, + "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==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -1361,7 +1358,7 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">= 14" @@ -1533,7 +1530,7 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@asamuzakjp/css-color": "^3.2.0", @@ -1554,7 +1551,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "whatwg-mimetype": "^4.0.0", @@ -1568,7 +1565,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -1578,7 +1575,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1596,7 +1593,7 @@ "version": "10.6.0", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/dequal": { @@ -1618,7 +1615,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", - "devOptional": true, + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -1749,7 +1746,7 @@ "version": "20.8.9", "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-20.8.9.tgz", "integrity": "sha512-Tz23LR9T9jOGVZm2x1EPdXqwA37G/owYMxRwU0E4miurAtFsPMQ1d2Jc2okUaSjZqAFz2oEn3FLXC5a0a+siyA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@types/node": ">=20.0.0", @@ -1767,7 +1764,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "whatwg-encoding": "^3.1.1" @@ -1780,7 +1777,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.0", @@ -1794,7 +1791,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.2", @@ -1808,7 +1805,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -1821,7 +1818,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/isexe": { @@ -1851,7 +1848,7 @@ "version": "26.1.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "cssstyle": "^4.2.1", @@ -1891,7 +1888,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -1944,7 +1941,7 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "devOptional": true, + "dev": true, "license": "ISC" }, "node_modules/lz-string": { @@ -2009,7 +2006,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/mz": { @@ -2028,7 +2025,7 @@ "version": "2.2.23", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", "integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/object-assign": { @@ -2052,7 +2049,7 @@ "version": "7.3.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "entities": "^6.0.0" @@ -2065,7 +2062,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "devOptional": true, + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -2163,6 +2160,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/poku/-/poku-4.2.0.tgz", "integrity": "sha512-GygMGFGgEJ9kfs6Z+QPg/ODs9OF3oGHN8+hYIxtBox3pwYISO+Vu660vH1e+YzjpGoaoy2o5y6YwE1tX5yZx3Q==", + "dev": true, "license": "MIT", "bin": { "poku": "lib/bin/index.js" @@ -2255,7 +2253,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -2393,21 +2391,21 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "xmlchars": "^2.2.0" @@ -2496,7 +2494,7 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/thenify": { @@ -2550,7 +2548,7 @@ "version": "6.1.86", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "tldts-core": "^6.1.86" @@ -2563,14 +2561,14 @@ "version": "6.1.86", "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/tough-cookie": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", - "devOptional": true, + "dev": true, "license": "BSD-3-Clause", "dependencies": { "tldts": "^6.1.32" @@ -2583,7 +2581,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "punycode": "^2.3.1" @@ -2714,7 +2712,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "xml-name-validator": "^5.0.0" @@ -2727,7 +2725,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "devOptional": true, + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -2738,7 +2736,7 @@ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "iconv-lite": "0.6.3" @@ -2751,7 +2749,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -2761,7 +2759,7 @@ "version": "14.2.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "tr46": "^5.1.0", @@ -2791,7 +2789,7 @@ "version": "8.20.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -2813,7 +2811,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=18" @@ -2823,7 +2821,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "devOptional": true, + "dev": true, "license": "MIT" } } diff --git a/package.json b/package.json index 3fded9b..b67b6c4 100644 --- a/package.json +++ b/package.json @@ -31,11 +31,19 @@ "typescript": ">=6.x.x" }, "scripts": { - "test": "npm run test:happy && npm run test:jsdom", + "test": "node --import=tsx run.test.ts", "test:happy": "cross-env POKU_REACT_TEST_DOM=happy-dom node --import=tsx ./node_modules/poku/lib/bin/index.js tests --showLogs", + "test:happy:none": "cross-env POKU_REACT_TEST_DOM=happy-dom node --import=tsx ./node_modules/poku/lib/bin/index.js tests --showLogs --isolation=none", + "test:happy:process": "cross-env POKU_REACT_TEST_DOM=happy-dom node --import=tsx ./node_modules/poku/lib/bin/index.js tests --showLogs --isolation=process", "test:jsdom": "cross-env POKU_REACT_TEST_DOM=jsdom node --import=tsx ./node_modules/poku/lib/bin/index.js tests --showLogs", - "test:bun": "cross-env POKU_REACT_TEST_DOM=happy-dom bun ./node_modules/poku/lib/bin/index.js tests --showLogs && cross-env POKU_REACT_TEST_DOM=jsdom bun ./node_modules/poku/lib/bin/index.js tests --showLogs", - "test:deno": "cross-env POKU_REACT_TEST_DOM=happy-dom deno run -A npm:poku tests --showLogs", + "test:jsdom:none": "cross-env POKU_REACT_TEST_DOM=jsdom node --import=tsx ./node_modules/poku/lib/bin/index.js tests --showLogs --isolation=none", + "test:jsdom:process": "cross-env POKU_REACT_TEST_DOM=jsdom node --import=tsx ./node_modules/poku/lib/bin/index.js tests --showLogs --isolation=process", + "test:bun": "bun run.test.ts", + "test:bun:none": "cross-env POKU_REACT_TEST_DOM=happy-dom bun ./node_modules/poku/lib/bin/index.js tests --showLogs --isolation=none && cross-env POKU_REACT_TEST_DOM=jsdom bun ./node_modules/poku/lib/bin/index.js tests --showLogs --isolation=none", + "test:bun:process": "cross-env POKU_REACT_TEST_DOM=happy-dom bun ./node_modules/poku/lib/bin/index.js tests --showLogs --isolation=process && cross-env POKU_REACT_TEST_DOM=jsdom bun ./node_modules/poku/lib/bin/index.js tests --showLogs --isolation=process", + "test:deno": "deno run -A run.test.ts", + "test:deno:none": "cross-env POKU_REACT_TEST_DOM=happy-dom deno run -A npm:poku tests --showLogs --isolation=none", + "test:deno:process": "cross-env POKU_REACT_TEST_DOM=happy-dom deno run -A npm:poku tests --showLogs --isolation=process", "clean": "rimraf dist", "build": "tsup src/index.ts src/plugin.ts src/react-testing.ts src/dom-setup-happy.ts src/dom-setup-jsdom.ts --format esm --dts --target node20 --sourcemap --clean --tsconfig tsconfig.tsup.json", "typecheck": "tsc -p tsconfig.build.json --noEmit", @@ -68,7 +76,6 @@ "provenance": true }, "dependencies": { - "@pokujs/dom": "^1.1.0", "@testing-library/dom": "^10.4.1" }, "peerDependencies": { @@ -91,10 +98,11 @@ } }, "devDependencies": { - "@ianvs/prettier-plugin-sort-imports": "^4.7.0", "@happy-dom/global-registrator": "^20.8.9", - "@types/node": "^25.5.0", + "@ianvs/prettier-plugin-sort-imports": "^4.7.0", + "@pokujs/dom": "^1.1.1", "@types/jsdom": "^28.0.1", + "@types/node": "^25.5.0", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", "cross-env": "^10.1.0", diff --git a/run.test.ts b/run.test.ts new file mode 100644 index 0000000..1bb466c --- /dev/null +++ b/run.test.ts @@ -0,0 +1,22 @@ +import { assert, poku } from 'poku'; +import { reactTestingPlugin } from './src/plugin.ts'; + +// isolation: 'none' — test files run in the same process; suites must be sequential +const happyCode = await poku('tests', { + noExit: true, + isolation: 'none', + plugins: [reactTestingPlugin({ dom: 'happy-dom' })], +}); + +assert.strictEqual(happyCode, 0, 'happy-dom suite'); + +// jsdom is not compatible with Deno +if (typeof Deno === 'undefined') { + const jsdomCode = await poku('tests', { + noExit: true, + isolation: 'none', + plugins: [reactTestingPlugin({ dom: 'jsdom' })], + }); + + assert.strictEqual(jsdomCode, 0, 'jsdom suite'); +} From 01c24e562ead534211ac17f9753c7ac6a008fac8 Mon Sep 17 00:00:00 2001 From: lojhan Date: Sun, 5 Apr 2026 17:56:02 -0300 Subject: [PATCH 8/9] chore: bump @pokujs/dom to ^1.1.2 --- deno.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deno.json b/deno.json index a7c7920..2dc131c 100644 --- a/deno.json +++ b/deno.json @@ -1,6 +1,6 @@ { "nodeModulesDir": "auto", "imports": { - "@pokujs/dom": "npm:@pokujs/dom@^1.1.0" + "@pokujs/dom": "npm:@pokujs/dom@^1.1.2" } } diff --git a/package.json b/package.json index b67b6c4..e8927e8 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "devDependencies": { "@happy-dom/global-registrator": "^20.8.9", "@ianvs/prettier-plugin-sort-imports": "^4.7.0", - "@pokujs/dom": "^1.1.1", + "@pokujs/dom": "^1.1.2", "@types/jsdom": "^28.0.1", "@types/node": "^25.5.0", "@types/react": "^19.2.14", From 4d45e5d422ccb910d3fd43f979e73d537876b3ef Mon Sep 17 00:00:00 2001 From: lojhan Date: Sun, 5 Apr 2026 17:56:51 -0300 Subject: [PATCH 9/9] chore: update package-lock.json for @pokujs/dom ^1.1.2 --- package-lock.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 47f1ee9..381ea60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "devDependencies": { "@happy-dom/global-registrator": "^20.8.9", "@ianvs/prettier-plugin-sort-imports": "^4.7.0", - "@pokujs/dom": "^1.1.1", + "@pokujs/dom": "^1.1.2", "@types/jsdom": "^28.0.1", "@types/node": "^25.5.0", "@types/react": "^19.2.14", @@ -857,9 +857,9 @@ } }, "node_modules/@pokujs/dom": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@pokujs/dom/-/dom-1.1.1.tgz", - "integrity": "sha512-qK9JRz9tDgcO4l+QibqwGaWpDeQDKHP7y0Y9b039ieK86kY51wf0WyOi7iDfeKJQ2Quk9vIKBqDaagzJvaaX/A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@pokujs/dom/-/dom-1.1.2.tgz", + "integrity": "sha512-Bs9blOGDABsgNdKBoMt7EoB0attpI83VF+LCfc2qU1BVFJQ6bRWFqniNIFWZAJOfT+qlyRcxIITmpQHYlRmLew==", "dev": true, "license": "MIT", "dependencies": {