From d57215363a11ab484e7181005c697cb76e7e9989 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 10:14:23 +0000 Subject: [PATCH] Add @amritk/mini-lynx-rsbuild-plugin and a device starter app MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Getting a mini-lynx app onto a phone took an undocumented pile of rspack wiring that every consumer would have written once each, wrongly. This is that wiring, published, plus the four-file app it builds and a record of what about the loop is actually verified. A Lynx template is not a bundle with an entry point. It is a container with two code slots — a main-thread chunk the engine executes to build the first screen and a background chunk it loads as /app-service.js — plus CSS the encoder compiles. rspeedy builds the container, but which code goes in which slot is the framework's to say, and every framework says it in a plugin of its own: ReactLynx's is @lynx-js/react-rsbuild-plugin, and there is no framework-agnostic one beneath it — @lynx-js/rsbuild-plugin, which sounds like one, is the dev server and the per-thread minifier split. pluginMiniLynx() splits one source.entry into a main-thread entry and a background entry, adds LynxTemplatePlugin and LynxEncodePlugin, sets the lynx:main-thread asset flag the encoder splits on, wraps the background chunk for the engine's module loader, and points the JSX transform at @amritk/mini-lynx. The asset flag is the sharp edge: nothing sets it for a runtime that is not ReactLynx and nothing complains when it is missing, so without it the build succeeds, the template encodes, and the device shows a blank screen. In dev the background chunk also gets the dev-server client and @rspack/core/hot/dev-server. Nothing accepts a hot update and nothing should — a component runs once here, so there is no live module graph for a diff to be applied to — and an update with no acceptor falls through to a page reload through the devtool, which is correct precisely because renderPage claims removeComponents. Two things about the package are unlike the rest of the repo. Its module load must stay side-effect free, because LynxEncodePlugin opens a worker pool on import and dist-smoke imports every published module under Node while consumer-e2e imports the entry from an install carrying no @lynx-js/* at all; both heavy imports are dynamic. And its test runs the artifact rather than asserting on a config: two real rspeedy builds, with and without a background module, then the built main-thread chunk executed in a node:vm context whose globals are createFakeEngine's Element PAPI, asserting on the tree it renders, on firstScreen, and on a tap mutating the existing element rather than replacing it. apps/starter-mini-lynx is the consumer: counter, globalProps, and the native bridge's round-trip on screen, because a missing background chunk is otherwise invisible. Its own suite drives the entry the way the engine does, which doubles as the shortest demonstration that an app on this runtime needs no device to be tested. docs/mini-lynx-explorer.md documents the loop and, more usefully, splits it into what is checked in CI, what was checked by hand against the real dev server (server starts, the LAN URL serves a real encoded template, an edit rebuilds and the next fetch carries it), and what no device was available to answer: that Explorer renders this template, that the reload fires on save, that events reach handlers on hardware, and layout. The phone half is unproven and says so. --- .changeset/plain-donkeys-build.md | 28 + .claude/architecture.md | 70 +- AGENTS.md | 28 +- CONTRIBUTING.md | 15 +- README.md | 19 +- apps/starter-mini-lynx/README.md | 66 ++ apps/starter-mini-lynx/lynx.config.ts | 15 + apps/starter-mini-lynx/package.json | 27 + apps/starter-mini-lynx/src/app.css | 50 ++ apps/starter-mini-lynx/src/app.test.ts | 65 ++ apps/starter-mini-lynx/src/background.ts | 16 + apps/starter-mini-lynx/src/main-thread.tsx | 78 ++ apps/starter-mini-lynx/tsconfig.json | 14 + apps/starter-mini-lynx/vitest.config.ts | 17 + bun.lock | 796 +++++++++++++++++- docs/mini-lynx-explorer.md | 195 +++++ llms-full.txt | 154 ++++ llms.txt | 1 + package.json | 4 +- packages/mini-lynx-rsbuild-plugin/AGENTS.md | 96 +++ packages/mini-lynx-rsbuild-plugin/AI.md | 129 +++ packages/mini-lynx-rsbuild-plugin/README.md | 158 ++++ .../fixture/README.md | 8 + .../fixture/src/app.css | 9 + .../fixture/src/background.ts | 3 + .../fixture/src/main-thread.tsx | 14 + .../mini-lynx-rsbuild-plugin/package.json | 75 ++ .../src/background-stub.ts | 10 + .../src/build.test.ts | 282 +++++++ .../mini-lynx-rsbuild-plugin/src/index.ts | 9 + .../src/main-thread-info.ts | 43 + .../mini-lynx-rsbuild-plugin/src/plugin.ts | 237 ++++++ .../tsconfig.build.json | 9 + .../mini-lynx-rsbuild-plugin/tsconfig.json | 10 + packages/mini-lynx/AGENTS.md | 16 + packages/mini-lynx/AI.md | 22 + packages/mini-lynx/README.md | 34 + scripts/consumer-e2e.test.ts | 1 + 38 files changed, 2798 insertions(+), 25 deletions(-) create mode 100644 .changeset/plain-donkeys-build.md create mode 100644 apps/starter-mini-lynx/README.md create mode 100644 apps/starter-mini-lynx/lynx.config.ts create mode 100644 apps/starter-mini-lynx/package.json create mode 100644 apps/starter-mini-lynx/src/app.css create mode 100644 apps/starter-mini-lynx/src/app.test.ts create mode 100644 apps/starter-mini-lynx/src/background.ts create mode 100644 apps/starter-mini-lynx/src/main-thread.tsx create mode 100644 apps/starter-mini-lynx/tsconfig.json create mode 100644 apps/starter-mini-lynx/vitest.config.ts create mode 100644 docs/mini-lynx-explorer.md create mode 100644 packages/mini-lynx-rsbuild-plugin/AGENTS.md create mode 100644 packages/mini-lynx-rsbuild-plugin/AI.md create mode 100644 packages/mini-lynx-rsbuild-plugin/README.md create mode 100644 packages/mini-lynx-rsbuild-plugin/fixture/README.md create mode 100644 packages/mini-lynx-rsbuild-plugin/fixture/src/app.css create mode 100644 packages/mini-lynx-rsbuild-plugin/fixture/src/background.ts create mode 100644 packages/mini-lynx-rsbuild-plugin/fixture/src/main-thread.tsx create mode 100644 packages/mini-lynx-rsbuild-plugin/package.json create mode 100644 packages/mini-lynx-rsbuild-plugin/src/background-stub.ts create mode 100644 packages/mini-lynx-rsbuild-plugin/src/build.test.ts create mode 100644 packages/mini-lynx-rsbuild-plugin/src/index.ts create mode 100644 packages/mini-lynx-rsbuild-plugin/src/main-thread-info.ts create mode 100644 packages/mini-lynx-rsbuild-plugin/src/plugin.ts create mode 100644 packages/mini-lynx-rsbuild-plugin/tsconfig.build.json create mode 100644 packages/mini-lynx-rsbuild-plugin/tsconfig.json diff --git a/.changeset/plain-donkeys-build.md b/.changeset/plain-donkeys-build.md new file mode 100644 index 0000000..632ebf7 --- /dev/null +++ b/.changeset/plain-donkeys-build.md @@ -0,0 +1,28 @@ +--- +'@amritk/mini-lynx-rsbuild-plugin': minor +--- + +Add `@amritk/mini-lynx-rsbuild-plugin` — the rspeedy build for a +`@amritk/mini-lynx` app, so `rspeedy dev` → QR code → Lynx Explorer works on day +one. + +A Lynx template is a container with two code slots — a main-thread chunk the +engine executes to build the first screen and a background chunk it loads as +`/app-service.js` — plus CSS the encoder compiles. rspeedy builds the container; +which code goes in which slot is the framework's to say, and every framework +says it in a plugin of its own. This is that plugin for a runtime that renders +on the main thread and drives the Element PAPI itself: `pluginMiniLynx()` splits +one entry into two chunks, adds the template plugin and encoder, sets the +`lynx:main-thread` asset flag the encoder splits on, wraps the background chunk +for the engine's module loader, and points the JSX transform at +`@amritk/mini-lynx`. + +In `dev` it wires the dev-server client and a devtool reload. Nothing hot-updates +and nothing should — a component runs once here — so an update no module accepts +falls through to a page reload, which is safe because `renderPage` claims +`removeComponents`. + +`apps/starter-mini-lynx` is a four-file app built through it, and +`docs/mini-lynx-explorer.md` records the loop along with what has been verified +(one real build per commit, whose main-thread chunk is executed against the fake +Element PAPI and asserted on) and what a device still has to answer. diff --git a/.claude/architecture.md b/.claude/architecture.md index cfdef84..c5d80aa 100644 --- a/.claude/architecture.md +++ b/.claude/architecture.md @@ -38,10 +38,12 @@ mini/ │ ├── lynx-location/ # @amritk/lynx-location — the second, built from its shape │ ├── lynx-dialogs/ # @amritk/lynx-dialogs — the third: date picker, sheet, alert │ ├── lynx-deep-linking/ # @amritk/lynx-deep-linking — the fourth, links in and out -│ └── lynx-secure-storage/ # @amritk/lynx-secure-storage — the fifth, a credential on disk -├── apps/ # Private kitchen-sink playgrounds, deployed to Cloudflare +│ ├── lynx-secure-storage/ # @amritk/lynx-secure-storage — the fifth, a credential on disk +│ └── mini-lynx-rsbuild-plugin/ # @amritk/mini-lynx-rsbuild-plugin — the rspeedy build +├── apps/ # Private apps: two playgrounds, one device starter │ ├── playground-mini/ # every @amritk/mini entry point, running -│ └── playground-mini-lynx/# every @amritk/mini-lynx entry point, through a DOM Element PAPI +│ ├── playground-mini-lynx/# every @amritk/mini-lynx entry point, through a DOM Element PAPI +│ └── starter-mini-lynx/ # a real .lynx.bundle, built by rspeedy, run in Lynx Explorer ├── .claude/ # Developer guidelines ├── .changeset/ # Changesets config (release automation) ├── .github/ # CI, release, bench, issue & PR templates @@ -418,6 +420,53 @@ behaviour are all platform behaviours, and all three are what the package is *for*. The caveat is carried in its `README.md`, `AI.md` and `AGENTS.md` exactly as its siblings carry theirs. +### `@amritk/mini-lynx-rsbuild-plugin` (`packages/mini-lynx-rsbuild-plugin`) + +The only package here that runs on a laptop rather than on a phone: one rsbuild +plugin that teaches [rspeedy](https://lynxjs.org/rspeedy) how to build a +`@amritk/mini-lynx` app into a `.lynx.bundle`. + +It exists because of a shape worth stating once. A Lynx template is not a bundle +with an entry point; it is a container with two code slots — a main-thread chunk +the engine executes to build the first screen, and a background chunk it loads +as `/app-service.js` — plus CSS the encoder compiles. rspeedy builds the +container, but **which code goes in which slot is the framework's to say**, and +every framework says it in a plugin of its own. `@lynx-js/react-rsbuild-plugin` +is ReactLynx's, and there is no framework-agnostic one beneath it: +`@lynx-js/rsbuild-plugin`, which sounds like one, is the dev server and the +per-thread minifier split. So the distance between "this runtime works" and "you +can run it on your phone" was ~150 lines of rspack wiring that every consumer +would otherwise write once each, wrongly. + +What it does: splits one `source.entry` into a main-thread entry and a +background entry, adds `LynxTemplatePlugin` and `LynxEncodePlugin`, flags the +main-thread chunk with the `lynx:main-thread` asset info the encoder splits on, +wraps the background chunk for the engine's module loader, and points the JSX +transform at `@amritk/mini-lynx`. In `dev` it also puts the dev-server client +and `@rspack/core/hot/dev-server` on the front of the background chunk, so an +edit reloads the page through the devtool — there is no hot update here, and +there should not be: a component runs once, so there is nothing for a module +diff to be applied to, and `renderPage`'s `removeComponents` is what makes the +reload correct. + +Two things about it are unlike the rest of the repo: + +- **Its module load must stay side-effect free.** `@lynx-js/template-webpack-plugin` + opens a worker pool on import, and `scripts/dist-smoke.test.ts` imports every + published module under Node while `scripts/consumer-e2e.test.ts` imports the + entry from an install that has no `@lynx-js/*` in it at all. Both heavy + imports are dynamic, inside `modifyBundlerChain`. +- **Its test runs the artifact.** `src/build.test.ts` performs one real rspeedy + build and then executes the built main-thread chunk in a `node:vm` context + whose globals are `createFakeEngine`'s Element PAPI, asserting on the tree it + renders and on `firstScreen`. Everything this plugin can get wrong — a JSX + transform pointed at React, a wrapper on the wrong chunk, a missing + main-thread flag — is a template that encodes cleanly and a device that shows + nothing, so asserting on the config would assert on the wrong thing. + +[`docs/mini-lynx-explorer.md`](../docs/mini-lynx-explorer.md) records the loop +and, more usefully, which links in it have been verified and which have not. + ## The playgrounds (`apps/`) Two private, unpublished apps — `@amritk/playground-mini` and @@ -467,6 +516,21 @@ Two conventions keep them honest, and both are worth preserving: without throwing, which is the cheapest guard against a screen that only fails for whoever next opens that tab. +### `apps/starter-mini-lynx` — the third app, and not a playground + +Four files that build to a real `.lynx.bundle` and run on a device through Lynx +Explorer. It is the build plugin's consumer, in the sense the playgrounds are +the runtimes' consumers, and it is the only app here that does not run in a +browser: `bun run dev` prints a QR code rather than opening localhost. + +It is deliberately small. A playground's job is coverage; a starter's is to be +copied, so it carries a counter, `globalProps`, and the native bridge's +round-trip — the last because a missing background chunk is otherwise invisible, +and putting the answer on screen turns it into something a person holding a +phone can read. Its `src/app.test.ts` drives the entry the way the engine does, +which doubles as the shortest demonstration that an app on this runtime needs no +device to be tested. + `bun run check:reactivity` scans `apps/` alongside `packages/` for the same reason — the called-signal footgun is a consumer's mistake to make, so the consumer-shaped code is where it is most likely to appear. diff --git a/AGENTS.md b/AGENTS.md index b352437..240d74e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -80,12 +80,29 @@ both re-export it from the subpath it already lived on. Each is independently published and carries its own `AGENTS.md` with the invariants that package cannot break. +One package is not a runtime at all: +[`packages/mini-lynx-rsbuild-plugin`](./packages/mini-lynx-rsbuild-plugin) — +`@amritk/mini-lynx-rsbuild-plugin`, the rspeedy build for a mini-lynx app. It +runs on a laptop rather than on a phone, and it exists because a Lynx template +is a container with two code slots rather than a bundle with an entry point: +which code goes in which slot is the framework's to say, ReactLynx says it in +`@lynx-js/react-rsbuild-plugin`, and there is no framework-agnostic plugin +underneath to reuse. Its own `AGENTS.md` carries the invariants; the loop it +serves, and what about that loop has and has not been verified, is +[`docs/mini-lynx-explorer.md`](./docs/mini-lynx-explorer.md). + Alongside them sit two private kitchen-sink playgrounds — `apps/playground-mini` and `apps/playground-mini-lynx` — that exercise every public entry point and deploy to Cloudflare Workers as static SPAs. They are the only code here written the way a consumer writes it, which makes them the fastest way to see a change and the place composition-level defects surface first. +A third app, `apps/starter-mini-lynx`, is a **starter** rather than a +playground: four files, built by rspeedy into a real `.lynx.bundle` and opened +on a device through Lynx Explorer. It is the build plugin's playground in the +sense the rule below means — the only place that package is used the way a +consumer uses it — and the only app here that does not run in a browser. + `apps/playground-mini-lynx` covers the bridge and all five native modules too, which a browser has no more of than it has an engine. Its `src/lib/fake-device.ts` is the answer: it installs both halves of the bridge over the fake contexts the @@ -103,6 +120,13 @@ and every composition-level defect this repo has found was found there rather than in a suite. A package with no screen is a package nobody has actually tried. +The rule is about *being used like a consumer uses it*, not about the screen. +`@amritk/mini-lynx-rsbuild-plugin` has no runtime surface to render, so its +equivalent is `apps/starter-mini-lynx`: a real app that builds through it, plus +a test that runs one real rspeedy build and drives the artifact. A build-time +package is finished when a change to it can break something a consumer would +notice, in this repo, without a device. + ## Workflow ```bash @@ -112,8 +136,8 @@ bun run check # biome lint + format check bun run check:reactivity # guard the compilerless-JSX called-signal footgun (packages + apps) bun run check:ai-docs # every package's AI.md against what that package actually exports bun run check:android # compile the notifications Kotlin (needs ANDROID_HOME; skips without) -bun run types:check # type-check both packages and both playgrounds -bun run build # build both packages and both playgrounds +bun run types:check # type-check every package and every app +bun run build # build every package and every app (the starter builds a .lynx.bundle) bun run test:dist # load and drive the built dist/ artifacts (needs a prior build) bun run bench -- --baseline # bundle-size delta against another checkout ``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2574e32..173f1df 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,20 +21,25 @@ You'll need [Bun](https://bun.sh) ≥ 1.1. | `bun run format` | Auto-format with biome | | `bun run check:reactivity` | Catch signals frozen by being called in JSX | | `bun run check:ai-docs` | Check every package's `AI.md` against what it publishes | -| `bun run types:check` | Type-check both packages and both playgrounds | -| `bun run build` | Build both packages and both playgrounds | +| `bun run types:check` | Type-check every package and every app | +| `bun run build` | Build every package and every app | | `bun run test:dist` | Load, drive and npm-install the built artifacts (needs a prior build) | Per package: `bun run --filter='@amritk/mini' test` (and `build`, `types:check`). -`bun run test` covers `packages/*` only — the kitchen-sink playgrounds under -`apps/` carry no tests of their own, and `bun run build` / `bun run types:check` -are what keep them honest. Run one with +`bun run test` covers `packages/*` plus the two apps that have suites of their +own; `apps/playground-mini` has none, and `bun run build` / `bun run types:check` +are what keep it honest. Run one with `bun run --filter='@amritk/playground-mini' dev`, and see [`apps/playground-mini`](./apps/playground-mini/README.md) and [`apps/playground-mini-lynx`](./apps/playground-mini-lynx/README.md) for what each demonstrates. +`apps/starter-mini-lynx` is the odd one out: not a playground but a four-file +starter that rspeedy builds into a real `.lynx.bundle` for +[Lynx Explorer](./docs/mini-lynx-explorer.md). `bun run --filter='@amritk/starter-mini-lynx' dev` +prints a QR code rather than opening a browser. + ## Workflow 1. Create a branch off `main`. diff --git a/README.md b/README.md index 6d24f62..c71a2c1 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,13 @@ shapes: | **[`@amritk/mini`](./packages/mini)** | The DOM. Reactive bindings, keyed lists, static-template cloning, and a compilerless JSX runtime. | | **[`@amritk/mini-lynx`](./packages/mini-lynx)** | **Lynx**, through its Element PAPI. The engine's own elements, attributes and events — no vocabulary in between. | -A third package, **[`@amritk/mini-helpers`](./packages/mini-helpers)**, holds the +Getting a Lynx app onto a phone takes one more package — +**[`@amritk/mini-lynx-rsbuild-plugin`](./packages/mini-lynx-rsbuild-plugin)**, +the [rspeedy](https://lynxjs.org/rspeedy) build for a mini-lynx app: two chunks, +one `.lynx.bundle`, and a QR code Lynx Explorer scans. See +[`docs/mini-lynx-explorer.md`](./docs/mini-lynx-explorer.md). + +A third runtime package, **[`@amritk/mini-helpers`](./packages/mini-helpers)**, holds the handful of helpers that turned out identical in both — route matching, query parsing, JSON Schema compilation. Both packages depend on it and re-export it, so you never import it directly; it is separate only because its charter is worth @@ -125,6 +131,8 @@ package READMEs: subpaths. - [`@amritk/mini-helpers`](./packages/mini-helpers/README.md) — the pure helpers both of the above share, and the bar for adding to them. +- [`@amritk/mini-lynx-rsbuild-plugin`](./packages/mini-lynx-rsbuild-plugin/README.md) + — the rspeedy build: `rspeedy dev`, a QR code, and the app on your phone. ## Playgrounds @@ -145,6 +153,15 @@ bun run --filter '@amritk/playground-mini' dev bun run --filter '@amritk/playground-mini-lynx' dev ``` +A third app is not a playground but a **starter**: +[`starter-mini-lynx`](./apps/starter-mini-lynx/README.md) — four files, built by +rspeedy into a real `.lynx.bundle` and opened on a phone through Lynx Explorer. +It is the only app here that runs on a device rather than in a browser. + +```sh +bun run --filter '@amritk/starter-mini-lynx' dev # prints a QR code +``` + ## For AI agents & LLMs Each package ships an **`AI.md`** next to its `README.md`: a mental model, a diff --git a/apps/starter-mini-lynx/README.md b/apps/starter-mini-lynx/README.md new file mode 100644 index 0000000..7c06c5e --- /dev/null +++ b/apps/starter-mini-lynx/README.md @@ -0,0 +1,66 @@ +# @amritk/starter-mini-lynx + +The smallest **real** `@amritk/mini-lynx` app: it builds to a `.lynx.bundle`, +`rspeedy dev` serves it, and Lynx Explorer runs it from a QR code. + +Everything else in this repo runs in a browser or a test process. This one is +for a phone. + +```bash +bun install +bun run dev # prints two QR codes; scan either with Lynx Explorer +bun run build # dist/main.lynx.bundle +bun run test # the app, driven through the fake Element PAPI — no device +``` + +The loop it belongs to, including where to get Explorer and what to check when +the phone shows nothing, is [`docs/mini-lynx-explorer.md`](../../docs/mini-lynx-explorer.md). + +## The four files + +``` +lynx.config.ts rspeedy: the entry, the QR plugin, pluginMiniLynx +src/main-thread.tsx the main-thread chunk — the whole app, and the entry +src/background.ts the background chunk — installs the native bridge +src/app.css real CSS, compiled into the template by the encoder +``` + +There is no `App.tsx` importing an `index.tsx`, and no framework entry to +extend. `renderPage(App)` at the bottom of `main-thread.tsx` **is** the entry: +it installs the global the engine calls once at startup. + +## Why two chunks + +A Lynx bundle carries two code slots, and they are two different JavaScript +contexts on the device: + +- The **main thread** runs the Element PAPI, which is what `@amritk/mini-lynx` + drives. Your components, your tree, your event handlers — a handler here runs + in the same frame as the gesture that triggered it. +- The **background thread** is the only place `NativeModules` and + `GlobalEventEmitter` exist. + +`src/background.ts` is one line: `installNativeBridge()`, the background half of +[`@amritk/mini-lynx-native`](../../packages/mini-lynx-native). The screen +labelled *background chunk* is that wire being exercised — the main-thread side +asks whether a module is reachable, the answer crosses the thread boundary, and +a signal is written when it lands. A `no answer` there means the background +chunk is not in the bundle; on a device it should say `bridge answered`. + +## What each screen is showing + +| Card | What it exercises | +| --- | --- | +| the counter | a signal driving a `` binding, and one element mutated rather than a subtree rebuilt | +| `globalProps` | the platform's own values as a signal — theme, locale, whatever your host pushes | +| `background chunk` | the two-chunk build, end to end, over the native bridge | + +## Copy it + +This directory is a starting point, not a demo of a framework's features. To +take it: copy the four files, replace `workspace:*` with the published versions +of `@amritk/mini-lynx`, `@amritk/mini-lynx-native` and +`@amritk/mini-lynx-rsbuild-plugin`, and delete this README. + +Private and never published; it exists to be read and to be the thing this +repo's build plugin is tried against. diff --git a/apps/starter-mini-lynx/lynx.config.ts b/apps/starter-mini-lynx/lynx.config.ts new file mode 100644 index 0000000..1511d7d --- /dev/null +++ b/apps/starter-mini-lynx/lynx.config.ts @@ -0,0 +1,15 @@ +import { pluginMiniLynx } from '@amritk/mini-lynx-rsbuild-plugin' +import { pluginQRCode } from '@lynx-js/qrcode-rsbuild-plugin' +import { defineConfig } from '@lynx-js/rspeedy' + +export default defineConfig({ + source: { entry: { main: './src/main-thread.tsx' } }, + plugins: [ + // What `rspeedy dev` prints for a phone to scan. `fullscreen` adds a second + // QR carrying Explorer's own `?fullscreen=true` flag, which hides its + // chrome so the screen is the app rather than the shell around it; press + // `a` in the terminal to switch between the two. + pluginQRCode({ fullscreen: true }), + pluginMiniLynx({ background: './src/background.ts' }), + ], +}) diff --git a/apps/starter-mini-lynx/package.json b/apps/starter-mini-lynx/package.json new file mode 100644 index 0000000..738dec7 --- /dev/null +++ b/apps/starter-mini-lynx/package.json @@ -0,0 +1,27 @@ +{ + "name": "@amritk/starter-mini-lynx", + "version": "0.0.0", + "private": true, + "description": "The smallest real @amritk/mini-lynx app: rspeedy dev, a QR code, and Lynx Explorer.", + "type": "module", + "scripts": { + "dev": "rspeedy dev", + "build": "rspeedy build", + "preview": "rspeedy preview", + "types:check": "tsgo -p . --noEmit", + "test": "vitest run" + }, + "dependencies": { + "@amritk/mini-lynx": "workspace:*", + "@amritk/mini-lynx-native": "workspace:*", + "@amritk/mini-lynx-rsbuild-plugin": "workspace:*" + }, + "devDependencies": { + "@lynx-js/qrcode-rsbuild-plugin": "^0.6.0", + "@lynx-js/rspeedy": "^0.16.4", + "@lynx-js/types": "^4.0.0", + "@rsbuild/core": "^2.1.10", + "typescript": "^5", + "vitest": "^4.1.5" + } +} diff --git a/apps/starter-mini-lynx/src/app.css b/apps/starter-mini-lynx/src/app.css new file mode 100644 index 0000000..12bd24b --- /dev/null +++ b/apps/starter-mini-lynx/src/app.css @@ -0,0 +1,50 @@ +/* + * Real CSS, compiled into the template by the encoder rather than shipped as + * text and applied at runtime. Lynx's own stylesheet — `linear` layout, + * `flex`, selectors, variables — so there is nothing framework-shaped here. + */ + +.screen { + display: flex; + flex-direction: column; + padding: 24px; + background-color: #0b1020; +} + +.title { + color: #a5b4fc; + font-size: 32px; + font-weight: bold; +} + +.subtitle { + color: #64748b; + font-size: 14px; + margin-bottom: 20px; +} + +.card { + display: flex; + flex-direction: column; + padding: 16px; + margin-bottom: 12px; + border-radius: 12px; + background-color: #151c33; +} + +.card-label { + color: #64748b; + font-size: 12px; + letter-spacing: 1px; +} + +.card-value { + color: #e2e8f0; + font-size: 40px; + font-weight: bold; +} + +.card-value-small { + color: #e2e8f0; + font-size: 14px; +} diff --git a/apps/starter-mini-lynx/src/app.test.ts b/apps/starter-mini-lynx/src/app.test.ts new file mode 100644 index 0000000..73710bd --- /dev/null +++ b/apps/starter-mini-lynx/src/app.test.ts @@ -0,0 +1,65 @@ +import { createFakeEngine, serializeTree } from '@amritk/mini-lynx/testing' +import { setPeerContext } from '@amritk/mini-lynx-native' +import { createFakeContexts } from '@amritk/mini-lynx-native/testing' +import { beforeEach, expect, it } from 'vitest' + +/** + * The app, driven the way the engine drives it: put a PAPI on the global + * object, call the global the entry registered, look at the tree. + * + * This is here as much to show the shape as to check the screen. An app on this + * runtime needs no device, no emulator and no browser to be tested — + * `createFakeEngine` is a complete Element PAPI, so a test against it is a test + * against the same API the phone exposes, and `main-thread.tsx` is imported + * exactly as the bundle's main-thread chunk is executed. + * + * The engine is installed as **globals** rather than with `setEngine`, because + * that is where `renderPage` looks: the PAPI is injected into the main-thread + * context as bare globals on a device, and an entry point that took its engine + * from somewhere else would be an entry point no engine could call. Passing a + * fake explicitly — `renderPage(App, { engine })` — is the other way, and it is + * the one to reach for when the app under test is not the shipping entry. + */ + +type LynxGlobals = { renderPage?: () => void } + +let engine = createFakeEngine() + +beforeEach(() => { + engine = createFakeEngine() + Object.assign(globalThis, engine.api) + + // The bridge's main-thread half talks to a peer context that exists only in a + // bundle with two chunks in it. The package publishes a fake pair for exactly + // this: the call goes out, nothing answers, and the screen shows its pending + // state instead of throwing. + setPeerContext(createFakeContexts().mainThread) +}) + +it('renders the first screen when the engine calls renderPage', async () => { + // The import runs `renderPage(App)`, which registers the global. The engine + // is what calls it, so the test does too. + await import('./main-thread') + ;(globalThis as LynxGlobals).renderPage?.() + + const tree = serializeTree(engine.page) + expect(tree).toContain('mini-lynx') + expect(tree).toContain('rspeedy → QR → Lynx Explorer') +}) + +it('counts taps by mutating the text element rather than rebuilding it', async () => { + await import('./main-thread') + ;(globalThis as LynxGlobals).renderPage?.() + + const card = engine.findAll('view').find((element) => element.classes.includes('card')) + expect(card).toBeDefined() + const value = engine.findAll('text').find((element) => element.classes.includes('card-value')) + + engine.dispatch(card as never, 'tap') + engine.dispatch(card as never, 'tap') + + expect(serializeTree(engine.page)).toContain('text="2"') + // The same element, written twice. Nothing was rebuilt to get here, which is + // the runtime's whole claim and the one an app should be able to check. + expect(engine.findAll('text').find((element) => element.classes.includes('card-value'))).toBe(value) +}) diff --git a/apps/starter-mini-lynx/src/background.ts b/apps/starter-mini-lynx/src/background.ts new file mode 100644 index 0000000..3fd56e1 --- /dev/null +++ b/apps/starter-mini-lynx/src/background.ts @@ -0,0 +1,16 @@ +/** + * The background chunk. + * + * Lynx runs `NativeModules` and `GlobalEventEmitter` only here, and this + * runtime renders only on the main thread, so the two halves of an app that + * touches native code live in two different chunks of the same bundle. The + * build wires them: `pluginMiniLynx({ background: './src/background.ts' })`. + * + * `installNativeBridge` is the whole of this side. Calls made from the + * main-thread chunk before it runs are queued rather than lost, which matters + * because the engine calls `renderPage` first. + */ + +import { installNativeBridge } from '@amritk/mini-lynx-native/background' + +installNativeBridge() diff --git a/apps/starter-mini-lynx/src/main-thread.tsx b/apps/starter-mini-lynx/src/main-thread.tsx new file mode 100644 index 0000000..49e4e25 --- /dev/null +++ b/apps/starter-mini-lynx/src/main-thread.tsx @@ -0,0 +1,78 @@ +import { globalProps, renderPage, signal } from '@amritk/mini-lynx' +import { isNativeModuleAvailable } from '@amritk/mini-lynx-native' +import './app.css' + +/** + * The main-thread chunk: the whole app, and the only file the engine executes + * to get a first screen. + * + * There is no `App.tsx` importing this or imported by it. `renderPage` at the + * bottom of the file IS the entry — it installs the global the engine calls + * once at startup — and the components above it are ordinary functions that run + * exactly once each. + */ + +/** Whether the background chunk answered. See `background.ts` for the other half. */ +const bridgeReady = signal(null) + +// Deliberately at module scope rather than inside a component: nothing native +// can be read during a build — the answer crosses a thread — so the call starts +// now and the signal it writes is what the tree is bound to. `Lynx.getDevTool` +// is asked for because the engine itself owns it, which makes a `false` here a +// statement about the bridge rather than about which modules an app linked. +void isNativeModuleAvailable('LynxDevToolSetModule') + .then((available) => bridgeReady(available)) + .catch(() => bridgeReady(false)) + +const Counter = () => { + const count = signal(0) + + return ( + count(count() + 1)}> + tap anywhere on this card + {/* A function child is a live binding; `count()` here would be frozen at + the value it had while the tree was being built. */} + {() => `${count()}`} + + ) +} + +/** + * What the platform pushed in, as a signal. + * + * `globalProps()` is written twice by the runtime — once from + * `lynx.__globalProps` before the first frame, and again whenever native calls + * `updateGlobalProps` — so reading it inside a function child is all an app has + * to do to follow a theme or a locale change. + */ +const Platform = () => ( + + globalProps + {() => JSON.stringify(globalProps()) || '{}'} + +) + +const Bridge = () => ( + + background chunk + + {() => { + const ready = bridgeReady() + if (ready === null) return 'asking…' + return ready ? 'bridge answered' : 'no answer — is background.ts in the bundle?' + }} + + +) + +const App = () => ( + + mini-lynx + rspeedy → QR → Lynx Explorer + + + + +) + +renderPage(App) diff --git a/apps/starter-mini-lynx/tsconfig.json b/apps/starter-mini-lynx/tsconfig.json new file mode 100644 index 0000000..15a25f0 --- /dev/null +++ b/apps/starter-mini-lynx/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "jsx": "react-jsx", + "jsxImportSource": "@amritk/mini-lynx", + // `@lynx-js/types` is the tag typings — the Lynx team's, tracking the + // engine version this app pins rather than the runtime's release schedule. + // The rspeedy client types are what make `import './app.css'` a module + // rather than an error; they are the build's, in the same way. + "types": ["@lynx-js/types", "@lynx-js/rspeedy/client"], + "noEmit": true + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "lynx.config.ts", "vitest.config.ts"] +} diff --git a/apps/starter-mini-lynx/vitest.config.ts b/apps/starter-mini-lynx/vitest.config.ts new file mode 100644 index 0000000..4e929ed --- /dev/null +++ b/apps/starter-mini-lynx/vitest.config.ts @@ -0,0 +1,17 @@ +import { defineConfig } from 'vitest/config' + +/** + * The app's own suite: one file, driving the entry point the way the engine + * does. + * + * Separate from the root config, like the other playground's, because that one + * is scoped to `packages/**`. The `@amritk/*` specifiers here resolve through + * the workspace to each package's `dist`, which is what a consumer's install + * resolves to — the point of an app in this repo is to be the one place that + * happens. + */ +export default defineConfig({ + test: { + include: ['src/**/*.test.ts'], + }, +}) diff --git a/bun.lock b/bun.lock index 84038ea..dbbb569 100644 --- a/bun.lock +++ b/bun.lock @@ -18,7 +18,7 @@ }, "apps/playground-mini": { "name": "@amritk/playground-mini", - "version": "0.0.2", + "version": "0.0.3", "dependencies": { "@amritk/mini": "workspace:*", "@amritk/runtime-validators": "^0.9.0", @@ -32,7 +32,7 @@ }, "apps/playground-mini-lynx": { "name": "@amritk/playground-mini-lynx", - "version": "0.0.5", + "version": "0.0.6", "dependencies": { "@amritk/lynx-deep-linking": "workspace:*", "@amritk/lynx-dialogs": "workspace:*", @@ -52,9 +52,26 @@ "wrangler": "^4", }, }, + "apps/starter-mini-lynx": { + "name": "@amritk/starter-mini-lynx", + "version": "0.0.0", + "dependencies": { + "@amritk/mini-lynx": "workspace:*", + "@amritk/mini-lynx-native": "workspace:*", + "@amritk/mini-lynx-rsbuild-plugin": "workspace:*", + }, + "devDependencies": { + "@lynx-js/qrcode-rsbuild-plugin": "^0.6.0", + "@lynx-js/rspeedy": "^0.16.4", + "@lynx-js/types": "^4.0.0", + "@rsbuild/core": "^2.1.10", + "typescript": "^5", + "vitest": "^4.1.5", + }, + }, "packages/lynx-deep-linking": { "name": "@amritk/lynx-deep-linking", - "version": "0.2.1", + "version": "0.2.2", "dependencies": { "@amritk/mini-helpers": "workspace:*", "@amritk/mini-lynx-native": "workspace:*", @@ -71,7 +88,7 @@ }, "packages/lynx-dialogs": { "name": "@amritk/lynx-dialogs", - "version": "0.2.1", + "version": "0.2.2", "dependencies": { "@amritk/mini-lynx-native": "workspace:*", }, @@ -87,7 +104,7 @@ }, "packages/lynx-location": { "name": "@amritk/lynx-location", - "version": "0.2.1", + "version": "0.2.2", "dependencies": { "@amritk/mini-lynx-native": "workspace:*", }, @@ -103,7 +120,7 @@ }, "packages/lynx-notifications": { "name": "@amritk/lynx-notifications", - "version": "0.2.1", + "version": "0.2.2", "dependencies": { "@amritk/mini-lynx-native": "workspace:*", }, @@ -119,7 +136,7 @@ }, "packages/lynx-secure-storage": { "name": "@amritk/lynx-secure-storage", - "version": "0.1.0", + "version": "0.2.0", "dependencies": { "@amritk/mini-lynx-native": "workspace:*", }, @@ -135,7 +152,7 @@ }, "packages/mini": { "name": "@amritk/mini", - "version": "0.7.0", + "version": "0.7.1", "dependencies": { "@amritk/mini-helpers": "workspace:*", "alien-signals": "catalog:", @@ -177,7 +194,7 @@ }, "packages/mini-lynx": { "name": "@amritk/mini-lynx", - "version": "0.4.0", + "version": "0.4.1", "dependencies": { "@amritk/mini-helpers": "workspace:*", "alien-signals": "catalog:", @@ -203,7 +220,7 @@ }, "packages/mini-lynx-native": { "name": "@amritk/mini-lynx-native", - "version": "0.2.1", + "version": "0.2.2", "devDependencies": { "@lynx-js/types": "^4.0.0", "typescript": "^5", @@ -217,6 +234,31 @@ "typescript", ], }, + "packages/mini-lynx-rsbuild-plugin": { + "name": "@amritk/mini-lynx-rsbuild-plugin", + "version": "0.1.0", + "dependencies": { + "@lynx-js/runtime-wrapper-webpack-plugin": "^0.2.3", + "@lynx-js/template-webpack-plugin": "^0.15.1", + }, + "devDependencies": { + "@amritk/mini-lynx": "workspace:*", + "@amritk/mini-lynx-native": "workspace:*", + "@lynx-js/rspeedy": "^0.16.4", + "@rsbuild/core": "^2.1.10", + "@rspack/core": "^2.1.10", + "typescript": "^5", + }, + "peerDependencies": { + "@amritk/mini-lynx": ">=0.4.0", + "@lynx-js/rspeedy": ">=0.16.0", + "@rsbuild/core": "^2.0.0", + }, + "optionalPeers": [ + "@amritk/mini-lynx", + "@rsbuild/core", + ], + }, }, "catalog": { "alien-signals": "3.2.1", @@ -240,12 +282,20 @@ "@amritk/mini-lynx-native": ["@amritk/mini-lynx-native@workspace:packages/mini-lynx-native"], + "@amritk/mini-lynx-rsbuild-plugin": ["@amritk/mini-lynx-rsbuild-plugin@workspace:packages/mini-lynx-rsbuild-plugin"], + "@amritk/playground-mini": ["@amritk/playground-mini@workspace:apps/playground-mini"], "@amritk/playground-mini-lynx": ["@amritk/playground-mini-lynx@workspace:apps/playground-mini-lynx"], "@amritk/runtime-validators": ["@amritk/runtime-validators@0.9.0", "", { "dependencies": { "json-schema-typed": "^8.0.1" } }, "sha512-BNL/WefH+ZOc10EoqagiB40/FrhuvR4GdOBv9MlEo69t8BXJI7H4+MbHnJQcOJ+Vh2q+j+rF5jO/SunbDNfSBw=="], + "@amritk/starter-mini-lynx": ["@amritk/starter-mini-lynx@workspace:apps/starter-mini-lynx"], + + "@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="], + "@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="], "@biomejs/biome": ["@biomejs/biome@2.4.4", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.4", "@biomejs/cli-darwin-x64": "2.4.4", "@biomejs/cli-linux-arm64": "2.4.4", "@biomejs/cli-linux-arm64-musl": "2.4.4", "@biomejs/cli-linux-x64": "2.4.4", "@biomejs/cli-linux-x64-musl": "2.4.4", "@biomejs/cli-win32-arm64": "2.4.4", "@biomejs/cli-win32-x64": "2.4.4" }, "bin": { "biome": "bin/biome" } }, "sha512-tigwWS5KfJf0cABVd52NVaXyAVv4qpUXOWJ1rxFL8xF1RVoeS2q/LK+FHgYoKMclJCuRoCWAPy1IXaN9/mS61Q=="], @@ -314,6 +364,8 @@ "@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260721.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9paFG5cMTKz/CRixnEEnZbe5uvFPBFSDthxJHANfCWhUtBj49GSL1FPIokIg+Q+H8DGJEExU0lL92LtxD0lTxQ=="], + "@colordx/core": ["@colordx/core@5.5.0", "", {}, "sha512-3PxTH8itZzltK0U9jTwVVnjLXvnDYuq3m+QXsHkENxWiPRh4WaoLcs1SQjqgZ55kS+QyirpH5BVwzP2gMVG6EQ=="], + "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], "@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="], @@ -426,14 +478,60 @@ "@inquirer/external-editor": ["@inquirer/external-editor@1.0.3", "", { "dependencies": { "chardet": "^2.1.1", "iconv-lite": "^0.7.0" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA=="], + "@jest/pattern": ["@jest/pattern@30.4.0", "", { "dependencies": { "@types/node": "*", "jest-regex-util": "30.4.0" } }, "sha512-RAWn3+f9u8BsHijKJ71uHcFp6vmyEt6VvoWXkl6hKF3qVIuWNmudVjg12DlBPGup/frIl5UcUlH5HfEuvHpEXg=="], + + "@jest/schemas": ["@jest/schemas@30.4.1", "", { "dependencies": { "@sinclair/typebox": "^0.34.0" } }, "sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q=="], + + "@jest/types": ["@jest/types@30.4.1", "", { "dependencies": { "@jest/pattern": "30.4.0", "@jest/schemas": "30.4.1", "@types/istanbul-lib-coverage": "^2.0.6", "@types/istanbul-reports": "^3.0.4", "@types/node": "*", "@types/yargs": "^17.0.33", "chalk": "^4.1.2" } }, "sha512-f1x/vJXIfjOlEmejYpbkbgw1gOqpPECwMvMEtBqe47j7H2Hg8h8w3o3ikhSXq3MI15kg+oQ0exWO0uCtTNJLoQ=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + "@jridgewell/source-map": ["@jridgewell/source-map@0.3.11", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA=="], + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], - "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + + "@lynx-js/cache-events-webpack-plugin": ["@lynx-js/cache-events-webpack-plugin@0.2.0", "", { "dependencies": { "@lynx-js/webpack-runtime-globals": "^0.0.7" } }, "sha512-f903x00MMmWB9yIyvACAoe4im0T58JHpKnypV/ccI2gp477RJoCgXPne2x8Obgo3fTOIMHpmNMdnxFW1ej9olQ=="], + + "@lynx-js/chunk-loading-webpack-plugin": ["@lynx-js/chunk-loading-webpack-plugin@0.4.1", "", { "dependencies": { "@lynx-js/webpack-runtime-globals": "0.0.7" } }, "sha512-vZb2HiZdkVdexs2OhRVZE3FkSUPYRvdnaAKG8y47WW2NlVFj6PHzqEhkqfO1L3dm5CIEsPgOMwzgSs3BHZZ8ig=="], + + "@lynx-js/css-serializer": ["@lynx-js/css-serializer@0.1.8", "", { "dependencies": { "css-tree": "^3.2.1", "pathe": "^2.0.3" } }, "sha512-gvK6vNB/Lyr7mCBLwlXIBu7IcaJXYsxx/no3U9wBREaB5nxMwkI3Yaj3I8Q6jTEiT08AXscvJ/nUZk5ZYewh6A=="], + + "@lynx-js/debug-metadata": ["@lynx-js/debug-metadata@0.1.0", "", { "bin": { "debug-metadata": "./dist/cli.js" } }, "sha512-3N+Wgc/kIc4/aG5KpdPWKsC9MsNngygeyg9JS6IOayS8AQJ37xjVEzlz1U3aYzT9al0RJKL7w4poa0tGaXBv1g=="], + + "@lynx-js/debug-metadata-rsbuild-plugin": ["@lynx-js/debug-metadata-rsbuild-plugin@0.2.1", "", { "dependencies": { "@lynx-js/debug-metadata": "^0.1.0" } }, "sha512-uvpX41tk7TxkIs8fJqIHqOUyOhRC5BVTH4ri+B1rZI6k3yclYIKA7lSnDirgEL+92GmkInerO3Zwg9y3Zyg5hA=="], + + "@lynx-js/qrcode-rsbuild-plugin": ["@lynx-js/qrcode-rsbuild-plugin@0.6.0", "", { "peerDependencies": { "@lynx-js/rspeedy": "^0.16.0" } }, "sha512-AjRhjQH5xEJKo5VUIIsjdk6zc6qXMf4QsGvKTDuwBjuGr01sDkLLpAt+wbu9GCJvDlGA7ygNTEsxaPJPYHPmIw=="], + + "@lynx-js/rsbuild-plugin": ["@lynx-js/rsbuild-plugin@0.0.2", "", { "dependencies": { "@lynx-js/cache-events-webpack-plugin": "^0.2.0", "@lynx-js/chunk-loading-webpack-plugin": "^0.4.1" }, "peerDependencies": { "@rsbuild/core": "^2.0.0" } }, "sha512-l5N0xuRTRmK2/OnlLGocDj93s7kVDCOeos7gC++y4X4ypyhHc2FPQaIQGEOaX39TdCCvnkAdKmPxO7/AEJl5tw=="], + + "@lynx-js/rspeedy": ["@lynx-js/rspeedy@0.16.4", "", { "dependencies": { "@lynx-js/debug-metadata-rsbuild-plugin": "^0.2.1", "@lynx-js/rsbuild-plugin": "0.0.2", "@lynx-js/web-rsbuild-server-middleware": "0.24.1", "@lynx-js/webpack-dev-transport": "^0.4.0", "@lynx-js/websocket": "^0.0.4", "@rsbuild/core": "2.1.10", "@rsbuild/plugin-css-minimizer": "2.0.1", "@rsdoctor/rspack-plugin": "~1.6.1" }, "peerDependencies": { "typescript": "5.1.6 - 6.0.x" }, "optionalPeers": ["typescript"], "bin": { "rspeedy": "./bin/rspeedy.js" } }, "sha512-XK8dYXTLIpYMX+8TR098EvQh7HtcuX0KWwN9S/MOYnNaDPTpKXVJNR5NUeNWyABh5GvVVb8Ytbx47yag9dCkxA=="], + + "@lynx-js/runtime-wrapper-webpack-plugin": ["@lynx-js/runtime-wrapper-webpack-plugin@0.2.3", "", { "dependencies": { "@lynx-js/webpack-runtime-globals": "0.0.7" } }, "sha512-xqBQ+g8fJn1kPJN+7tgzypPj+FK9+8ifDVhXu9i0S6630XebdZ7ZKPehlGMNdfZPnS96Wo0EBCoEaAwJ6c9UpA=="], + + "@lynx-js/tasm": ["@lynx-js/tasm@0.0.49", "", { "bin": { "lynx-tasm": "cli.js" } }, "sha512-sI+xmLXaMvXWFN5n47kYNHFEMIEpkrz/bVvU2GwvhB26lXfYPdSNedE3bh85vfW/vAmYsB/TbKwtiNhXgN3LDw=="], + + "@lynx-js/template-webpack-plugin": ["@lynx-js/template-webpack-plugin@0.15.1", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.31", "@lynx-js/css-serializer": "0.1.8", "@lynx-js/tasm": "0.0.49", "@lynx-js/web-core": "0.24.1", "@lynx-js/webpack-runtime-globals": "^0.0.7", "@rspack/lite-tapable": "1.1.5", "css-tree": "^3.2.1", "object.groupby": "^1.0.3", "tinypool": "^2.1.0" } }, "sha512-puDjVSFLBcqGJ+D59NDx13oESRR5zGTgvlwddDNtQEH/4IkRMsLo0cD44HrBX3MAp4Rdkuw6eHLL6RVCXFCJoQ=="], "@lynx-js/types": ["@lynx-js/types@4.0.0", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-FBtBV8wt+9/CAUbTdZwvbhGjJEnyzKLWVpq5gaTHTbhDztbhdP0avZ0nHD6I5HSgAhzYNB9oDrqMt/r6YqBkng=="], + "@lynx-js/web-core": ["@lynx-js/web-core@0.24.1", "", { "dependencies": { "@lynx-js/web-elements": "0.12.8", "@lynx-js/web-worker-rpc": "0.24.1", "wasm-feature-detect": "^1.8.0" }, "peerDependencies": { "@lynx-js/css-serializer": "0.1.8", "@lynx-js/lynx-core": "0.1.4", "tslib": "^2.5.0" }, "optionalPeers": ["@lynx-js/css-serializer", "@lynx-js/lynx-core", "tslib"] }, "sha512-+HP8Pjqj56M0i5vnmvqk2IPmSaRwUdyBWSfVLZ9elFqYszXMwr9uwqitDIh4wcQBoKgJjLNcRxhPPQCcx7trMw=="], + + "@lynx-js/web-elements": ["@lynx-js/web-elements@0.12.8", "", { "dependencies": { "dompurify": "^3.4.13", "markdown-it": "^15.0.0" }, "peerDependencies": { "tslib": "^2.5.0" } }, "sha512-n3cXrlvwZZg917MdrGmWFdGyMjBfNUyBCXzEobk0AvF4KeBoIaiq9XpbNJPmbbOwWZNtDmywEgWoHLfmApok0A=="], + + "@lynx-js/web-rsbuild-server-middleware": ["@lynx-js/web-rsbuild-server-middleware@0.24.1", "", {}, "sha512-HcwOJOsW9f9PDX5K+6SeURbUNHUyol9uiW7iLdBsCoCBsSwZ4CdQJYG2sJ/6ycIAU5jD4b5+PBnpKi23ADaJzw=="], + + "@lynx-js/web-worker-rpc": ["@lynx-js/web-worker-rpc@0.24.1", "", {}, "sha512-iDXiRxVKJ7FrahwhqhRorLZDo5K7HlXCbWFY5z0iY5HnBziDnRyyedioCgp9GqpEd353l4NyPsvbY8/jo5XHkg=="], + + "@lynx-js/webpack-dev-transport": ["@lynx-js/webpack-dev-transport@0.4.0", "", {}, "sha512-+XeG9yUGM7oCWeXe/Pbxl6cBmF6JQ6jQ08rm9w8zbV6Liq1THghlcKPdj2DAS1u1WU3llSi1RGzGQabWlDwR1w=="], + + "@lynx-js/webpack-runtime-globals": ["@lynx-js/webpack-runtime-globals@0.0.7", "", {}, "sha512-HGWCIX8FMeoeCfUZpijrZO20UVp8wVHj7f+aEiMbx94H2iqIVxLzrCLZudBfvo4+WZ3kdgM8CqhU1EERKhLi0w=="], + + "@lynx-js/websocket": ["@lynx-js/websocket@0.0.4", "", { "dependencies": { "eventemitter3": "^5.0.1" } }, "sha512-yXuMiTALLNvkDz8hG+0KdkBodnyJDvyfr8bdIq6zMP9X8JAoBC/czc1HIhUgYEJ3Zee5F/vGKjNxcoSx2t1E6w=="], + "@manypkg/find-root": ["@manypkg/find-root@1.1.0", "", { "dependencies": { "@babel/runtime": "^7.5.5", "@types/node": "^12.7.1", "find-up": "^4.1.0", "fs-extra": "^8.1.0" } }, "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA=="], "@manypkg/get-packages": ["@manypkg/get-packages@1.1.3", "", { "dependencies": { "@babel/runtime": "^7.5.5", "@changesets/types": "^4.0.1", "@manypkg/find-root": "^1.1.0", "fs-extra": "^8.1.0", "globby": "^11.0.0", "read-yaml-file": "^1.1.0" } }, "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A=="], @@ -486,28 +584,130 @@ "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="], + "@rsbuild/core": ["@rsbuild/core@2.1.13", "", { "dependencies": { "@rspack/core": "~2.1.10", "@swc/helpers": "^0.5.23" }, "peerDependencies": { "core-js": ">= 3.0.0" }, "optionalPeers": ["core-js"], "bin": { "rsbuild": "./bin/rsbuild.js" } }, "sha512-Z+6MzmjOio4+bFZQ24k+7ge/oNCOdXIunAssrswTNE8AIf6mcyXpJZevRXRiOEMZasRPA8VNyh+9JngQLg729Q=="], + + "@rsbuild/plugin-check-syntax": ["@rsbuild/plugin-check-syntax@1.6.1", "", { "dependencies": { "acorn": "^8.15.0", "browserslist-to-es-version": "^1.2.0", "htmlparser2": "10.0.0", "picocolors": "^1.1.1", "source-map": "^0.7.6" }, "peerDependencies": { "@rsbuild/core": "^1.0.0 || ^2.0.0-0" }, "optionalPeers": ["@rsbuild/core"] }, "sha512-26xtEYN0QjZYoyt0lWnvIztBWjEZJvcfw7MN4f5B4SpNggmnF7F7aNPrgkY3EccXVFx1VGQBhnCkBV//OoS07Q=="], + + "@rsbuild/plugin-css-minimizer": ["@rsbuild/plugin-css-minimizer@2.0.1", "", { "dependencies": { "css-minimizer-webpack-plugin": "^8.0.0", "reduce-configs": "^1.1.2" }, "peerDependencies": { "@rsbuild/core": "^1.0.0 || ^2.0.0-0" }, "optionalPeers": ["@rsbuild/core"] }, "sha512-QZUEBLTYXwtCUVziK3XHaPv+3wLLGvO6X27sIwt12eyuIMSA5WbeuLD9y1hwsXu27jZBofP6s/mdV5H5bA/FOg=="], + + "@rsdoctor/client": ["@rsdoctor/client@1.6.2", "", {}, "sha512-6HngWsWIUcMoHD2ruCZLVbjeqA6Vh41xD3MQhTb/LQ1CWSpU7KVkvge0iV5JqLEv9EemSojIz5RhMRdg3AsCSA=="], + + "@rsdoctor/core": ["@rsdoctor/core@1.6.2", "", { "dependencies": { "@rsbuild/plugin-check-syntax": "^1.6.1", "@rsdoctor/graph": "1.6.2", "@rsdoctor/sdk": "1.6.2", "@rsdoctor/types": "1.6.2", "@rsdoctor/utils": "1.6.2", "@rspack/resolver": "^0.2.8", "browserslist-load-config": "^1.0.2", "es-toolkit": "^1.49.0", "filesize": "^11.0.17", "fs-extra": "^11.1.1", "semver": "^7.8.5", "source-map": "^0.7.6" } }, "sha512-YPf71epg7RDU3nT6Q3sI53y7xdksen6B/DTVCQl6mbMnG096r8Ilx0ggV9nXaa4vDOXZpiZZ+vGOhb5VeWFMMA=="], + + "@rsdoctor/graph": ["@rsdoctor/graph@1.6.2", "", { "dependencies": { "@rsdoctor/types": "1.6.2", "@rsdoctor/utils": "1.6.2", "es-toolkit": "^1.49.0", "path-browserify": "1.0.1", "source-map": "^0.7.6" } }, "sha512-EzwDKYs43UyZW/FmhQAZUqw3Z0lFA/b6XVq4OQRMUcMpNBmn/hxCDWUYUubRQEiCaqJthgl1Puu4anTJhof61g=="], + + "@rsdoctor/rspack-plugin": ["@rsdoctor/rspack-plugin@1.6.2", "", { "dependencies": { "@rsdoctor/core": "1.6.2", "@rsdoctor/graph": "1.6.2", "@rsdoctor/sdk": "1.6.2", "@rsdoctor/types": "1.6.2", "@rsdoctor/utils": "1.6.2" }, "peerDependencies": { "@rspack/core": "*" }, "optionalPeers": ["@rspack/core"] }, "sha512-vDRf/n6Uj6JkmolLFAG4rC115NMQ2W2T6OVjSiMU7oAds8yn1dtKzt8slL/OErCBl2p2sFcGZ1pGkdleZpFD/w=="], + + "@rsdoctor/sdk": ["@rsdoctor/sdk@1.6.2", "", { "dependencies": { "@rsdoctor/client": "1.6.2", "@rsdoctor/graph": "1.6.2", "@rsdoctor/types": "1.6.2", "@rsdoctor/utils": "1.6.2", "launch-editor": "^2.13.2", "safer-buffer": "2.1.2", "socket.io": "4.8.1", "tapable": "2.3.3" } }, "sha512-wP26caE6hnYRQuDF5uyBXSKiBlwcOSEXtYoJRdG9ZMyf2rz0/8KWgKlp3V5Mtobf0zYlFnpi5H+8/JHfczdHVQ=="], + + "@rsdoctor/types": ["@rsdoctor/types@1.6.2", "", { "dependencies": { "@types/connect": "3.4.38", "@types/estree": "1.0.5", "@types/tapable": "2.3.0", "source-map": "^0.7.6" }, "peerDependencies": { "@rspack/core": "*", "webpack": "5.x" }, "optionalPeers": ["@rspack/core", "webpack"] }, "sha512-+giYQPsgpPyo8OCGM9qNrdZKc2oaU+gUsZ5cnpHgbD3zwgUDj39PGgnnRj3kc9BP4PFrhVrBIJUnVVG/v60Jxw=="], + + "@rsdoctor/utils": ["@rsdoctor/utils@1.6.2", "", { "dependencies": { "@babel/code-frame": "7.26.2", "@rsdoctor/types": "1.6.2", "@types/estree": "1.0.5", "acorn": "^8.10.0", "acorn-import-attributes": "^1.9.5", "acorn-walk": "8.3.5", "deep-eql": "4.1.4", "envinfo": "7.21.0", "fs-extra": "^11.1.1", "get-port": "5.1.1", "json-stream-stringify": "3.0.1", "lines-and-columns": "2.0.4", "picocolors": "^1.1.1", "rslog": "^2.1.2", "strip-ansi": "^7.2.0" } }, "sha512-e6veT/5SdXxmTKV6K6Ay0S2LyvDMtedwaHIeRJNgT0a2T0esdAuL+O5q/jWqa33k9+Df+o+E/i2boX9CP3rYLA=="], + + "@rspack/binding": ["@rspack/binding@2.1.10", "", { "optionalDependencies": { "@rspack/binding-darwin-arm64": "2.1.10", "@rspack/binding-darwin-x64": "2.1.10", "@rspack/binding-linux-arm64-gnu": "2.1.10", "@rspack/binding-linux-arm64-musl": "2.1.10", "@rspack/binding-linux-ppc64-gnu": "2.1.10", "@rspack/binding-linux-riscv64-gnu": "2.1.10", "@rspack/binding-linux-riscv64-musl": "2.1.10", "@rspack/binding-linux-s390x-gnu": "2.1.10", "@rspack/binding-linux-x64-gnu": "2.1.10", "@rspack/binding-linux-x64-musl": "2.1.10", "@rspack/binding-wasm32-wasi": "2.1.10", "@rspack/binding-win32-arm64-msvc": "2.1.10", "@rspack/binding-win32-ia32-msvc": "2.1.10", "@rspack/binding-win32-x64-msvc": "2.1.10" } }, "sha512-vnu/UP5HnrND15lO9+VeG6eUrbTyycHNQNQ3XEiRiFojuoiGZkIZC3Hbzr8qQH44C6vScPODEPvvIVvLcO2LpQ=="], + + "@rspack/binding-darwin-arm64": ["@rspack/binding-darwin-arm64@2.1.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DZlcTpbIb2mjeS1aSG4k01UH33Zj7T+k8ZylPK6HmsKs4JvK4wgpWFC78WVv3p/Aj3MZS6DwtDLwpZ2Ihj/fpg=="], + + "@rspack/binding-darwin-x64": ["@rspack/binding-darwin-x64@2.1.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-my/0h2LwxCRT6cg3oDDC2e0ZOxQLVajAdIcv0fqnQk5JRNvVuL89PuTutitnSqie1A0/JSL8OQz5XHwmoS3kow=="], + + "@rspack/binding-linux-arm64-gnu": ["@rspack/binding-linux-arm64-gnu@2.1.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-laevn9g+E5PAUEGqiKe6Ju5KApsuQYp+bPI17XS3Lkl8eqL5pS/BmHYU7QMlst4GzV8+wlruVTMh//+st6Vqzg=="], + + "@rspack/binding-linux-arm64-musl": ["@rspack/binding-linux-arm64-musl@2.1.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-V71+Qz5G72+ROZXrJn5zxOszdG1AEbO8pcC/itXXtf4yRR6a3bVHKNKGhipBNxb8eI6cnD/01FH1h3ZG655jLw=="], + + "@rspack/binding-linux-ppc64-gnu": ["@rspack/binding-linux-ppc64-gnu@2.1.10", "", { "os": "linux", "cpu": "ppc64" }, "sha512-U7HlNzHcDtZ+LYOtOJmtx67kHEybZzUUAaP7aEXjGYO5WTCgh/176sW2UYP0rmZLrgUNFUuzn+B98RLaClNaVg=="], + + "@rspack/binding-linux-riscv64-gnu": ["@rspack/binding-linux-riscv64-gnu@2.1.10", "", { "os": "linux", "cpu": "none" }, "sha512-GMGTJpy9/ecE+5F5IfxZH4bXv0Wx/b2TiehTlCbTksbL+pKpLHYy0rwGdjWDKbmBkhxMMqPiC7PDnn9LbdnnLA=="], + + "@rspack/binding-linux-riscv64-musl": ["@rspack/binding-linux-riscv64-musl@2.1.10", "", { "os": "linux", "cpu": "none" }, "sha512-rkurnAWc04vIbzG1QCrPBWSJadZvaOt1mazFH3EdiJO8VUiu0I1T9zdiwuDOPrd50lOKIZlcTXbd5aaAkWEnvQ=="], + + "@rspack/binding-linux-s390x-gnu": ["@rspack/binding-linux-s390x-gnu@2.1.10", "", { "os": "linux", "cpu": "s390x" }, "sha512-X+DyxkriZEAF/wihI7ERDv+CAS0mbMv36aEuQ+vXzTlvS6cSmpou/r29AHbvIF3NlG1UeAbDVlOs9QrMBZjpUQ=="], + + "@rspack/binding-linux-x64-gnu": ["@rspack/binding-linux-x64-gnu@2.1.10", "", { "os": "linux", "cpu": "x64" }, "sha512-Fat09V6jUuyo9qG7Wyj9cQ31VDfLmokXyBtGqKxY5OvSWHereB7QUub5btbPXHwbp6Iq4aAQyUbbLTzvR1YaBw=="], + + "@rspack/binding-linux-x64-musl": ["@rspack/binding-linux-x64-musl@2.1.10", "", { "os": "linux", "cpu": "x64" }, "sha512-lhHOnIJ4ClpIlA1f1L8aoxEZivYLjnjq5A6jKKz7BKsm+cHK8kqqEm6lO5KqA5xQT0Lonq1o28bmKHEj6JHInw=="], + + "@rspack/binding-wasm32-wasi": ["@rspack/binding-wasm32-wasi@2.1.10", "", { "dependencies": { "@emnapi/core": "1.11.3", "@emnapi/runtime": "1.11.3", "@napi-rs/wasm-runtime": "1.1.6" }, "cpu": "none" }, "sha512-KY5YbWbuvYcoaLXnV+vzZOvGRCeb6jt4EpVpKdph1h1IJjwX/ju15EQ+GOe3iecZEdf0OttQcNVcwBkLkFT9ag=="], + + "@rspack/binding-win32-arm64-msvc": ["@rspack/binding-win32-arm64-msvc@2.1.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-z4GWzMLofaDGpAt9Z+MlN88LlUBDm+zM6R2GdOOPM6/4g/h3/+47OP7casmSL3AwTGYBEJqogwt08sRSosB6Cg=="], + + "@rspack/binding-win32-ia32-msvc": ["@rspack/binding-win32-ia32-msvc@2.1.10", "", { "os": "win32", "cpu": "ia32" }, "sha512-7qcWdsZ+GuGtzKjqgy7wTN7Dso/ezIY8yhx1r2yIbcczdmXj4FhaEampMDp/25HwtKwIGBBoh6HHSt3JWxpTUg=="], + + "@rspack/binding-win32-x64-msvc": ["@rspack/binding-win32-x64-msvc@2.1.10", "", { "os": "win32", "cpu": "x64" }, "sha512-pgp23pLrzfhGnKycxzr7ifP17lAbWZEfnx1bX8gXtYrnpJ66DRNyTKSzxB6sa/HBWjS1L8PX5TjMZ44WfPydqQ=="], + + "@rspack/core": ["@rspack/core@2.1.10", "", { "dependencies": { "@rspack/binding": "2.1.10" }, "peerDependencies": { "@module-federation/runtime-tools": "^0.24.1 || ^2.0.0", "@swc/helpers": "^0.5.23" }, "optionalPeers": ["@module-federation/runtime-tools", "@swc/helpers"] }, "sha512-YSS2/Xxz8uiG/KXDkqOoA3dTetNo/vysk7bAexQOrU8iuq7JuzDTTAwLKvWZnwmvME8M8m5wcM4YvfIwYmidHA=="], + + "@rspack/lite-tapable": ["@rspack/lite-tapable@1.1.5", "", {}, "sha512-uzB782zJbFTM3ta+e2Glikx36dca/6Y+DXyvFN+wb0Tx5ItIW+g03A0t3amP3LGzPHSkb0k81VHCm4jxLQwfag=="], + + "@rspack/resolver": ["@rspack/resolver@0.2.8", "", { "optionalDependencies": { "@rspack/resolver-binding-darwin-arm64": "0.2.8", "@rspack/resolver-binding-darwin-x64": "0.2.8", "@rspack/resolver-binding-linux-arm64-gnu": "0.2.8", "@rspack/resolver-binding-linux-arm64-musl": "0.2.8", "@rspack/resolver-binding-linux-x64-gnu": "0.2.8", "@rspack/resolver-binding-linux-x64-musl": "0.2.8", "@rspack/resolver-binding-wasm32-wasi": "0.2.8", "@rspack/resolver-binding-win32-arm64-msvc": "0.2.8", "@rspack/resolver-binding-win32-ia32-msvc": "0.2.8", "@rspack/resolver-binding-win32-x64-msvc": "0.2.8" } }, "sha512-FBWqdHhzS8mcf/WN4Ktzr7EaeaN+hsxbN98EweegX3924beZuY6H70CSFWCv1fIHAieCUv/9XCjKggHvhCsLwA=="], + + "@rspack/resolver-binding-darwin-arm64": ["@rspack/resolver-binding-darwin-arm64@0.2.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-nTnK17kmxXEvR+WpOIZPSIzUFYeWCHoffgU9tvOLOwuTBH41kWnSQXXWu+AiMVwvJ6wdRO6Vo30hPhlXEG7Pyw=="], + + "@rspack/resolver-binding-darwin-x64": ["@rspack/resolver-binding-darwin-x64@0.2.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-Aqr4TK2rA6XVYUOmM5YCtYyCMZhOIR53P4cOGgGARg99A7OuMBMzUL4r1n0M0Fx35v6/sSx1OBe+odHmPxksEg=="], + + "@rspack/resolver-binding-linux-arm64-gnu": ["@rspack/resolver-binding-linux-arm64-gnu@0.2.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-wGvkxm2G4mNTztslaOzLzx5JuySQSy5DcOWEZxHcjJJzp5L3ODbYLK18HtUc6cvmaVOmjaGrrYPrqJJ0hHTVFg=="], + + "@rspack/resolver-binding-linux-arm64-musl": ["@rspack/resolver-binding-linux-arm64-musl@0.2.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-EqRJ9zLQsLAvyDKJKVZ45BSqRIMS12f5HtJdy3KkAHU14ZmsGv8e5IKkwUZN5CNBRad8xVlOMMx3dOfF4whJzg=="], + + "@rspack/resolver-binding-linux-x64-gnu": ["@rspack/resolver-binding-linux-x64-gnu@0.2.8", "", { "os": "linux", "cpu": "x64" }, "sha512-eXbeotNCTntL4/+mxJRVCxK63YeWzTfp0F3POeHJFSs6Nt0f2J/mZNFlasJmd6xm7zvE80h/HWOwbwjRBLcElA=="], + + "@rspack/resolver-binding-linux-x64-musl": ["@rspack/resolver-binding-linux-x64-musl@0.2.8", "", { "os": "linux", "cpu": "x64" }, "sha512-KWFHlOWGkT+eMngoUgPGXrDi+rU04VCh9jyk0U6Ot2RTWvhGxwKykjmLS+CWZI/EBrzr9A6g2U3jzKTMNz9oCw=="], + + "@rspack/resolver-binding-wasm32-wasi": ["@rspack/resolver-binding-wasm32-wasi@0.2.8", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-I6GIhgICFViE88jejIV74oiiWHnpLpQ5ogaZM1ozM9KDnfqcHoX0IVEyrIh5KqA8iLDyhuoFSW+Hf0qN7VTBBQ=="], + + "@rspack/resolver-binding-win32-arm64-msvc": ["@rspack/resolver-binding-win32-arm64-msvc@0.2.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-ZXCt3qUfDAEbtc2sHpvxM7lNFZM+DxfblgXUIl3Jy6BuEZbHe1i6z+t9c34ayHoGTVbVSNCtaYuG/MaWdSnPHw=="], + + "@rspack/resolver-binding-win32-ia32-msvc": ["@rspack/resolver-binding-win32-ia32-msvc@0.2.8", "", { "os": "win32", "cpu": "ia32" }, "sha512-2LRymjDK8MpUERD8CL0PPae5y2crU5TAg4T4EzpeL5jLARVq6izsEruiWzB6Y+D15vUYlvmgs2370GXVSB861w=="], + + "@rspack/resolver-binding-win32-x64-msvc": ["@rspack/resolver-binding-win32-x64-msvc@0.2.8", "", { "os": "win32", "cpu": "x64" }, "sha512-hzRpfbtvv4M4EVrKKIAaHDs5wT8lVcbSUjtwPs5u4IeLEix45nQPQ6ZQjmE4lIH0GP/3L3XQhZroYmTcH/xdsQ=="], + + "@sinclair/typebox": ["@sinclair/typebox@0.34.52", "", {}, "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw=="], + "@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="], + "@socket.io/component-emitter": ["@socket.io/component-emitter@3.1.2", "", {}, "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA=="], + "@speed-highlight/core": ["@speed-highlight/core@1.2.17", "", {}, "sha512-Z92FwKpCtfaW1V0jTU/fh3QzYEZN8wDwrzRIBoADCJfn4mJCNcJN/XegifX7BDrQ8/h9Xh/JnbyMchL0FqXrkg=="], "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "@swc/helpers": ["@swc/helpers@0.5.23", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw=="], + "@tanstack/query-core": ["@tanstack/query-core@5.101.3", "", {}, "sha512-pWLyu7AjFFVM5G+frjcL81kKEW9R8GCCPKnL3uaWbMwd2f3ZINFCuy+PtKkdz/+pKw/f/XMsFsYq/H+uJHM4GQ=="], "@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="], "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], + "@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="], + + "@types/cors": ["@types/cors@2.8.19", "", { "dependencies": { "@types/node": "*" } }, "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg=="], + "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], + "@types/istanbul-lib-coverage": ["@types/istanbul-lib-coverage@2.0.6", "", {}, "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w=="], + + "@types/istanbul-lib-report": ["@types/istanbul-lib-report@3.0.3", "", { "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA=="], + + "@types/istanbul-reports": ["@types/istanbul-reports@3.0.4", "", { "dependencies": { "@types/istanbul-lib-report": "*" } }, "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + "@types/node": ["@types/node@25.9.5", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-OScDchr2fwuUmWdf4kZ9h7PcJiYDVInhJizG/biAq3cAvqwYktuy/TYGGdZNMtNTFUP7rnb0NU4TUdm82kt4Rg=="], + "@types/tapable": ["@types/tapable@2.3.0", "", { "dependencies": { "tapable": "^2.3.0" } }, "sha512-oMnbAXeVo+KUnje3hzdORXUbfnzTfqD0H92mLl19NE5hFqH9Q4ktq+xehNSxcNeeLm1COopYwa0zeP6Iz+oIXg=="], + + "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="], + "@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="], "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], + "@types/yargs": ["@types/yargs@17.0.35", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg=="], + + "@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="], + "@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260707.2", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260707.2", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260707.2", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260707.2", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260707.2", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260707.2", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260707.2", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260707.2" }, "bin": { "tsgo": "bin/tsgo" } }, "sha512-oUGp+Rep/hqMhPunyinsALUwSlzHINSxitifPiSaeqoKOKD2OlR9NE3TaPqwsl4NlGslsOSUXI1JotWQzpYCPg=="], "@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260707.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-wny2pgKjGbiZtnOIHVa3tXC1UfDqxNEFzyPGmiqybedG8hipG2Nfp0l5UxbaKCjkLacUpH/W5bP2hBOMVhCOzg=="], @@ -524,6 +724,8 @@ "@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260707.2", "", { "os": "win32", "cpu": "x64" }, "sha512-DL4u27stv0fo71sVhOzHSwE+YMZsbBijVI+kg5dLDLilSH79WFTJ8RSQ46vJrCMt+Gjlv/JOZP1PuLJDfioYeQ=="], + "@ungap/structured-clone": ["@ungap/structured-clone@1.3.3", "", {}, "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg=="], + "@vitest/expect": ["@vitest/expect@4.1.10", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.10", "@vitest/utils": "4.1.10", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA=="], "@vitest/mocker": ["@vitest/mocker@4.1.10", "", { "dependencies": { "@vitest/spy": "4.1.10", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow=="], @@ -538,122 +740,406 @@ "@vitest/utils": ["@vitest/utils@4.1.10", "", { "dependencies": { "@vitest/pretty-format": "4.1.10", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA=="], + "@webassemblyjs/ast": ["@webassemblyjs/ast@1.14.1", "", { "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ=="], + + "@webassemblyjs/floating-point-hex-parser": ["@webassemblyjs/floating-point-hex-parser@1.13.2", "", {}, "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA=="], + + "@webassemblyjs/helper-api-error": ["@webassemblyjs/helper-api-error@1.13.2", "", {}, "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ=="], + + "@webassemblyjs/helper-buffer": ["@webassemblyjs/helper-buffer@1.14.1", "", {}, "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA=="], + + "@webassemblyjs/helper-numbers": ["@webassemblyjs/helper-numbers@1.13.2", "", { "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA=="], + + "@webassemblyjs/helper-wasm-bytecode": ["@webassemblyjs/helper-wasm-bytecode@1.13.2", "", {}, "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA=="], + + "@webassemblyjs/helper-wasm-section": ["@webassemblyjs/helper-wasm-section@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/wasm-gen": "1.14.1" } }, "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw=="], + + "@webassemblyjs/ieee754": ["@webassemblyjs/ieee754@1.13.2", "", { "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw=="], + + "@webassemblyjs/leb128": ["@webassemblyjs/leb128@1.13.2", "", { "dependencies": { "@xtuc/long": "4.2.2" } }, "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw=="], + + "@webassemblyjs/utf8": ["@webassemblyjs/utf8@1.13.2", "", {}, "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ=="], + + "@webassemblyjs/wasm-edit": ["@webassemblyjs/wasm-edit@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/helper-wasm-section": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-opt": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1", "@webassemblyjs/wast-printer": "1.14.1" } }, "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ=="], + + "@webassemblyjs/wasm-gen": ["@webassemblyjs/wasm-gen@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg=="], + + "@webassemblyjs/wasm-opt": ["@webassemblyjs/wasm-opt@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1" } }, "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw=="], + + "@webassemblyjs/wasm-parser": ["@webassemblyjs/wasm-parser@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ=="], + + "@webassemblyjs/wast-printer": ["@webassemblyjs/wast-printer@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw=="], + + "@xtuc/ieee754": ["@xtuc/ieee754@1.2.0", "", {}, "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="], + + "@xtuc/long": ["@xtuc/long@4.2.2", "", {}, "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="], + + "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], + + "acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="], + + "acorn-import-attributes": ["acorn-import-attributes@1.9.5", "", { "peerDependencies": { "acorn": "^8" } }, "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ=="], + + "acorn-walk": ["acorn-walk@8.3.5", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw=="], + + "ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="], + + "ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="], + + "ajv-keywords": ["ajv-keywords@5.1.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3" }, "peerDependencies": { "ajv": "^8.8.2" } }, "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw=="], + "alien-signals": ["alien-signals@3.2.1", "", {}, "sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g=="], "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + "array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="], + "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], + "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="], + "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], + "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], + + "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], + + "base64id": ["base64id@2.0.0", "", {}, "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="], + + "baseline-browser-mapping": ["baseline-browser-mapping@2.11.15", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-FwMjJJ7HnyZpWe+oWxegG0fezZyBZUagI5LZEoO3GCbtbKNwRfMH9Ue5d5v01PNePBy1QSfPSDTTeVL0Hb9EzA=="], + "better-path-resolve": ["better-path-resolve@1.0.0", "", { "dependencies": { "is-windows": "^1.0.0" } }, "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g=="], "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], "blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="], + "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + "browserslist": ["browserslist@4.28.8", "", { "dependencies": { "baseline-browser-mapping": "^2.11.12", "caniuse-lite": "^1.0.30001809", "electron-to-chromium": "^1.5.402", "node-releases": "^2.0.53", "update-browserslist-db": "^1.3.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA=="], + + "browserslist-load-config": ["browserslist-load-config@1.0.3", "", {}, "sha512-boNaPS4KlW6AITZQ60G+1oDJLuxauljDd7QNQFOYpRtldzcTDknMZ8awbwI0BT/8h1/Y/CG4k/tDOLip9lAGcg=="], + + "browserslist-to-es-version": ["browserslist-to-es-version@1.4.2", "", { "dependencies": { "browserslist": "^4.28.2" }, "bin": { "browserslist-to-es-version": "./dist/cli.js" } }, "sha512-3NV13pCv0wmPxxZZcekHAG6vt8rQ94w2c4/UBe3ZU3NDUm5TP+QFK3rjS6XeKWSHWpnPYNfQzlhnljka0BrEOA=="], + + "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + "buffer-image-size": ["buffer-image-size@0.6.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ=="], + "call-bind": ["call-bind@1.0.9", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "get-intrinsic": "^1.3.0", "set-function-length": "^1.2.2" } }, "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + + "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], + + "caniuse-api": ["caniuse-api@3.0.0", "", { "dependencies": { "browserslist": "^4.0.0", "caniuse-lite": "^1.0.0", "lodash.memoize": "^4.1.2", "lodash.uniq": "^4.5.0" } }, "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001809", "", {}, "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ=="], + "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "chardet": ["chardet@2.2.0", "", {}, "sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA=="], "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], + "chrome-trace-event": ["chrome-trace-event@1.0.4", "", {}, "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ=="], + + "ci-info": ["ci-info@4.4.0", "", {}, "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + "commander": ["commander@9.5.0", "", {}, "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ=="], "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], + "cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="], + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + "css-declaration-sorter": ["css-declaration-sorter@7.4.0", "", { "peerDependencies": { "postcss": "^8.0.9" } }, "sha512-LTuzjPoyA2vMGKKcaOqKSp7Ub2eGrNfKiZH4LpezxpNrsICGCSFvsQOI29psISxNZtaXibkC2CXzrQ5enMeGGw=="], + + "css-minimizer-webpack-plugin": ["css-minimizer-webpack-plugin@8.0.0", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "cssnano": "^7.0.4", "jest-worker": "^30.0.5", "postcss": "^8.4.40", "schema-utils": "^4.2.0", "serialize-javascript": "^7.0.3" }, "peerDependencies": { "webpack": "^5.0.0" } }, "sha512-9bEpzHs8gEq6/cbEj418jXL/YWjBUD2YTLLk905Npt2JODqnRITin0+So5Vx4Dp5vyi2Lpt9pp2QHzQ7fdxNrw=="], + + "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="], + + "css-tree": ["css-tree@3.2.1", "", { "dependencies": { "mdn-data": "2.27.1", "source-map-js": "^1.2.1" } }, "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA=="], + + "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="], + + "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + + "cssnano": ["cssnano@7.1.9", "", { "dependencies": { "cssnano-preset-default": "^7.0.17", "lilconfig": "^3.1.3" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-uPR75+5Dk/WJ/YSPR1/YDHdwMM9c5FsaARljfKWgeCKLKOtJ0we21xy/RcCjn53fZnD/f6yYEIZ8pu18+GnbNQ=="], + + "cssnano-preset-default": ["cssnano-preset-default@7.0.17", "", { "dependencies": { "browserslist": "^4.28.2", "css-declaration-sorter": "^7.2.0", "cssnano-utils": "^5.0.3", "postcss-calc": "^10.1.1", "postcss-colormin": "^7.0.10", "postcss-convert-values": "^7.0.12", "postcss-discard-comments": "^7.0.8", "postcss-discard-duplicates": "^7.0.4", "postcss-discard-empty": "^7.0.3", "postcss-discard-overridden": "^7.0.3", "postcss-merge-longhand": "^7.0.7", "postcss-merge-rules": "^7.0.11", "postcss-minify-font-values": "^7.0.3", "postcss-minify-gradients": "^7.0.5", "postcss-minify-params": "^7.0.9", "postcss-minify-selectors": "^7.1.2", "postcss-normalize-charset": "^7.0.3", "postcss-normalize-display-values": "^7.0.3", "postcss-normalize-positions": "^7.0.4", "postcss-normalize-repeat-style": "^7.0.4", "postcss-normalize-string": "^7.0.3", "postcss-normalize-timing-functions": "^7.0.3", "postcss-normalize-unicode": "^7.0.9", "postcss-normalize-url": "^7.0.3", "postcss-normalize-whitespace": "^7.0.3", "postcss-ordered-values": "^7.0.4", "postcss-reduce-initial": "^7.0.9", "postcss-reduce-transforms": "^7.0.3", "postcss-svgo": "^7.1.3", "postcss-unique-selectors": "^7.0.7" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-11qO63A+czwguQFJCaTdICvbaxn0pJzz/XghLlv+OT7WyToDxAMR0Xb3/26/l0y0hQJywwNbj/SLSQlGBHE1OA=="], + + "cssnano-utils": ["cssnano-utils@5.0.3", "", { "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-ynIREMICLxkxm7e9bCR9sh75s4Q5drICi0ua1yxo5jH2XPBqSKkl4dOh4EbFqtUmnTMhRffHgYL0EKKkMjtJTg=="], + + "csso": ["csso@5.0.5", "", { "dependencies": { "css-tree": "~2.2.0" } }, "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ=="], + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + "data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="], + + "data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="], + + "data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="], + + "debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], + + "deep-eql": ["deep-eql@4.1.4", "", { "dependencies": { "type-detect": "^4.0.0" } }, "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg=="], + + "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], + + "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="], + "detect-indent": ["detect-indent@6.1.0", "", {}, "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA=="], "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="], + "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], + + "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], + + "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], + + "dompurify": ["dompurify@3.4.13", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ=="], + + "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], + + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + + "electron-to-chromium": ["electron-to-chromium@1.5.411", "", {}, "sha512-gglkxzokjHfawpGxq75XdBV2/l3BAPzrsMs70qgaZdTW5rpV1tC4MdgJVP9fN126bODA4ZJQkn1wryEzJyQXIg=="], + + "engine.io": ["engine.io@6.6.9", "", { "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", "@types/ws": "^8.5.12", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.4.1", "engine.io-parser": "~5.2.1", "ws": "~8.21.0" } }, "sha512-clKkw4C7nJ22mGgoVcCg6V/W/TxdNyIOTr89k2ONZu81qqkddPFDF0LXcbAwhzPD8DjkiRCjzuiO6Y+fkpD4vg=="], + + "engine.io-parser": ["engine.io-parser@5.2.3", "", {}, "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q=="], + + "enhanced-resolve": ["enhanced-resolve@5.24.5", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A=="], + "enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="], "entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], + "envinfo": ["envinfo@7.21.0", "", { "bin": { "envinfo": "dist/cli.js" } }, "sha512-Lw7I8Zp5YKHFCXL7+Dz95g4CcbMEpgvqZNNq3AmlT5XAV6CgAAk6gyAMqn2zjw08K9BHfcNuKrMiCPLByGafow=="], + "error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="], + "es-abstract": ["es-abstract@1.24.2", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg=="], + + "es-abstract-get": ["es-abstract-get@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "es-object-atoms": "^1.1.2", "is-callable": "^1.2.7", "object-inspect": "^1.13.4" } }, "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg=="], + + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + "es-module-lexer": ["es-module-lexer@2.3.1", "", {}, "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA=="], + "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="], + + "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], + + "es-to-primitive": ["es-to-primitive@1.3.4", "", { "dependencies": { "es-abstract-get": "^1.0.0", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "is-callable": "^1.2.7", "is-date-object": "^1.1.0", "is-symbol": "^1.1.1" } }, "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw=="], + + "es-toolkit": ["es-toolkit@1.51.0", "", {}, "sha512-zC2lQGkM7QX+Gm6iM3+WIdZJzthsEd14LvRNJneSO2hzyz/zNBENR8+YXWo1cKxgPBtV6ksPYHELbcwBRzmdCw=="], + "esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="], + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="], + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], + "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="], + + "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], + "expect-type": ["expect-type@1.4.0", "", {}, "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA=="], "extendable-error": ["extendable-error@0.1.7", "", {}, "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg=="], + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + "fast-uri": ["fast-uri@3.1.5", "", {}, "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw=="], + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + "filesize": ["filesize@11.0.22", "", {}, "sha512-RlCVs9CY+oSsRnNZn95J9vDXjNjOwddKyTFjOYtA4yxYVIxBnwiVVGJX+TFhsmu3uUf81JDGyijtYL9xgawlTw=="], + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], "find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], + "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], + "fs-extra": ["fs-extra@7.0.1", "", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw=="], "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "function.prototype.name": ["function.prototype.name@1.2.0", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2", "hasown": "^2.0.4", "is-callable": "^1.2.7", "is-document.all": "^1.0.0" } }, "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew=="], + + "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="], + + "generator-function": ["generator-function@2.0.1", "", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="], + + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-port": ["get-port@5.1.1", "", {}, "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="], + "get-tsconfig": ["get-tsconfig@4.14.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA=="], "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], + "globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="], + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], "happy-dom": ["happy-dom@20.11.0", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "buffer-image-size": "^0.6.4", "entities": "^7.0.1", "whatwg-mimetype": "^3.0.0", "ws": "^8.21.0" } }, "sha512-XogN4asPd1a56di9prVG6bZxteNcXsZxxKmAvcEfc5Px5Ca2hMyMgk8wvqK2K1V8zXg40j9VANXsDaJYh9DeNA=="], + "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], + + "has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="], + + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], + + "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], + + "htmlparser2": ["htmlparser2@10.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.2.1", "entities": "^6.0.0" } }, "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g=="], + "human-id": ["human-id@4.2.0", "", { "bin": { "human-id": "dist/cli.js" } }, "sha512-K3GbkIWqyvvlpfhBPlbEvD97TtqBpAYA4kt+cn2lD2x2HuohzZCibcA2nOlnJT6exqvJLggoB5nv2dNf192nEA=="], "iconv-lite": ["iconv-lite@0.7.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ=="], "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], + + "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="], + + "is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="], + + "is-bigint": ["is-bigint@1.1.0", "", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="], + "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], + "is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="], + + "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="], + + "is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="], + + "is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="], + + "is-document.all": ["is-document.all@1.0.0", "", { "dependencies": { "call-bound": "^1.0.4" } }, "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g=="], + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + "is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="], + + "is-generator-function": ["is-generator-function@1.1.2", "", { "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA=="], + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="], + + "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="], + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="], + + "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="], + + "is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="], + + "is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="], + + "is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="], + "is-subdir": ["is-subdir@1.2.0", "", { "dependencies": { "better-path-resolve": "1.0.0" } }, "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw=="], + "is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="], + + "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="], + + "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="], + + "is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="], + + "is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="], + "is-windows": ["is-windows@1.0.2", "", {}, "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="], + "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + "jest-regex-util": ["jest-regex-util@30.4.0", "", {}, "sha512-mWlvLviKIgIQ8VCuM1xRdD0TWp3zlzionlmDBjuXVBs+VkmXq6FgW9T4Emr7oGz/Rk6feDCGyiugolcQEyp3mg=="], + + "jest-util": ["jest-util@30.4.1", "", { "dependencies": { "@jest/types": "30.4.1", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", "picomatch": "^4.0.3" } }, "sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw=="], + + "jest-worker": ["jest-worker@30.4.1", "", { "dependencies": { "@types/node": "*", "@ungap/structured-clone": "^1.3.0", "jest-util": "30.4.1", "merge-stream": "^2.0.0", "supports-color": "^8.1.1" } }, "sha512-SHynN/q/QD++iNyvMdy+WMmbCGk8jIsNcRxycXbWubSOhvo6T+j2afcfUSl+3hYsiBebOTo0cT7c2H7CXugu1g=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + "js-yaml": ["js-yaml@4.3.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q=="], + "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + "json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="], + "json-stream-stringify": ["json-stream-stringify@3.0.1", "", {}, "sha512-vuxs3G1ocFDiAQ/SX0okcZbtqXwgj1g71qE9+vrjJ2EkjKQlEFDAcUNRxRU8O+GekV4v5cM2qXP0Wyt/EMDBiQ=="], + "jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], + "launch-editor": ["launch-editor@2.14.1", "", { "dependencies": { "picocolors": "^1.1.1", "shell-quote": "^1.8.4" } }, "sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA=="], + "lightningcss": ["lightningcss@1.33.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.33.0", "lightningcss-darwin-arm64": "1.33.0", "lightningcss-darwin-x64": "1.33.0", "lightningcss-freebsd-x64": "1.33.0", "lightningcss-linux-arm-gnueabihf": "1.33.0", "lightningcss-linux-arm64-gnu": "1.33.0", "lightningcss-linux-arm64-musl": "1.33.0", "lightningcss-linux-x64-gnu": "1.33.0", "lightningcss-linux-x64-musl": "1.33.0", "lightningcss-win32-arm64-msvc": "1.33.0", "lightningcss-win32-x64-msvc": "1.33.0" } }, "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA=="], "lightningcss-android-arm64": ["lightningcss-android-arm64@1.33.0", "", { "os": "android", "cpu": "arm64" }, "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg=="], @@ -678,30 +1164,78 @@ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.33.0", "", { "os": "win32", "cpu": "x64" }, "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA=="], + "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], + + "lines-and-columns": ["lines-and-columns@2.0.4", "", {}, "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A=="], + + "linkify-it": ["linkify-it@6.1.0", "", { "dependencies": { "uc.micro": "^3.0.0" } }, "sha512-wJ/TwpSDTLepCrQoYWYIExIKg5Zchex2Nn5yk2mFnB+6PtdkHtyLx742md9csRjjOnGkKIS/RrbY7l8D6gT9Vw=="], + "locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], + "lodash.memoize": ["lodash.memoize@4.1.2", "", {}, "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="], + "lodash.startcase": ["lodash.startcase@4.4.0", "", {}, "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg=="], + "lodash.uniq": ["lodash.uniq@4.5.0", "", {}, "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ=="], + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + "markdown-it": ["markdown-it@15.0.0", "", { "dependencies": { "argparse": "^3.0.0", "entities": "^8.0.0", "linkify-it": "^6.0.0", "mdurl": "^2.1.0", "punycode.js": "^2.3.1", "uc.micro": "^3.0.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-Lf8ajvVNdRpzSNB4VegxNy7gjs8gU35l4b4+ET49LrQC5PKYwLZ72u60LeJ9gv3qiaesuYjJWCyVeQmv/QWKQw=="], + + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "mdn-data": ["mdn-data@2.27.1", "", {}, "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ=="], + + "mdurl": ["mdurl@2.1.0", "", {}, "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg=="], + + "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + "miniflare": ["miniflare@4.20260721.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "0.34.5", "undici": "7.28.0", "workerd": "1.20260721.1", "ws": "8.21.0", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-fBLaCxZ2i/nPH8iyLzvza0C8/sSF4sjD1ma1Skf+pkZVK0TlaW5ujHJlUHwcwR66v2JZt+Q28d4DCX/oaLG0cA=="], + "minimizer-webpack-plugin": ["minimizer-webpack-plugin@5.6.1", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", "terser": "^5.31.1" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-DoeAZz8Q1C1znwsUzej1fdoi4jCf7/+Em27ouLqfK/+3m8G+D7yDhUwrc3CNhjSzGUN1kn7Iv4sWmjflQHenpw=="], + "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + "mylas": ["mylas@2.1.14", "", {}, "sha512-BzQguy9W9NJgoVn2mRWzbFrFWWztGCcng2QI9+41frfk+Athwgx3qhqhvStz7ExeUUu7Kzw427sNzHpEZNINog=="], "nanoid": ["nanoid@3.3.16", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q=="], + "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], + + "neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="], + + "node-releases": ["node-releases@2.0.53", "", {}, "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ=="], + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], + + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], + + "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="], + + "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="], + + "object.groupby": ["object.groupby@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2" } }, "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ=="], + "obug": ["obug@2.1.4", "", {}, "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA=="], "outdent": ["outdent@0.5.0", "", {}, "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q=="], + "own-keys": ["own-keys@1.0.2", "", { "dependencies": { "call-bound": "^1.0.4", "get-intrinsic": "^1.3.0", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg=="], + "p-filter": ["p-filter@2.1.0", "", { "dependencies": { "p-map": "^2.0.0" } }, "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw=="], "p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], @@ -714,6 +1248,8 @@ "package-manager-detector": ["package-manager-detector@0.2.11", "", { "dependencies": { "quansync": "^0.2.7" } }, "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ=="], + "path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="], + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], @@ -732,10 +1268,72 @@ "plimit-lit": ["plimit-lit@1.6.1", "", { "dependencies": { "queue-lit": "^1.5.1" } }, "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA=="], + "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], + "postcss": ["postcss@8.5.20", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-lW616l85ucIQL+FocMmL7pQFPqBmwejrCMg+iPxyImlrANNJG9NHq/RkyCZopDhd8C3LA03PHRJDjkbGu8vvug=="], + "postcss-calc": ["postcss-calc@10.1.1", "", { "dependencies": { "postcss-selector-parser": "^7.0.0", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.38" } }, "sha512-NYEsLHh8DgG/PRH2+G9BTuUdtf9ViS+vdoQ0YA5OQdGsfN4ztiwtDWNtBl9EKeqNMFnIu8IKZ0cLxEQ5r5KVMw=="], + + "postcss-colormin": ["postcss-colormin@7.0.10", "", { "dependencies": { "@colordx/core": "^5.4.3", "browserslist": "^4.28.2", "caniuse-api": "^3.0.0", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-yFr6JezOolHLta/buLE71VKPh2mXursp4saVe98/ol8ZnEWhL+racShqPKlvd/DKWLre/39B6HhcMXf7RZ3hxg=="], + + "postcss-convert-values": ["postcss-convert-values@7.0.12", "", { "dependencies": { "browserslist": "^4.28.2", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-xurKu5qqk4viR3Cp3p4xBR4KfnZm4w4ys6+UBwBmeuBSNkH7+DtLnYOYnOffgtE4yx8sH9S1VZ6RAAvROXzP2Q=="], + + "postcss-discard-comments": ["postcss-discard-comments@7.0.8", "", { "dependencies": { "postcss-selector-parser": "^7.1.1" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-CvvS5S9WrXblFXCEJ9nVo+4z+eA7zSC7Z88V1HEJuwlQhlFnYTIjg1xJY+BCUiG2bvICap2tXii4mP22BD108Q=="], + + "postcss-discard-duplicates": ["postcss-discard-duplicates@7.0.4", "", { "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-VBNn1+EuMZkeGVVtz0gRfbNGtx9IFgAsAV+E2pHtXPrp4qfGBkhTIiAuE/wrb+Y6Pakg9NewAlfTpYIFAWODtw=="], + + "postcss-discard-empty": ["postcss-discard-empty@7.0.3", "", { "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-M2pyjQCU+/7cMHVtL6bKTHjv0lZnPLMpicgr67Dlth7AbuV9gjVTtUqaRwn6Pp6BwSDspUzhz8SaUrRykJU5Dw=="], + + "postcss-discard-overridden": ["postcss-discard-overridden@7.0.3", "", { "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-aNovXo9UsZuRNLzHJtp13lHIvinDPfiXBPePpXkSjCbgp++iU2FqE+YxvjIsg6EdyPZsASFbfu+JcBFVsErXIQ=="], + + "postcss-merge-longhand": ["postcss-merge-longhand@7.0.7", "", { "dependencies": { "postcss-value-parser": "^4.2.0", "stylehacks": "^7.0.11" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-b3mfYUxR388u5Pt0HPcVIUtUDn/k15UfTY9M+ORW+meCR6JLNxoZffiYvXyOYQoRYQNZyX/UFkMCM/mNHxe1qA=="], + + "postcss-merge-rules": ["postcss-merge-rules@7.0.11", "", { "dependencies": { "browserslist": "^4.28.2", "caniuse-api": "^3.0.0", "cssnano-utils": "^5.0.3", "postcss-selector-parser": "^7.1.1" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-SJUPM18g2BmPhf8BVlbwqWz4aK3pLu6u6xjfwEzra7xL6IBR10sUaiB++EzqcVfadPHrKBSMlNdP+XieykhI+Q=="], + + "postcss-minify-font-values": ["postcss-minify-font-values@7.0.3", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-yilG/VOaNI74IylQvAQQxm3/wZVBkXyYUqNUAdxqwtbWUXPsbK1q8Ms0mL83v+f8YicgcyfYCRZtWACUdYajpA=="], + + "postcss-minify-gradients": ["postcss-minify-gradients@7.0.5", "", { "dependencies": { "@colordx/core": "^5.4.3", "cssnano-utils": "^5.0.3", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-YraROyQRg3BI1+Hg8E05B/JPdnTm8EDSVu4P2BxdM+CRiOyfmou809+chGIqo6fQqwjPGQ947nbGncSjmTU1WQ=="], + + "postcss-minify-params": ["postcss-minify-params@7.0.9", "", { "dependencies": { "browserslist": "^4.28.2", "cssnano-utils": "^5.0.3", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-R8itbB8BhlpoYyBm1ou0dD+vJnQ3F6adQipR4UnkCHUwlo+S9WXJaDRg1RHjC8YVAtIdrQzSWvJl40HnGDTKjA=="], + + "postcss-minify-selectors": ["postcss-minify-selectors@7.1.2", "", { "dependencies": { "browserslist": "^4.28.1", "caniuse-api": "^3.0.0", "cssesc": "^3.0.0", "postcss-selector-parser": "^7.1.1" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-aQtrEWKwqafNlExcKHQvPGsXR2+vlUqqJtf5XsCQcgsSb5PL4wlujWBYDJuWsP4UnQX1YHDHU8qRlD+1PzTQ+Q=="], + + "postcss-normalize-charset": ["postcss-normalize-charset@7.0.3", "", { "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-NoBfZu8PR4c2NlmjvrqQTzCzLY79hwcSRgNQ3ZiNK0ABzf9kYKloE/jNj+/8GQY1wsm8pRRgANk6ydLH8cwo0Q=="], + + "postcss-normalize-display-values": ["postcss-normalize-display-values@7.0.3", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-ldsCX0QIt05pKIOobZtVQ48wXJecr+czw4+e1/YjVhLMqslShgpVxgPtI2CefURR8oyVoYaU/l829MMwExDMLw=="], + + "postcss-normalize-positions": ["postcss-normalize-positions@7.0.4", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-VEvlpeGd3Ju1Hqa/oN4jaP3+ms4laYwkEL9N9u+B6k54PZjXbW1n6wI+aVprf1BQXlCYpS5+1pl/7/vHiKgARg=="], + + "postcss-normalize-repeat-style": ["postcss-normalize-repeat-style@7.0.4", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-6mPKlY/8cSaDHxX502wERADarJsccwlky6yIrOapHH2ZgfoKAV94SbiTKfKEs4EEpdazuc3J72WsqeYk7hp9+Q=="], + + "postcss-normalize-string": ["postcss-normalize-string@7.0.3", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-HnEQPUchi1eznmDKEYrKUTqrprEq97SrpUYClgUkv7V2zRODD9DFoUsYU+m9ZOetmD5ku7fEMZB/lwy8IT6xVQ=="], + + "postcss-normalize-timing-functions": ["postcss-normalize-timing-functions@7.0.3", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-zmEzHdvpZBZu0OKlbJSfgASQvaayyAoVuWtvyr34IJ/LyS+DaOKvvR3EvFJ9RWWtNIx+CMvO125OVophaxNYew=="], + + "postcss-normalize-unicode": ["postcss-normalize-unicode@7.0.9", "", { "dependencies": { "browserslist": "^4.28.2", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-DRAdWfeh/TjmhLJsw91vdiWCnUod9iwvM7xyS02/nF/sLsCR3A8l3pztrSUrWG8DSBqfX7yEk9FM0USaVJ2mSg=="], + + "postcss-normalize-url": ["postcss-normalize-url@7.0.3", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-CL93wmloq5qsffmFv+bw24MIRbmhHrp53qoh1LDAb/5TtjWEXI/np4xcP/Gw9oWCb2XyWnqHYLDUwiKRoJBA1Q=="], + + "postcss-normalize-whitespace": ["postcss-normalize-whitespace@7.0.3", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-FdHjjn+Ht5Z2ZRjNOmeCbNq6lq09sUYKpmlF/Aq0XjVNSLTL6fmHlA/3swN2wP2caY9GV/tjSDcIIyS7aN7W0A=="], + + "postcss-ordered-values": ["postcss-ordered-values@7.0.4", "", { "dependencies": { "cssnano-utils": "^5.0.3", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-nubSi49hDHQk4E8KIj+IbLY8Bg+8OcSUEhgyolgM+atnOvXjV7EjaR6bac4YGZoFyPa9mWoAF3EaYbWdFkKqVg=="], + + "postcss-reduce-initial": ["postcss-reduce-initial@7.0.9", "", { "dependencies": { "browserslist": "^4.28.2", "caniuse-api": "^3.0.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-ztTNPdIxXTxtBcG03E9u8v44M4ElXbMIRT7pf2onlquGula0Y83nKKxqM22FA/hMgkfCjN7ohevkVlaNwI8iOQ=="], + + "postcss-reduce-transforms": ["postcss-reduce-transforms@7.0.3", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-FXsnN9ZwcZTT8Yf8cAHA8qIGUXcX6WfLd9JoYhrdDfmvsVhhfqkkv7m4AC3rwFOfz+GzkUa87OCKF9dUcicd+g=="], + + "postcss-selector-parser": ["postcss-selector-parser@7.1.5", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw=="], + + "postcss-svgo": ["postcss-svgo@7.1.3", "", { "dependencies": { "postcss-value-parser": "^4.2.0", "svgo": "^4.0.1" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-2QfoFOYMcj8lwcVEf9WeTlkVIAm7u2QvOEhMzkQU3KUhhGX/l8hVV9EtjMv4iq3E9iI3OeeMN0YoMLbGusuigw=="], + + "postcss-unique-selectors": ["postcss-unique-selectors@7.0.7", "", { "dependencies": { "postcss-selector-parser": "^7.1.1" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-d+sCkaRnSefghOUdH8CMJZV9yUQhj2ojpe8Nw/lA+LV1UOfeleGkLTl6XdCFFSai9UJ+DJPb69FFuqthXYsY8w=="], + + "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], + "prettier": ["prettier@2.8.8", "", { "bin": { "prettier": "bin-prettier.js" } }, "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="], + "punycode.js": ["punycode.js@2.3.1", "", {}, "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="], + "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], "queue-lit": ["queue-lit@1.5.2", "", {}, "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw=="], @@ -746,6 +1344,14 @@ "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + "reduce-configs": ["reduce-configs@1.1.2", "", {}, "sha512-AgBP55V8FC7NaqoOP2RCbTpu6LE+YuX3LUZkNAoitcfyS3/PIC8Obg/TJrBzTkJ+lDvZv0TTAeDpLkzjTtYlbw=="], + + "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="], + + "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="], + + "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], @@ -754,26 +1360,66 @@ "rolldown": ["rolldown@1.1.5", "", { "dependencies": { "@oxc-project/types": "=0.139.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.1.5", "@rolldown/binding-darwin-arm64": "1.1.5", "@rolldown/binding-darwin-x64": "1.1.5", "@rolldown/binding-freebsd-x64": "1.1.5", "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", "@rolldown/binding-linux-arm64-gnu": "1.1.5", "@rolldown/binding-linux-arm64-musl": "1.1.5", "@rolldown/binding-linux-ppc64-gnu": "1.1.5", "@rolldown/binding-linux-s390x-gnu": "1.1.5", "@rolldown/binding-linux-x64-gnu": "1.1.5", "@rolldown/binding-linux-x64-musl": "1.1.5", "@rolldown/binding-openharmony-arm64": "1.1.5", "@rolldown/binding-wasm32-wasi": "1.1.5", "@rolldown/binding-win32-arm64-msvc": "1.1.5", "@rolldown/binding-win32-x64-msvc": "1.1.5" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA=="], + "rslog": ["rslog@2.3.0", "", {}, "sha512-g2wW/ermwzGTLlzGdJBDRc4YKz2/yPBjf57w9g5CvhtpZ91Xq95OaWku0oNHYi+XsuV6v8QrCo2oJJR/pCUR8g=="], + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + "safe-array-concat": ["safe-array-concat@1.1.4", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "get-intrinsic": "^1.3.0", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg=="], + + "safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="], + + "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="], + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + "sax": ["sax@1.6.1", "", {}, "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q=="], + + "schema-utils": ["schema-utils@4.3.3", "", { "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } }, "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA=="], + "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], + "serialize-javascript": ["serialize-javascript@7.1.0", "", {}, "sha512-RNEqWOyhhUQYN9V1GfHwu9AR/g+NTciH6Z5u3/no6X3/w+04J2lVDL+svFQVXgXrEGBMG2puMVN3gq2SNGuTGw=="], + + "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], + + "set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="], + + "set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="], + "sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="], "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + "shell-quote": ["shell-quote@1.10.0", "", {}, "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA=="], + + "side-channel": ["side-channel@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4", "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ=="], + + "side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="], + + "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], + + "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], + "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], + "socket.io": ["socket.io@4.8.1", "", { "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" } }, "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg=="], + + "socket.io-adapter": ["socket.io-adapter@2.5.8", "", { "dependencies": { "debug": "~4.4.1", "ws": "~8.21.0" } }, "sha512-6Oy52pbg+kvdCVvjcN+FnY7BvxZ7cIHNScbvztT/It5d0vbwoJoVZmF2gjJmnV0/4WlXRfG15zc45ySk9Ah8bw=="], + + "socket.io-parser": ["socket.io-parser@4.2.7", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.4.1" } }, "sha512-IH/iSeO9T6gz1KkFleGDWkG9N3dl4jXVYUtMhIqH10Md0ttMer8nUNWiP1DKuNrybD2xBrixLJdCC9J6ECoYkg=="], + + "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], + "spawndamnit": ["spawndamnit@3.0.1", "", { "dependencies": { "cross-spawn": "^7.0.5", "signal-exit": "^4.0.1" } }, "sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg=="], "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], @@ -782,20 +1428,38 @@ "std-env": ["std-env@4.2.0", "", {}, "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw=="], + "stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="], + + "string.prototype.trim": ["string.prototype.trim@1.2.11", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-object-atoms": "^1.1.2", "has-property-descriptors": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w=="], + + "string.prototype.trimend": ["string.prototype.trimend@1.0.10", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.2" } }, "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw=="], + + "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="], + "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], - "supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], + "stylehacks": ["stylehacks@7.0.11", "", { "dependencies": { "browserslist": "^4.28.2", "postcss-selector-parser": "^7.1.1" }, "peerDependencies": { "postcss": "^8.5.13" } }, "sha512-iODNfhXVLqc5LADs+Y6Oh5wJuK5ZcHbVng8aiK3y9pjMQdc5hLrBW0eFU6FtnpNrE6PoEg/MmFTU4waotj5WNg=="], + + "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + + "svgo": ["svgo@4.0.2", "", { "dependencies": { "commander": "^11.1.0", "css-select": "^5.1.0", "css-tree": "^3.0.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", "sax": "^1.5.0" }, "bin": "./bin/svgo.js" }, "sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng=="], + + "tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="], "term-size": ["term-size@2.2.1", "", {}, "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="], + "terser": ["terser@5.50.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-CN9BVxWhgS/hRxtUMjtC2uRWSTcSfQFHMDWma6sKKfIivCD91sM+FOPfvwoaRMqCSrUpe1nv3jDamd9eEQ4y+w=="], + "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], "tinyexec": ["tinyexec@1.2.4", "", {}, "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg=="], "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], + "tinypool": ["tinypool@2.1.0", "", {}, "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw=="], + "tinyrainbow": ["tinyrainbow@3.1.0", "", {}, "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], @@ -804,8 +1468,22 @@ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "type-detect": ["type-detect@4.1.0", "", {}, "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw=="], + + "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="], + + "typed-array-byte-length": ["typed-array-byte-length@1.0.3", "", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="], + + "typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="], + + "typed-array-length": ["typed-array-length@1.0.8", "", { "dependencies": { "call-bind": "^1.0.9", "for-each": "^0.3.5", "gopd": "^1.2.0", "is-typed-array": "^1.1.15", "possible-typed-array-names": "^1.1.0", "reflect.getprototypeof": "^1.0.10" } }, "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g=="], + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + "uc.micro": ["uc.micro@3.0.0", "", {}, "sha512-U3PppEkleoTnIfi8BozMx3yju3qc/L6SwqWo2Sw+54PX+PX0q9I+r1Um5HCmqD7n9VDX5/v3vQH/AjA6deDdtw=="], + + "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], + "undici": ["undici@7.28.0", "", {}, "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA=="], "undici-types": ["undici-types@7.24.6", "", {}, "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="], @@ -814,14 +1492,36 @@ "universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + "update-browserslist-db": ["update-browserslist-db@1.3.1", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], + "vite": ["vite@8.1.5", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.5", "postcss": "^8.5.17", "rolldown": "~1.1.5", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.3.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw=="], "vitest": ["vitest@4.1.10", "", { "dependencies": { "@vitest/expect": "4.1.10", "@vitest/mocker": "4.1.10", "@vitest/pretty-format": "4.1.10", "@vitest/runner": "4.1.10", "@vitest/snapshot": "4.1.10", "@vitest/spy": "4.1.10", "@vitest/utils": "4.1.10", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.10", "@vitest/browser-preview": "4.1.10", "@vitest/browser-webdriverio": "4.1.10", "@vitest/coverage-istanbul": "4.1.10", "@vitest/coverage-v8": "4.1.10", "@vitest/ui": "4.1.10", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "./vitest.mjs" } }, "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw=="], + "wasm-feature-detect": ["wasm-feature-detect@1.9.0", "", {}, "sha512-zonE+xlIIYtxPy++L24ow0hAD8CICb4+FgPyROd3buyXIqsJvUEDkBgfCCoXOd1Hu3DUr0GOfnPIdcGV+YpNaA=="], + + "watchpack": ["watchpack@2.5.2", "", { "dependencies": { "graceful-fs": "^4.1.2" } }, "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg=="], + + "webpack": ["webpack@5.109.2", "", { "dependencies": { "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.16.0", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.24.4", "es-module-lexer": "^2.1.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "graceful-fs": "^4.2.11", "mime-db": "^1.54.0", "minimizer-webpack-plugin": "^5.6.1", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", "watchpack": "^2.5.2", "webpack-sources": "^3.5.1" }, "bin": { "webpack": "bin/webpack.js" } }, "sha512-U9/cvLzxObKNEZ9+TtdqrHM5/9z3lgl2c+c4BzbqGxFQvQvBAq87yql5A8pQ+rrMbS496MZJeF5enVBndIy2hw=="], + + "webpack-sources": ["webpack-sources@3.5.1", "", {}, "sha512-jyuiGJdtvY434z5bUZrjz67v76/ePNvFZTp9Mdz29IlH4+GPsgyGjiv0fKI+M7BdkU6ADjulUcKAd3tUK3WlEw=="], + "whatwg-mimetype": ["whatwg-mimetype@3.0.0", "", {}, "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q=="], "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + "which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="], + + "which-builtin-type": ["which-builtin-type@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="], + + "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="], + + "which-typed-array": ["which-typed-array@1.1.22", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.9", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw=="], + "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], "workerd": ["workerd@1.20260721.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260721.1", "@cloudflare/workerd-darwin-arm64": "1.20260721.1", "@cloudflare/workerd-linux-64": "1.20260721.1", "@cloudflare/workerd-linux-arm64": "1.20260721.1", "@cloudflare/workerd-windows-64": "1.20260721.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-b/DWhpV0jTudzQpLhDovcOgBz233386q+3Hbari7CLCNT9UXxjQziSTZ9yCoKdT2K3TSx5jrwlOisq8hlLWXYg=="], @@ -834,6 +1534,10 @@ "youch-core": ["youch-core@0.3.3", "", { "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } }, "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA=="], + "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], + + "@lynx-js/rspeedy/@rsbuild/core": ["@rsbuild/core@2.1.10", "", { "dependencies": { "@rspack/core": "~2.1.8", "@swc/helpers": "^0.5.23" }, "peerDependencies": { "core-js": ">= 3.0.0" }, "optionalPeers": ["core-js"], "bin": { "rsbuild": "./bin/rsbuild.js" } }, "sha512-lwxC5w88U2AMv6aNwG3VH7+AV33N4JJQjD//egVWFsMbV+OE/bnfCsurSpX8s3lGyRYkJMwUVN+YXMbmmYZFfw=="], + "@manypkg/find-root/@types/node": ["@types/node@12.20.55", "", {}, "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="], "@manypkg/find-root/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], @@ -842,16 +1546,84 @@ "@manypkg/get-packages/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], + "@poppinss/dumper/supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], + + "@rsbuild/plugin-check-syntax/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + + "@rsdoctor/core/fs-extra": ["fs-extra@11.4.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA=="], + + "@rsdoctor/core/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + + "@rsdoctor/graph/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + + "@rsdoctor/types/@types/estree": ["@types/estree@1.0.5", "", {}, "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="], + + "@rsdoctor/types/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + + "@rsdoctor/utils/@types/estree": ["@types/estree@1.0.5", "", {}, "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="], + + "@rsdoctor/utils/fs-extra": ["fs-extra@11.4.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA=="], + + "@rsdoctor/utils/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "@rspack/binding-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.3", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.3", "tslib": "^2.4.0" } }, "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg=="], + + "@rspack/binding-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA=="], + "anymatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], + "chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="], + + "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "engine.io/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], + + "engine.io/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "esrecurse/estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "htmlparser2/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], + + "markdown-it/argparse": ["argparse@3.0.0", "", {}, "sha512-BOp5NMrHqKxmq/OLr+clzzrRxgOKSLkcjmkWuChp7Irqwn4s74WjOBPIgWfA/HMcBnVkZ5XEuf9uUqzlpfCQ6A=="], + + "markdown-it/entities": ["entities@8.0.0", "", {}, "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA=="], + "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], + "mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + "miniflare/ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="], + "minimizer-webpack-plugin/jest-worker": ["jest-worker@27.5.1", "", { "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg=="], + "read-yaml-file/js-yaml": ["js-yaml@3.15.0", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog=="], "readdirp/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], + "socket.io-adapter/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "socket.io-parser/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "svgo/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], + + "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], + + "@rsdoctor/core/fs-extra/jsonfile": ["jsonfile@6.2.1", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q=="], + + "@rsdoctor/core/fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + + "@rsdoctor/utils/fs-extra/jsonfile": ["jsonfile@6.2.1", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q=="], + + "@rsdoctor/utils/fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + + "@rsdoctor/utils/strip-ansi/ansi-regex": ["ansi-regex@6.3.0", "", {}, "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ=="], + + "@rspack/binding-wasm32-wasi/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g=="], + + "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="], + "read-yaml-file/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], } } diff --git a/docs/mini-lynx-explorer.md b/docs/mini-lynx-explorer.md new file mode 100644 index 0000000..5becf8b --- /dev/null +++ b/docs/mini-lynx-explorer.md @@ -0,0 +1,195 @@ +# rspeedy, a QR code, and Lynx Explorer + +How a `@amritk/mini-lynx` app gets onto a phone, why the build has the shape it +has, and — the part that matters most — exactly which links in that chain have +been verified and which have not. + +The code this describes is +[`packages/mini-lynx-rsbuild-plugin`](../packages/mini-lynx-rsbuild-plugin) and +[`apps/starter-mini-lynx`](../apps/starter-mini-lynx). + +--- + +## 1. The loop + +``` +rspeedy dev → http://:3000/main.lynx.bundle → QR code → Explorer → app + ↑ │ + └──────────────────── save a file, the page reloads ───────────────────────────────┘ +``` + +Concretely: + +```bash +cd apps/starter-mini-lynx +bun install +bun run dev +``` + +``` + ➜ Lynx http://192.168.1.24:3000/main.lynx.bundle + ➜ ∟ Fullscreen http://192.168.1.24:3000/main.lynx.bundle?fullscreen=true +``` + +Scan either QR code with [Lynx Explorer](https://lynxjs.org/guide/start/quick-start.html) +— the Lynx team's host app, whose whole job is to open a bundle URL — or paste +the URL into its *Enter Card URL* box, which is what a simulator needs. The app +is on the screen. Edit `src/main-thread.tsx`, save, and it reloads. + +`bun run build` produces `dist/main.lynx.bundle`, which is the same artifact +without the dev server around it. + +## 2. Why a build plugin was needed at all + +A Lynx template is not a bundle with an entry point. It is a container with two +code slots and a compiled stylesheet: + +| Slot | What runs there | In this repo | +| --- | --- | --- | +| main-thread chunk | the Element PAPI, executed by the engine to build the first screen | your whole app | +| background chunk (`/app-service.js`) | `NativeModules`, `GlobalEventEmitter` | `@amritk/mini-lynx-native/background`, or nothing | +| CSS | compiled by the encoder into the template, not shipped as text | `app.css` | + +`@lynx-js/rspeedy` builds the container and runs the dev server. **Which code +goes in which slot is the framework's to say**, and every framework says it in a +plugin of its own — ReactLynx's is `@lynx-js/react-rsbuild-plugin`. There is no +framework-agnostic plugin underneath it to reuse: `@lynx-js/rsbuild-plugin`, +which sounds like one, is the dev server and the per-thread minifier split +rather than the template. + +So the gap between "this runtime works" and "you can run it on your phone" was +about 150 lines of rspack wiring that every consumer would otherwise have +written, wrongly, once each. That is what the plugin is. + +The single sharpest edge in it: the encoder decides which chunk is the first +screen by reading one `lynx:main-thread` boolean off the asset's info. Nothing +sets it for a runtime that is not ReactLynx, and nothing complains when it is +missing — a template with no main-thread slot is a legal template. You get a +build that succeeds, a bundle that loads, and a blank screen. + +## 3. Reload, not hot update + +The dev build adds two modules to the front of the background chunk: +`@lynx-js/webpack-dev-transport/client` (the socket back to the dev server, +which rspeedy aliases with the host, port and token already in its query) and +`@rspack/core/hot/dev-server`, which rspeedy aliases to the Lynx build that +reloads through the devtool rather than through a `window.location` that does +not exist. + +Nothing in a mini-lynx app accepts a hot update, and nothing should. A hot +update is a diff applied to a live module graph; this runtime has no such graph, +because a component runs once and the tree it built is mutated by signals +forever. There is no second render for a new module version to be applied to. + +What the runtime *does* have is a teardown: `renderPage` claims +`removeComponents`, which the engine calls before it rebuilds. So the fallback — +an update nothing accepted bubbles to the entry, fails to apply, and the page +reloads — is not a degraded outcome here. It is the correct one, and it is +cheap: the app is a few hundred kilobytes served off localhost. + +The reload itself is `Page.reload` sent over the devtool's CDP channel, so it +needs Explorer (or a host app with the devtool enabled). Without one, the socket +still connects and the terminal still rebuilds; you pull to refresh by hand. + +## 4. What has been verified, and how + +This matters more than usual here, because the failure mode of a Lynx build is +silence: the bundle encodes, the device loads it, and nothing appears. + +### Verified in CI, on every commit + +`packages/mini-lynx-rsbuild-plugin/src/build.test.ts` runs **real rspeedy +builds** of a real app — one with a background module and one without, since the +second is what a consumer gets before they have anything native to reach for — +and then runs the artifact: + +- the template is emitted, and is a template rather than an empty container; +- the main-thread slot is filled — the failure above, caught directly; +- the background slot is filled, and reaches the encoder under the + `/app-service.js` name the engine's module loader requires; +- the app's CSS was compiled into the template; +- the engine's module wrapper is on the background chunk and **not** on the + main-thread one; +- the built main-thread chunk, pulled out of the encoder's input and executed in + a `node:vm` context whose globals are `createFakeEngine`'s Element PAPI, + **renders the app** — the right tree, and `firstScreen` emitted; +- a tap dispatched through that same fake mutates the existing `` element + rather than replacing it, so the runtime's whole claim survives the bundler. + +That last pair is the point. A JSX transform pointed at React, a wrapper on the +wrong chunk, a `renderPage` that never reached the global object: each is a +passing string search over the template and a blank screen on the phone. Each +fails that test instead. + +`apps/starter-mini-lynx/src/app.test.ts` does the same for the app itself, +without a build — which is also the shortest demonstration that an app on this +runtime is testable with no device, no emulator and no browser. + +### Verified by hand, in a container, against the real dev server + +Everything up to the phone: + +- `rspeedy dev` starts, prints the LAN URL and both QR schemas; +- `GET http://:3000/main.lynx.bundle` returns **200** and a real encoded + template (the magic bytes, `/app-service.js`, the main-thread code inside it); +- the dev bundle carries the transport client and the devtool reload path — the + `rsbuild-hmr` socket path and `Page.reload` are both in the served bytes; +- editing `src/main-thread.tsx` triggers a rebuild and the **next fetch of the + same URL returns the edited app**, which is the watch half of the loop. + +### Not verified — no device was available + +Everything from the QR code onward: + +- that Explorer renders this template, at `targetSdkVersion: '3.2'`, in the + version you install; +- that the reload actually fires on save on the device, rather than the socket + connecting and the CDP call being refused; +- that events reach handlers on hardware. This is the runtime's own open + question rather than the build's — the worklet-handle transport in + `@amritk/mini-lynx` is inferred from the engine's source, and + `@amritk/mini-lynx/bridge` is the fallback if it is wrong. See *Before you + ship* in [the runtime's README](../packages/mini-lynx/README.md); +- layout. The fake engine records what it was asked to do and lays nothing out. + +**Treat the phone half as unproven.** The build half is not. + +## 5. When the phone shows nothing + +In rough order of likelihood: + +1. **The phone cannot reach your laptop.** The URL is a LAN address; a guest + network, a VPN, or a host-only firewall rule all produce exactly the same + symptom. `curl` the URL from another device on the same network first. +2. **`targetSdkVersion` is ahead of your Explorer.** An Explorer older than the + template refuses it outright and says so in terms of the SDK rather than your + code. The plugin's default is `'3.2'`, which is also ReactLynx's. +3. **A blank screen with a running app** is the main-thread slot being empty, or + a throw during the build of the tree. `renderPage` emits `firstScreen` even + when the root component threw — deliberately, because a splash screen that + never dismisses tells you nothing — so a blank screen means look for the + error report, and `setErrorHandler` is where it went. +4. **The tree renders and nothing responds to touch.** That is the worklet + transport question above, not the build. Swap in + `namedHandlerTransport` from `@amritk/mini-lynx/bridge` and see if the app + comes alive. +5. **The screen labelled `background chunk` says `no answer`.** The background + half is missing or threw. It is the one part of the app whose failure is + otherwise invisible, which is why the starter puts it on screen. + +## 6. What is deliberately not here + +**No `create-mini-lynx` scaffolder.** The app is four files and copying them is +faster than maintaining a generator. `apps/starter-mini-lynx` is the template, +and its README says which lines to change. + +**No web environment.** The plugin does nothing in an environment named `web`. +A mini-lynx app on the web is a real question — the runtime's DOM story is +`@amritk/mini`, not a Lynx build — and a plugin that half-configured one would +be worse than a plugin that skips it. + +**No lazy bundles, and no layer-based module resolution.** ReactLynx compiles +the same source twice, once per thread, and uses webpack layers to swap what +each import resolves to. Here the two chunks are two files you wrote. That is +simpler, and it means nothing stops a background module from being imported into +the main-thread chunk: if you import it, you get it. diff --git a/llms-full.txt b/llms-full.txt index 2a4ffce..105983b 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -307,6 +307,28 @@ JSX config in the consuming package (this is **not** the React runtime): { "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "@amritk/mini-lynx" } } ``` +### The build that produces the two chunks + +The bundler that "marks the main-thread chunk" is +[rspeedy](https://lynxjs.org/rspeedy), Lynx's own, and the marking is +`@amritk/mini-lynx-rsbuild-plugin`: + +```ts +// lynx.config.ts +import { pluginMiniLynx } from '@amritk/mini-lynx-rsbuild-plugin' +import { pluginQRCode } from '@lynx-js/qrcode-rsbuild-plugin' +import { defineConfig } from '@lynx-js/rspeedy' + +export default defineConfig({ + source: { entry: { main: './src/main-thread.tsx' } }, + plugins: [pluginQRCode({ fullscreen: true }), pluginMiniLynx({ background: './src/background.ts' })], +}) +``` + +`source.entry` is the **main-thread** entry; the background module is the +plugin's `background` option, not a second entry. `rspeedy dev` prints a QR code +for Lynx Explorer; `rspeedy build` writes `dist/main.lynx.bundle`. + ## Handlers run on the main thread Driving the Element PAPI is what puts this runtime there, so a `bindtap` handler @@ -1611,3 +1633,135 @@ import { createFakeContexts, createFakeEmitter } from '@amritk/mini-lynx-native/ - **Nothing here is reactive.** No signals, deliberately — a second edge onto the signal engine gives a consumer two reactive graphs that cannot see each other's writes. Wire a promise into your own signal in one line. + +--- + +# AI.md — @amritk/mini-lynx-rsbuild-plugin + +For an LLM consuming this package. Editing the repo instead? See +[`AGENTS.md`](./AGENTS.md). + +## Mental model + +This is a **build-time** package. Nothing here runs on a device: it is one +rsbuild plugin that teaches [rspeedy](https://lynxjs.org/rspeedy) — Lynx's +build tool — how to turn a `@amritk/mini-lynx` app into a `.lynx.bundle` +template. + +A Lynx template is not a bundle with an entry point. It is a container with two +code slots — a **main-thread** chunk the engine executes to build the first +screen, and a **background** chunk it loads as `/app-service.js` — plus the CSS, +which the encoder compiles rather than shipping as text. rspeedy builds the +container; which code goes in which slot is the framework's to say, and every +framework says it in a plugin of its own. ReactLynx's is +`@lynx-js/react-rsbuild-plugin`. This is that plugin for a runtime that renders +on the main thread and drives the Element PAPI itself. + +## The surface, in full + +```ts +import { pluginMiniLynx, type PluginMiniLynxOptions } from '@amritk/mini-lynx-rsbuild-plugin' + +type PluginMiniLynxOptions = { + /** The module that runs in the background chunk. Defaults to a stub that installs nothing. */ + background?: string + /** The Lynx engine version the template is encoded for. Default '3.2'. */ + targetSdkVersion?: string +} + +pluginMiniLynx(options?: PluginMiniLynxOptions): RsbuildPlugin +``` + +That is the whole package. One function, two options. + +## A complete app + +Four files. There is no `App.tsx` convention and no framework entry to extend — +`renderPage` is the entry. + +```ts +// lynx.config.ts +import { pluginMiniLynx } from '@amritk/mini-lynx-rsbuild-plugin' +import { pluginQRCode } from '@lynx-js/qrcode-rsbuild-plugin' +import { defineConfig } from '@lynx-js/rspeedy' + +export default defineConfig({ + source: { entry: { main: './src/main-thread.tsx' } }, + plugins: [ + pluginQRCode({ fullscreen: true }), + pluginMiniLynx({ background: './src/background.ts' }), + ], +}) +``` + +```tsx +// src/main-thread.tsx — the main-thread chunk, and the whole app +import { renderPage, signal } from '@amritk/mini-lynx' +import './app.css' + +const App = () => { + const count = signal(0) + return ( + count(count() + 1)}> + {() => `tapped ${count()} times`} + + ) +} + +renderPage(App) +``` + +```ts +// src/background.ts — the background chunk; omit it and the default stub is used +import { installNativeBridge } from '@amritk/mini-lynx-native/background' + +installNativeBridge() +``` + +```jsonc +// tsconfig.json — the build reads jsxImportSource from the plugin, but the +// EDITOR reads it from here, so both have to say it +{ + "compilerOptions": { + "jsx": "react-jsx", + "jsxImportSource": "@amritk/mini-lynx", + "types": ["@lynx-js/types", "@lynx-js/rspeedy/client"] + } +} +``` + +Then `rspeedy dev`, scan the QR code with Lynx Explorer, and the app is on the +phone. + +## Gotchas + +**`source.entry` names the MAIN-THREAD entry.** The background module is the +plugin's `background` option, not a second entry. Adding it to `source.entry` +would build a second template rather than a second chunk. + +**Nothing hot-updates.** An edit reloads the whole page through the devtool. +This is not a limitation being worked around: a component in this runtime runs +once, so there is no re-render for a new module version to be applied to. What +makes the reload safe is that `renderPage` claims `removeComponents` and tears +the previous tree down. + +**Live reload needs the devtool.** The reload is `Page.reload` over the CDP +channel, which Lynx Explorer has and a production host app usually does not. + +**The plugin is for the `lynx` environment.** In a `web` environment it does +nothing — a web build of a mini-lynx app is not a solved problem here, and a +plugin that half-configured one would be worse than a plugin that skips it. + +**`targetSdkVersion` is a compatibility floor, not a feature switch.** An +Explorer older than the version a template names refuses the template outright, +with a message about the SDK rather than about your code. + +## Where the pieces are + +| Thing | Owned by | +| --- | --- | +| The `.lynx.bundle` container, and encoding it | `@lynx-js/template-webpack-plugin` (a dependency here) | +| The dev server, the LAN URL, HMR transport | `@lynx-js/rspeedy` | +| The QR code in the terminal | `@lynx-js/qrcode-rsbuild-plugin` | +| Which chunk is which, and the JSX transform | this package | +| Everything that runs on the device | `@amritk/mini-lynx` | diff --git a/llms.txt b/llms.txt index b910ec1..7401cd2 100644 --- a/llms.txt +++ b/llms.txt @@ -15,6 +15,7 @@ mini is a pre-alpha monorepo of independently published `@amritk/*` packages. Ea - [@amritk/lynx-secure-storage](https://github.com/amritk/mini/blob/main/packages/lynx-secure-storage/README.md): Encrypted key-value storage for Lynx: Keychain on iOS, EncryptedSharedPreferences on Android, and a promise-shaped facade that reaches them from the main thread — [AI.md](https://github.com/amritk/mini/blob/main/packages/lynx-secure-storage/AI.md) - [@amritk/mini-helpers](https://github.com/amritk/mini/blob/main/packages/mini-helpers/README.md): The pure helpers @amritk/mini and @amritk/mini-lynx both need: no reactivity, no platform, no dependencies — [AI.md](https://github.com/amritk/mini/blob/main/packages/mini-helpers/AI.md) - [@amritk/mini-lynx-native](https://github.com/amritk/mini/blob/main/packages/mini-lynx-native/README.md): The thread hop between a main-thread mini-lynx tree and Lynx's background-thread NativeModules, as a typed request/reply channel — [AI.md](https://github.com/amritk/mini/blob/main/packages/mini-lynx-native/AI.md) +- [@amritk/mini-lynx-rsbuild-plugin](https://github.com/amritk/mini/blob/main/packages/mini-lynx-rsbuild-plugin/README.md): The rspeedy build for a @amritk/mini-lynx app: two chunks, one .lynx.bundle template, and a QR code Lynx Explorer scans — [AI.md](https://github.com/amritk/mini/blob/main/packages/mini-lynx-rsbuild-plugin/AI.md) ## Optional diff --git a/package.json b/package.json index d64b3f5..f95b1b2 100644 --- a/package.json +++ b/package.json @@ -30,8 +30,8 @@ "check:android": "bun run scripts/check-android.ts", "format": "biome check --write --formatter-enabled=true --linter-enabled=false .", "lint": "biome lint .", - "test": "bun run --filter='./packages/*' --filter='@amritk/playground-mini-lynx' test", - "test:seq": "bun run --filter='./packages/*' --filter='@amritk/playground-mini-lynx' --sequential test", + "test": "bun run --filter='./packages/*' --filter='@amritk/playground-mini-lynx' --filter='@amritk/starter-mini-lynx' test", + "test:seq": "bun run --filter='./packages/*' --filter='@amritk/playground-mini-lynx' --filter='@amritk/starter-mini-lynx' --sequential test", "test:dist": "vitest run --config vitest.dist.config.ts", "bench": "bun run scripts/bench-compare.ts", "bench:reconciler": "bun run scripts/bench-reconciler.ts", diff --git a/packages/mini-lynx-rsbuild-plugin/AGENTS.md b/packages/mini-lynx-rsbuild-plugin/AGENTS.md new file mode 100644 index 0000000..673c391 --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/AGENTS.md @@ -0,0 +1,96 @@ +# AGENTS.md — @amritk/mini-lynx-rsbuild-plugin + +Contributor guide for AI agents editing **this package**. Repo-wide rules: +[`../../AGENTS.md`](../../AGENTS.md) and [`../../CLAUDE.md`](../../CLAUDE.md). +Consuming the package instead? See [`AI.md`](./AI.md). + +The rspeedy build for a `@amritk/mini-lynx` app: two chunks, one +`.lynx.bundle`, and the dev server Lynx Explorer scans. It is the only package +here that runs on a laptop rather than on a phone. + +## Commands + +```bash +bun run --filter='@amritk/mini-lynx-rsbuild-plugin' test +bun run --filter='@amritk/mini-lynx-rsbuild-plugin' types:check +bun run --filter='@amritk/mini-lynx-rsbuild-plugin' build +``` + +`apps/starter-mini-lynx` is this package's playground — the only place it is +used the way a consumer uses it. `cd apps/starter-mini-lynx && bun run build` +is the fastest end-to-end check; `bun run dev` is the one that involves a +device. + +## Layout + +``` +src/ + index.ts The `.` entry: pluginMiniLynx and its options + plugin.ts The plugin — entries, template, encoder, JSX, dev client + main-thread-info.ts The rspack plugin that flags the main-thread chunk + background-stub.ts The default background chunk: an empty module + build.test.ts A real rspeedy build, then its output, run for real +fixture/ The app build.test.ts builds. Not published. +``` + +## Invariants — do not break these + +- **The main-thread flag is the whole game.** The encoder splits an entry's + assets by one `lynx:main-thread` boolean on the asset info and treats + everything else as background code. Lose it and the build still succeeds, the + template still encodes, and the app has no first screen — a failure with no + error anywhere. `main-thread-info.ts` sets it; `build.test.ts` asserts the + main-thread slot is filled. +- **The runtime wrapper goes on the background chunk only.** It emits the + `tt.define` the engine's module loader needs. Wrapped around the main-thread + chunk it would register a module nobody requires; unwrapped, the background + chunk cannot be loaded at all. `NOT_MAIN_THREAD` is the regex that keeps them + apart, and both directions are asserted. +- **The background entry keeps the original entry name.** rspeedy derives the + template filename, the dev server's URLs and the QR code from + `source.entry`'s keys. Renaming that entry moves the URL the phone fetches + and breaks the QR code without breaking the build. +- **Module load stays free of side effects.** `@lynx-js/template-webpack-plugin` + opens a worker pool the moment it is imported, and this package is imported by + things that never build anything — a consumer's smoke test, an editor, the + repo's own `dist-smoke` sweep, which imports every published module under + Node. Both heavy imports are dynamic, inside `modifyBundlerChain`. Keep them + there. +- **No hot update path.** A component runs once here, so there is nothing for a + module-level diff to be applied to. The dev build adds the transport client + and `@rspack/core/hot/dev-server` so that an update nothing accepts falls + through to a devtool reload, which is the only correct outcome. Do not add + `module.hot.accept` anywhere, and do not add a refresh runtime. +- **Nothing here may know about the app.** No injected imports, no globals, no + generated entry wrapper. `renderPage` is the app's own line, and the whole + reason the runtime can be tested and the bundle can be reasoned about is that + the build adds nothing to the graph the app did not ask for. The one exception + is the two dev-only modules above, which exist only in `dev` and only in the + background chunk. + +## Testing + +`build.test.ts` runs real rspeedy builds of `fixture/` — with and without a +background module — and then **runs the artifact**: the main-thread chunk is +pulled out of the encoder's input and executed in a `node:vm` context whose +globals are `createFakeEngine`'s Element PAPI, which is the same shape the +engine presents, minus a screen. A JSX transform pointed at React, a wrapper on +the wrong chunk, a `renderPage` that never reached the global: each is a passing +string search and a blank screen on the phone, and each fails there instead. + +The fixture resolves `@amritk/mini-lynx` to the runtime's **source** through an +rspack alias, mirroring what `vitest.config.ts` does for every other suite here, +so a test never depends on a prior `bun run build`. + +What the suite cannot answer is whether the engine agrees: layout, the devtool +connection, the reload, and whether a given Explorer accepts the template's +`targetSdkVersion`. [`docs/mini-lynx-explorer.md`](../../docs/mini-lynx-explorer.md) +records what has been checked on hardware and what has not. + +## Versions this was built against + +rspeedy `0.16.4`, `@lynx-js/template-webpack-plugin` `0.15.1`, +`@lynx-js/runtime-wrapper-webpack-plugin` `0.2.3`. Every JS-side Lynx package is +still 0.x and the template plugin's hooks are marked `@alpha` upstream, so a +minor bump there can move this package's ground. The build test is what will +tell you: it fails on the artifact rather than on the API. diff --git a/packages/mini-lynx-rsbuild-plugin/AI.md b/packages/mini-lynx-rsbuild-plugin/AI.md new file mode 100644 index 0000000..26e084c --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/AI.md @@ -0,0 +1,129 @@ +# AI.md — @amritk/mini-lynx-rsbuild-plugin + +For an LLM consuming this package. Editing the repo instead? See +[`AGENTS.md`](./AGENTS.md). + +## Mental model + +This is a **build-time** package. Nothing here runs on a device: it is one +rsbuild plugin that teaches [rspeedy](https://lynxjs.org/rspeedy) — Lynx's +build tool — how to turn a `@amritk/mini-lynx` app into a `.lynx.bundle` +template. + +A Lynx template is not a bundle with an entry point. It is a container with two +code slots — a **main-thread** chunk the engine executes to build the first +screen, and a **background** chunk it loads as `/app-service.js` — plus the CSS, +which the encoder compiles rather than shipping as text. rspeedy builds the +container; which code goes in which slot is the framework's to say, and every +framework says it in a plugin of its own. ReactLynx's is +`@lynx-js/react-rsbuild-plugin`. This is that plugin for a runtime that renders +on the main thread and drives the Element PAPI itself. + +## The surface, in full + +```ts +import { pluginMiniLynx, type PluginMiniLynxOptions } from '@amritk/mini-lynx-rsbuild-plugin' + +type PluginMiniLynxOptions = { + /** The module that runs in the background chunk. Defaults to a stub that installs nothing. */ + background?: string + /** The Lynx engine version the template is encoded for. Default '3.2'. */ + targetSdkVersion?: string +} + +pluginMiniLynx(options?: PluginMiniLynxOptions): RsbuildPlugin +``` + +That is the whole package. One function, two options. + +## A complete app + +Four files. There is no `App.tsx` convention and no framework entry to extend — +`renderPage` is the entry. + +```ts +// lynx.config.ts +import { pluginMiniLynx } from '@amritk/mini-lynx-rsbuild-plugin' +import { pluginQRCode } from '@lynx-js/qrcode-rsbuild-plugin' +import { defineConfig } from '@lynx-js/rspeedy' + +export default defineConfig({ + source: { entry: { main: './src/main-thread.tsx' } }, + plugins: [ + pluginQRCode({ fullscreen: true }), + pluginMiniLynx({ background: './src/background.ts' }), + ], +}) +``` + +```tsx +// src/main-thread.tsx — the main-thread chunk, and the whole app +import { renderPage, signal } from '@amritk/mini-lynx' +import './app.css' + +const App = () => { + const count = signal(0) + return ( + count(count() + 1)}> + {() => `tapped ${count()} times`} + + ) +} + +renderPage(App) +``` + +```ts +// src/background.ts — the background chunk; omit it and the default stub is used +import { installNativeBridge } from '@amritk/mini-lynx-native/background' + +installNativeBridge() +``` + +```jsonc +// tsconfig.json — the build reads jsxImportSource from the plugin, but the +// EDITOR reads it from here, so both have to say it +{ + "compilerOptions": { + "jsx": "react-jsx", + "jsxImportSource": "@amritk/mini-lynx", + "types": ["@lynx-js/types", "@lynx-js/rspeedy/client"] + } +} +``` + +Then `rspeedy dev`, scan the QR code with Lynx Explorer, and the app is on the +phone. + +## Gotchas + +**`source.entry` names the MAIN-THREAD entry.** The background module is the +plugin's `background` option, not a second entry. Adding it to `source.entry` +would build a second template rather than a second chunk. + +**Nothing hot-updates.** An edit reloads the whole page through the devtool. +This is not a limitation being worked around: a component in this runtime runs +once, so there is no re-render for a new module version to be applied to. What +makes the reload safe is that `renderPage` claims `removeComponents` and tears +the previous tree down. + +**Live reload needs the devtool.** The reload is `Page.reload` over the CDP +channel, which Lynx Explorer has and a production host app usually does not. + +**The plugin is for the `lynx` environment.** In a `web` environment it does +nothing — a web build of a mini-lynx app is not a solved problem here, and a +plugin that half-configured one would be worse than a plugin that skips it. + +**`targetSdkVersion` is a compatibility floor, not a feature switch.** An +Explorer older than the version a template names refuses the template outright, +with a message about the SDK rather than about your code. + +## Where the pieces are + +| Thing | Owned by | +| --- | --- | +| The `.lynx.bundle` container, and encoding it | `@lynx-js/template-webpack-plugin` (a dependency here) | +| The dev server, the LAN URL, HMR transport | `@lynx-js/rspeedy` | +| The QR code in the terminal | `@lynx-js/qrcode-rsbuild-plugin` | +| Which chunk is which, and the JSX transform | this package | +| Everything that runs on the device | `@amritk/mini-lynx` | diff --git a/packages/mini-lynx-rsbuild-plugin/README.md b/packages/mini-lynx-rsbuild-plugin/README.md new file mode 100644 index 0000000..966668a --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/README.md @@ -0,0 +1,158 @@ +
+ +# @amritk/mini-lynx-rsbuild-plugin + +**`rspeedy dev` → QR code → your app on the phone. The build half of [`@amritk/mini-lynx`](../mini-lynx).** + +![status](https://img.shields.io/badge/status-pre--alpha-ef4444?style=flat-square)  +![version](https://img.shields.io/npm/v/@amritk/mini-lynx-rsbuild-plugin?style=flat-square&logo=npm&logoColor=white&label=version&color=6366f1)  +![license](https://img.shields.io/badge/license-MIT-22c55e?style=flat-square)  +![vibe coded](https://img.shields.io/badge/vibe-coded-a855f7?style=flat-square) + +
+ +--- + +## What it is + +One [rsbuild](https://rsbuild.rs) plugin that teaches +[rspeedy](https://lynxjs.org/rspeedy) — Lynx's build tool — how to build a +`@amritk/mini-lynx` app. + +A Lynx template is not a bundle with an entry point. It is a container with two +code slots — a **main-thread** chunk the engine executes to build the first +screen, and a **background** chunk it loads as `/app-service.js` — plus the CSS, +which the encoder compiles rather than shipping as text. rspeedy builds the +container. Which code goes in which slot is the framework's to say, and every +framework says it in a plugin of its own: ReactLynx's is +`@lynx-js/react-rsbuild-plugin`, and there is no framework-agnostic one +underneath it to reuse. + +This is that plugin, for a runtime that renders on the main thread and drives +the Element PAPI itself. + +## Install + +```bash +npm install -D @amritk/mini-lynx-rsbuild-plugin @lynx-js/rspeedy @lynx-js/qrcode-rsbuild-plugin +# or: pnpm add -D / yarn add -D / bun add -d +``` + +## A complete app + +```ts +// lynx.config.ts +import { pluginMiniLynx } from '@amritk/mini-lynx-rsbuild-plugin' +import { pluginQRCode } from '@lynx-js/qrcode-rsbuild-plugin' +import { defineConfig } from '@lynx-js/rspeedy' + +export default defineConfig({ + source: { entry: { main: './src/main-thread.tsx' } }, + plugins: [ + pluginQRCode({ fullscreen: true }), + pluginMiniLynx({ background: './src/background.ts' }), + ], +}) +``` + +```tsx +// src/main-thread.tsx — the main-thread chunk, and the whole app +import { renderPage, signal } from '@amritk/mini-lynx' +import './app.css' + +const App = () => { + const count = signal(0) + return ( + count(count() + 1)}> + {() => `tapped ${count()} times`} + + ) +} + +renderPage(App) +``` + +```ts +// src/background.ts — the background chunk. Leave the option off and you get a +// stub; this is where `NativeModules` lives, so it is where the bridge installs. +import { installNativeBridge } from '@amritk/mini-lynx-native/background' + +installNativeBridge() +``` + +Then: + +```bash +rspeedy dev # prints a QR code; scan it with Lynx Explorer +rspeedy build # dist/main.lynx.bundle +``` + +A runnable version of exactly this is +[`apps/starter-mini-lynx`](../../apps/starter-mini-lynx), and the loop it +belongs to — Explorer, the QR code, what to do when the phone shows nothing — is +[`docs/mini-lynx-explorer.md`](../../docs/mini-lynx-explorer.md). + +## Options + +| Option | Default | What it is | +| --- | --- | --- | +| `background` | a stub | The module that runs in the background chunk | +| `targetSdkVersion` | `'3.2'` | The Lynx engine version the template is encoded for | + +## What the plugin does, exactly + +Per entry in `source.entry`: + +1. **Splits one entry into two.** `main` becomes `main__main-thread` (your app) + and `main` (the background module), emitted into `.rspeedy/main/`. The + background entry keeps the original name because that is what rspeedy derives + the template filename, the dev server's URLs and the QR code from. +2. **Adds `LynxTemplatePlugin` and `LynxEncodePlugin`**, which collect those two + chunks plus the CSS into one template and encode it. +3. **Flags the main-thread chunk.** The encoder splits an entry's assets by one + `lynx:main-thread` boolean on the asset — set for ReactLynx by its own + webpack plugin, and by a ~20 line rspack plugin here. Without it, every chunk + looks like background code, the template encodes without complaint, and the + app has no first screen. +4. **Wraps the background chunk** for the engine's module loader, and only that + one. +5. **Points the JSX transform at `@amritk/mini-lynx`**, so a consumer does not + configure SWC by hand to get a runtime that is not React. + +## Reload rather than hot update + +In `dev` the background chunk gets the dev-server client and +`@rspack/core/hot/dev-server` on the front. Nothing accepts a hot update and +nothing should: a component in this runtime runs once, and the tree it built is +mutated by signals forever, so there is no re-render for a new module version to +apply to. An update with no acceptor bubbles to the entry, fails, and the page +reloads through the devtool — which is correct here in a way it is not for a +VDOM framework, because `renderPage` claims `removeComponents` and tears the +previous tree down on the way past. + +The reload is `Page.reload` over the devtool's CDP channel, so it needs an +Explorer (or a host app) with the devtool enabled. + +## Known gaps + +**No web environment.** In an environment named `web` this plugin does nothing. +A web build of a mini-lynx app is not a solved problem, and a plugin that +half-configured one would be worse than one that skips it. + +**Lazy bundles are not wired.** `LynxTemplatePlugin` supports them and this +plugin does not configure them, so a dynamic `import()` from the main-thread +chunk is not something to rely on yet. + +**No layer-based module resolution.** ReactLynx compiles the *same* source +twice, once per thread, and uses webpack layers to swap module resolution +between them. Here the two chunks are two files you wrote, which is simpler and +means `background-only`-style guards have nothing to hook into: if you import a +main-thread module from the background chunk, you get it. + +> **Pre-alpha.** Every JS-side Lynx package is still 0.x and the template +> plugin's hooks are `@alpha` upstream, so a minor bump there can move this +> package's ground. + +## License + +[MIT](../../LICENSE) diff --git a/packages/mini-lynx-rsbuild-plugin/fixture/README.md b/packages/mini-lynx-rsbuild-plugin/fixture/README.md new file mode 100644 index 0000000..09bed97 --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/fixture/README.md @@ -0,0 +1,8 @@ +# fixture + +The app `src/build.test.ts` builds. It is a directory rather than a string in +the test because rspack resolves a real module graph from a real path — the JSX +transform, the CSS pipeline and `@amritk/mini-lynx-native/background` all have +to be found the way an app's would be. + +Not published: `package.json`'s `files` ships `dist` and `src`. diff --git a/packages/mini-lynx-rsbuild-plugin/fixture/src/app.css b/packages/mini-lynx-rsbuild-plugin/fixture/src/app.css new file mode 100644 index 0000000..3833485 --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/fixture/src/app.css @@ -0,0 +1,9 @@ +.card { + padding: 24px; + background-color: #111827; +} + +.title { + color: #a5b4fc; + font-size: 28px; +} diff --git a/packages/mini-lynx-rsbuild-plugin/fixture/src/background.ts b/packages/mini-lynx-rsbuild-plugin/fixture/src/background.ts new file mode 100644 index 0000000..e5aead7 --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/fixture/src/background.ts @@ -0,0 +1,3 @@ +import { installNativeBridge } from '@amritk/mini-lynx-native/background' + +installNativeBridge() diff --git a/packages/mini-lynx-rsbuild-plugin/fixture/src/main-thread.tsx b/packages/mini-lynx-rsbuild-plugin/fixture/src/main-thread.tsx new file mode 100644 index 0000000..319bf75 --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/fixture/src/main-thread.tsx @@ -0,0 +1,14 @@ +import { renderPage, signal } from '@amritk/mini-lynx' +import './app.css' + +const Counter = () => { + const count = signal(0) + return ( + count(count() + 1)}> + mini-lynx + {() => `tapped ${count()} times`} + + ) +} + +renderPage(Counter) diff --git a/packages/mini-lynx-rsbuild-plugin/package.json b/packages/mini-lynx-rsbuild-plugin/package.json new file mode 100644 index 0000000..ae95e0f --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/package.json @@ -0,0 +1,75 @@ +{ + "name": "@amritk/mini-lynx-rsbuild-plugin", + "version": "0.1.0", + "description": "The rspeedy build for a @amritk/mini-lynx app: two chunks, one .lynx.bundle template, and a QR code Lynx Explorer scans.", + "type": "module", + "license": "MIT", + "author": "amritk", + "sideEffects": false, + "keywords": [ + "lynx", + "rspeedy", + "rsbuild", + "rspack", + "lynx-explorer", + "typescript", + "mjst" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/amritk/mini.git", + "directory": "packages/mini-lynx-rsbuild-plugin" + }, + "homepage": "https://github.com/amritk/mini/tree/main/packages/mini-lynx-rsbuild-plugin#readme", + "bugs": { + "url": "https://github.com/amritk/mini/issues" + }, + "files": [ + "dist", + "src/**/*.ts", + "!src/**/*.test.ts", + "AI.md" + ], + "publishConfig": { + "access": "public" + }, + "scripts": { + "build": "tsgo -p tsconfig.build.json && tsc-alias -p tsconfig.build.json -f && node ../../scripts/strip-comments.mjs", + "prepublishOnly": "node ../../scripts/check-publishable.mjs", + "types:check": "tsgo -p . --noEmit", + "test": "NODE_ENV=production vitest run --root ../.. packages/mini-lynx-rsbuild-plugin/" + }, + "exports": { + "./package.json": "./package.json", + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "default": "./dist/index.js" + } + }, + "dependencies": { + "@lynx-js/runtime-wrapper-webpack-plugin": "^0.2.3", + "@lynx-js/template-webpack-plugin": "^0.15.1" + }, + "peerDependencies": { + "@amritk/mini-lynx": ">=0.4.0", + "@lynx-js/rspeedy": ">=0.16.0", + "@rsbuild/core": "^2.0.0" + }, + "peerDependenciesMeta": { + "@amritk/mini-lynx": { + "optional": true + }, + "@rsbuild/core": { + "optional": true + } + }, + "devDependencies": { + "@amritk/mini-lynx": "workspace:*", + "@amritk/mini-lynx-native": "workspace:*", + "@lynx-js/rspeedy": "^0.16.4", + "@rsbuild/core": "^2.1.10", + "@rspack/core": "^2.1.10", + "typescript": "^5" + } +} diff --git a/packages/mini-lynx-rsbuild-plugin/src/background-stub.ts b/packages/mini-lynx-rsbuild-plugin/src/background-stub.ts new file mode 100644 index 0000000..44bd5af --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/src/background-stub.ts @@ -0,0 +1,10 @@ +/** + * The background chunk of an app that has nothing to run in the background. + * + * A Lynx template carries two code slots and the engine loads both, so the + * chunk exists whether or not the app put anything in it. An app that reaches + * for `NativeModules` — through `@amritk/mini-lynx-native/background`, say — + * passes its own module as the plugin's `background` option and this file is + * never compiled into anything. + */ +export {} diff --git a/packages/mini-lynx-rsbuild-plugin/src/build.test.ts b/packages/mini-lynx-rsbuild-plugin/src/build.test.ts new file mode 100644 index 0000000..942d7a7 --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/src/build.test.ts @@ -0,0 +1,282 @@ +import { readFile, rm } from 'node:fs/promises' +import { dirname, resolve } from 'node:path' +import { fileURLToPath } from 'node:url' +import { createContext, runInContext } from 'node:vm' +import { createFakeEngine, serializeTree } from '@amritk/mini-lynx/testing' +import { createRspeedy } from '@lynx-js/rspeedy' +import type { RsbuildPlugin } from '@rsbuild/core' +import { afterAll, beforeAll, describe, expect, it } from 'vitest' + +import { pluginMiniLynx } from './plugin' + +/** + * The build, end to end, against the artifact a device would be handed. + * + * Everything else about this package is a matter of shaping a config object, + * and a test that asserted on the shape would pass just as happily against a + * config the encoder rejects. What the encoder actually needs — which chunk + * carries the first screen, which one the module loader wraps, whether the CSS + * survived — is only visible in the template it produces, so that is what this + * reads: one real rspeedy build of a real app, then its output. + * + * The main-thread half goes further and is the point of the file. The chunk is + * pulled out of the encoder's input and run against `createFakeEngine`, which + * is a complete Element PAPI, so the assertions below are about what the built + * bundle renders rather than about what it contains. A JSX transform pointed at + * React, a runtime wrapper applied to the wrong chunk, a `renderPage` that + * never reached the global — each is a passing string search and a blank screen + * on the phone, and each fails here. + * + * What it cannot answer: whether the engine agrees. Layout, the devtool + * connection, the reload the dev client asks the devtool for, and whether + * Explorer accepts this `targetSdkVersion` are all device questions. See + * `docs/mini-lynx-explorer.md` for what was checked on hardware and what was + * not. + */ + +const HERE = dirname(fileURLToPath(import.meta.url)) +const ROOT = resolve(HERE, '../../..') +const FIXTURE = resolve(HERE, '../fixture') + +/** + * What the encoder was handed, read at the moment it was handed it. + * + * A snapshot rather than a reference to the hook's own object: the encoder + * rewrites that object in place on its way to the binary — `lepusCode.root` + * goes from an asset to the string inside it — so anything held across the + * build describes the encoder's output and not its input. + */ +type EncodeSnapshot = { + mainThread: string + manifest: Record + cssChunkCount: number +} + +/** + * Reads the encoder's input on its way past. + * + * The template plugin's `beforeEncode` hook is the last place the two chunks + * exist as separate, readable assets: `LynxEncodePlugin` turns them into one + * binary and deletes them. Tapping it is how a test gets the main-thread source + * to run, and it is the same hook ReactLynx uses to append its worklet runtime, + * so nothing here is reaching around the plugin's back. + */ +const captureEncodeData = (into: { current?: EncodeSnapshot }): RsbuildPlugin => ({ + name: 'capture-encode-data', + setup(api) { + api.modifyBundlerChain((chain) => { + chain.plugin('capture-encode-data').use({ + apply: (compiler: { + hooks: { thisCompilation: { tap: (name: string, fn: (compilation: unknown) => void) => void } } + }) => { + compiler.hooks.thisCompilation.tap('capture-encode-data', async (compilation) => { + const { LynxTemplatePlugin } = await import('@lynx-js/template-webpack-plugin') + LynxTemplatePlugin.getLynxTemplatePluginHooks(compilation as never).beforeEncode.tap( + 'capture-encode-data', + (args) => { + const { css, lepusCode, manifest } = args.encodeData + into.current = { + mainThread: String(lepusCode.root?.source.source() ?? ''), + manifest: { ...manifest }, + cssChunkCount: css.chunks.length, + } + return args + }, + ) + }) + }, + }) + }) + }, +}) + +/** + * Runs the built main-thread chunk the way the engine does: as a script, in a + * context whose globals are the Element PAPI, with nothing imported. + * + * That is the whole contract between a Lynx bundle and the main thread — the + * chunk defines `renderPage` on the global object and the engine calls it once + * — so a context with the fake engine's functions on it is the same shape a + * device presents, minus a screen. + */ +const renderInFakeEngine = (mainThreadSource: string) => { + const engine = createFakeEngine() + const lifecycle: { type: string }[] = [] + const context = createContext({ + ...(engine.api as unknown as Record), + console, + __OnLifecycleEvent: (event: { type: string }) => void lifecycle.push(event), + }) + // The chunk is an IIFE that assigns the globals; the engine then calls the + // one it cares about. + runInContext(mainThreadSource, context) + runInContext('renderPage()', context) + + // An event reaches a handler through `runWorklet`, which the bundle installs + // on ITS global — and the fake engine, running out here, looks for the same + // name on this one. On a device there is a single global object and the two + // are the same; a `vm` context is the only reason they are not, so the seam + // is closed rather than worked around. + const outer = globalThis as { runWorklet?: unknown } + outer.runWorklet = (context as { runWorklet?: unknown }).runWorklet + + return { engine, lifecycle } +} + +/** + * One real rspeedy build of `fixture/`, into a directory of its own so two + * builds in this file cannot read each other's output. + * + * The runtime resolves to its **source**, like every other suite here, so a + * test is never downstream of `bun run build`. rspack resolves its own graph and + * knows nothing about vitest's aliases, so the same mapping is spelled again for + * it. + */ +const buildFixture = async ( + distRoot: string, + options: Parameters[0], +): Promise<{ template: Buffer; captured: { current?: EncodeSnapshot } }> => { + const captured: { current?: EncodeSnapshot } = {} + const rspeedy = await createRspeedy({ + cwd: FIXTURE, + rspeedyConfig: { + plugins: [pluginMiniLynx(options), captureEncodeData(captured)], + output: { distPath: { root: distRoot } }, + source: { + entry: { main: './src/main-thread.tsx' }, + alias: { + '@amritk/mini-lynx/jsx-runtime': resolve(ROOT, 'packages/mini-lynx/src/jsx-runtime.ts'), + '@amritk/mini-lynx/jsx-dev-runtime': resolve(ROOT, 'packages/mini-lynx/src/jsx-dev-runtime.ts'), + '@amritk/mini-lynx': resolve(ROOT, 'packages/mini-lynx/src/index.ts'), + '@amritk/mini-lynx-native/background': resolve(ROOT, 'packages/mini-lynx-native/src/background/index.ts'), + }, + }, + }, + }) + + await rspeedy.build() + return { template: await readFile(resolve(FIXTURE, distRoot, 'main.lynx.bundle')), captured } +} + +describe('the rspeedy build', () => { + let captured: { current?: EncodeSnapshot } = {} + let template: Buffer + + beforeAll(async () => { + const built = await buildFixture('dist', { background: './src/background.ts' }) + template = built.template + captured = built.captured + }, 120_000) + + afterAll(async () => { + await rm(resolve(FIXTURE, 'dist'), { recursive: true, force: true }) + }) + + it('emits one encoded template per entry', () => { + // Not a size assertion dressed up: an encoder that produced an empty + // container would still write a file, and the number is what says the two + // chunks and the CSS are inside it. + expect(template.byteLength).toBeGreaterThan(1_000) + }) + + it('fills both of the template’s code slots', () => { + // The main-thread slot. Empty is the failure this package exists to avoid: + // without the `lynx:main-thread` flag every chunk looks like background + // code, the template encodes fine, and the app has no first screen — and + // the encoder reports nothing, because a template without one is legal. + expect(captured.current?.mainThread).toContain('renderPage') + + // The background slot. The encoder is handed it under its chunk name and + // publishes it as `/app-service.js`, which is the name the engine's module + // loader requires and therefore the one worth asserting on the artifact. + expect(Object.keys(captured.current?.manifest ?? {})).toEqual(['.rspeedy/main/background.js']) + expect(template.includes('/app-service.js')).toBe(true) + }) + + it('compiles the app’s CSS into the template rather than shipping it as text', () => { + expect(captured.current?.cssChunkCount).toBeGreaterThan(0) + }) + + it('wraps the background chunk for the engine’s module loader, and not the main-thread one', () => { + const mainThread = captured.current?.mainThread ?? '' + const background = captured.current?.manifest['.rspeedy/main/background.js'] ?? '' + + // `tt.define` is the engine's module registration, and the wrapper around + // the background chunk is what emits it. The main-thread chunk is executed + // by the engine directly: the same wrapper around it would register a + // module nobody requires, and the first screen would never be built. + expect(background).toContain('.define(') + // And the app's own background module is what is inside it: the bridge's + // message prefix, which nothing else in the graph emits. + expect(background).toContain('mini-lynx-native:') + expect(mainThread).not.toContain('.define(') + }) + + it('renders the app when the engine calls renderPage', () => { + const mainThread = captured.current?.mainThread ?? '' + const { engine, lifecycle } = renderInFakeEngine(mainThread) + + expect(serializeTree(engine.page)).toMatchInlineSnapshot(` + " + + + + + " + `) + + // The platform's cue to stop waiting. A bundle that renders and never sends + // it is an app stuck on its splash screen, which is not a failure any + // string search over the template would find. + expect(lifecycle).toEqual([{ type: 'firstScreen' }]) + }) + + it('keeps the built tree reactive, so a tap is not a re-render', () => { + const mainThread = captured.current?.mainThread ?? '' + const { engine } = renderInFakeEngine(mainThread) + + const view = engine.find('view') + expect(view).toBeDefined() + const before = engine.find('text') + engine.dispatch(view as never, 'tap') + + expect(serializeTree(engine.page)).toContain('tapped 1 times') + // The same element, mutated. A runtime that rebuilt the subtree would pass + // the assertion above and fail this one, which is the difference this + // package is here to preserve through a bundler. + expect(engine.find('text')).toBe(before) + }) +}) + +describe('an app with no background module', () => { + let captured: { current?: EncodeSnapshot } = {} + let template: Buffer + + beforeAll(async () => { + // No `background` option — the path a consumer takes before they have + // anything native to reach for, and the one that has to keep producing a + // valid template anyway. + const built = await buildFixture('dist-stub', {}) + template = built.template + captured = built.captured + }, 120_000) + + afterAll(async () => { + await rm(resolve(FIXTURE, 'dist-stub'), { recursive: true, force: true }) + }) + + it('still fills the background slot, with the stub', () => { + expect(template.includes('/app-service.js')).toBe(true) + const background = captured.current?.manifest['.rspeedy/main/background.js'] ?? '' + expect(background).toContain('.define(') + // The app's own background module is what is NOT in it. + expect(background).not.toContain('mini-lynx-native:') + }) + + it('renders the same first screen', () => { + const { engine, lifecycle } = renderInFakeEngine(captured.current?.mainThread ?? '') + + expect(serializeTree(engine.page)).toContain('tapped 0 times') + expect(lifecycle).toEqual([{ type: 'firstScreen' }]) + }) +}) diff --git a/packages/mini-lynx-rsbuild-plugin/src/index.ts b/packages/mini-lynx-rsbuild-plugin/src/index.ts new file mode 100644 index 0000000..e723b23 --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/src/index.ts @@ -0,0 +1,9 @@ +/** + * @packageDocumentation + * + * The rspeedy build for a `@amritk/mini-lynx` app: two chunks, one template, + * and the dev server Lynx Explorer scans. + */ + +export type { PluginMiniLynxOptions } from './plugin' +export { pluginMiniLynx } from './plugin' diff --git a/packages/mini-lynx-rsbuild-plugin/src/main-thread-info.ts b/packages/mini-lynx-rsbuild-plugin/src/main-thread-info.ts new file mode 100644 index 0000000..e954cec --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/src/main-thread-info.ts @@ -0,0 +1,43 @@ +import type { Compiler } from '@rspack/core' + +/** + * Flags the main-thread chunks so the encoder puts them in the template's + * main-thread slot. + * + * The encoder does not infer the split from entry names or filenames: it reads + * one `lynx:main-thread` boolean off each asset's info and treats everything + * without it as background code. ReactLynx sets it from its own webpack plugin, + * which is the only reason that plugin is in the chain for a build that has no + * React in it — so this is that one flag, and nothing else. + * + * A missing chunk is skipped rather than thrown on. The name is computed from + * an entry this plugin's own configuration created, so a miss means the entry + * produced no asset at all — a compilation that already failed, and one whose + * real error is worth more than an invariant firing on top of it. + */ +export class MainThreadInfoPlugin { + readonly #chunks: readonly string[] + + constructor(chunks: readonly string[]) { + this.#chunks = chunks + } + + apply(compiler: Compiler): void { + const name = 'MainThreadInfoPlugin' + compiler.hooks.thisCompilation.tap(name, (compilation) => { + compilation.hooks.processAssets.tap( + // ADDITIONAL is the first stage assets exist at, which puts the flag on + // before the template plugin reads it and before any later stage can + // rewrite the asset without carrying its info forward. + { name, stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL }, + () => { + for (const chunk of this.#chunks) { + const asset = compilation.getAsset(chunk) + if (!asset) continue + compilation.updateAsset(asset.name, asset.source, { ...asset.info, 'lynx:main-thread': true }) + } + }, + ) + }) + } +} diff --git a/packages/mini-lynx-rsbuild-plugin/src/plugin.ts b/packages/mini-lynx-rsbuild-plugin/src/plugin.ts new file mode 100644 index 0000000..bf805bc --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/src/plugin.ts @@ -0,0 +1,237 @@ +import { existsSync } from 'node:fs' +import { fileURLToPath } from 'node:url' +import type { RsbuildPlugin } from '@rsbuild/core' + +import { MainThreadInfoPlugin } from './main-thread-info' + +/** + * Where the pre-encode chunks live. rspeedy's own convention, and the reason it + * is spelled out rather than chosen: `@lynx-js/rspeedy` cleans `.rspeedy/` and + * its `distPath.intermediate` default names the same directory, so a build that + * put them anywhere else would leave them behind in `dist/`. + */ +const INTERMEDIATE = '.rspeedy' + +/** + * Everything that is not the main-thread chunk. The runtime wrapper wraps the + * background chunk in the function signature the engine's `app-service.js` + * loader calls; applying it to the main-thread chunk too would wrap code the + * engine executes directly, and nothing would run. + */ +const NOT_MAIN_THREAD = /^(?!.*main-thread(?:\.[A-Fa-f0-9]*)?\.js$).*\.js$/ + +/** The environments a Lynx template is emitted for. rspeedy names its default `lynx`. */ +const isLynxEnvironment = (name: string): boolean => name === 'lynx' || name.startsWith('lynx-') + +export type PluginMiniLynxOptions = { + /** + * The module that runs in the **background** chunk — `NativeModules`, + * `GlobalEventEmitter`, and the background half of + * `@amritk/mini-lynx-native`. + * + * Defaults to a stub that installs nothing, because a Lynx template carries a + * background chunk whether or not the app has anything to put in it. + */ + background?: string + /** + * The Lynx engine version the template is encoded for. Must be one the app + * you are loading it into can read: an Explorer older than the template + * refuses it outright. + * + * @defaultValue `'3.2'` + */ + targetSdkVersion?: string +} + +/** + * Builds a `@amritk/mini-lynx` app into a `.lynx.bundle` template. + * + * ## What it has to do, and why any of it is needed + * + * A Lynx template is not a bundle with an entry point. It is a container with + * two code slots — a main-thread chunk the engine executes to build the first + * screen, and a background chunk it loads as `/app-service.js` — plus the CSS, + * compiled by the encoder rather than shipped as text. `@lynx-js/rspeedy` + * builds the container; which code goes in which slot is the framework's to + * say, and every framework says it in its own plugin. ReactLynx's is + * `@lynx-js/react-rsbuild-plugin`, and it is where the two entries, the + * template plugin and the encoder are wired together. There is no + * framework-agnostic plugin underneath it to reuse — `@lynx-js/rsbuild-plugin` + * is the dev server and the minifier split, not the template — so this is that + * wiring, for a runtime that renders on the main thread and drives the Element + * PAPI itself. + * + * Concretely, per entry: + * + * 1. **Two entries from one.** `source.entry.main` becomes `main__main-thread` + * (your app) and `main` (the background module), emitted to + * `.rspeedy/main/`. rspeedy's `source.entry` stays the app's, so the dev + * server's URLs and the QR code still name `main.lynx.bundle`. + * 2. **`LynxTemplatePlugin`**, which collects those two chunks plus the CSS + * into one template, and **`LynxEncodePlugin`**, which encodes it. + * 3. **The main-thread flag.** The encoder splits an entry's assets into the + * two slots by one `lynx:main-thread` flag on the asset — set for ReactLynx + * by its own webpack plugin, and by {@link MainThreadInfoPlugin} here. + * Without it every chunk looks like background code and the template has no + * first screen at all. + * 4. **The runtime wrapper**, on the background chunk only, which is what makes + * it loadable by the engine's module system. + * 5. **JSX**, pointed at `@amritk/mini-lynx` — the same line the app's + * `tsconfig.json` carries, applied to the build, so a consumer does not have + * to configure SWC by hand to get a runtime that is not React. + * + * ## Reload rather than hot update + * + * In `dev` the background chunk gets two more modules on the front: + * `@lynx-js/webpack-dev-transport/client`, which opens the socket back to the + * dev server, and `@rspack/core/hot/dev-server`, which listens for what comes + * over it. + * + * Nothing here accepts a hot update, and nothing should. A hot update is a diff + * applied to a live module graph, and this runtime has no such graph: a + * component runs once and the tree it built is mutated by signals forever, so + * there is no second render to re-run against a new module. An update with no + * acceptor bubbles to the entry, fails to apply, and the dev-server module + * reloads the page through the devtool instead — which is the correct outcome + * and the one this runtime can support, because `renderPage` claims + * `removeComponents` and tears the previous tree down on the way. Save a file, + * the app on the device restarts. + * + * The reload itself is `Page.reload` over the devtool's CDP channel, so it + * needs an Explorer (or host app) with the devtool enabled — the same thing + * scanning a QR code needs. + * + * @example + * ```ts + * // lynx.config.ts + * import { pluginQRCode } from '@lynx-js/qrcode-rsbuild-plugin' + * import { defineConfig } from '@lynx-js/rspeedy' + * import { pluginMiniLynx } from '@amritk/mini-lynx-rsbuild-plugin' + * + * export default defineConfig({ + * source: { entry: { main: './src/main-thread.tsx' } }, + * plugins: [ + * pluginQRCode({ fullscreen: true }), + * pluginMiniLynx({ background: './src/background.ts' }), + * ], + * }) + * ``` + */ +export const pluginMiniLynx = (options: PluginMiniLynxOptions = {}): RsbuildPlugin => ({ + name: 'mini-lynx', + + setup(api) { + const { background = backgroundStub(), targetSdkVersion = '3.2' } = options + + api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => + mergeRsbuildConfig(config, { + tools: { + swc: { + jsc: { transform: { react: { runtime: 'automatic', importSource: '@amritk/mini-lynx' } } }, + }, + }, + }), + ) + + api.modifyBundlerChain(async (chain, { environment, isDev }) => { + if (!isLynxEnvironment(environment.name)) return + + // Imported here rather than at the top of the file so that loading this + // module costs nothing: `LynxEncodePlugin` opens a worker pool the moment + // it is imported, and a plugin that is only ever read (a consumer's + // smoke test, an editor) should not start one. + const [{ LynxEncodePlugin, LynxTemplatePlugin }, { RuntimeWrapperWebpackPlugin }] = await Promise.all([ + import('@lynx-js/template-webpack-plugin'), + import('@lynx-js/runtime-wrapper-webpack-plugin'), + ]) + + const entries = chain.entryPoints.entries() ?? {} + const mainThreadChunks: string[] = [] + chain.entryPoints.clear() + + for (const [entryName, entryPoint] of Object.entries(entries)) { + const imports = toImports(entryPoint.values()) + const mainThreadEntry = `${entryName}__main-thread` + const mainThreadName = `${INTERMEDIATE}/${entryName}/main-thread.js` + const backgroundName = `${INTERMEDIATE}/${entryName}/background.js` + mainThreadChunks.push(mainThreadName) + + chain + .entry(mainThreadEntry) + .add({ import: imports, filename: mainThreadName }) + .end() + // The background entry keeps the ORIGINAL entry name: it is the name + // rspeedy's dev server, the QR code and the template filename are all + // derived from, so renaming it would move the URL the device fetches. + .entry(entryName) + .add({ import: [background], filename: backgroundName }) + .when(isDev, (entry) => { + // Both specifiers are aliased by rspeedy — the client to its own, + // with the dev server's host, port and token already in the query, + // and `hot/dev-server` to the Lynx build of it that reloads through + // the devtool rather than through a `window` that is not there. + // Which is why they are added by name and given no options here. + if (environment.config.dev?.hmr !== false) { + entry.prepend({ import: '@rspack/core/hot/dev-server' }) + } + entry.prepend({ import: '@lynx-js/webpack-dev-transport/client' }) + }) + .end() + .plugin(`mini-lynx:template-${entryName}`) + .use(LynxTemplatePlugin, [ + { + ...LynxTemplatePlugin.defaultOptions, + // The engine's no-diff main-thread mode: the chunk builds the + // element tree itself and the engine does not reconcile anything + // behind it. It is what this runtime does, and ReactLynx's + // setting for the same reason. + dsl: 'react_nodiff', + chunks: [mainThreadEntry, entryName], + filename: `${entryName}.lynx.bundle`, + intermediate: `${INTERMEDIATE}/${entryName}`, + targetSdkVersion, + }, + ]) + .end() + } + + chain + .plugin('mini-lynx:main-thread-info') + .use(MainThreadInfoPlugin, [mainThreadChunks]) + .end() + .plugin('mini-lynx:runtime-wrapper') + .use(RuntimeWrapperWebpackPlugin, [{ targetSdkVersion, test: NOT_MAIN_THREAD }]) + .end() + .plugin('mini-lynx:encode') + .use(LynxEncodePlugin, [{ inlineScripts: true }]) + .end() + }) + }, +}) + +/** + * An rsbuild entry is a list of strings, of descriptor objects, or of both, and + * both chunks are built from the same list — so it is flattened once, here, + * rather than at each of the two places that consume it. + */ +const toImports = (values: readonly unknown[]): string[] => + values.flatMap((value) => { + if (typeof value === 'string') return [value] + if (Array.isArray(value)) return toImports(value) + const { import: entry } = value as { import: string | string[] } + return Array.isArray(entry) ? entry : [entry] + }) + +/** + * The default background entry: the chunk a template carries whether or not the + * app has anything to run there. + * + * Resolved as a path rather than as a bare specifier because the app's rspack + * resolves it, and an app that installed this plugin as a build-time dependency + * of a workspace may not have it in its own `node_modules`. The `.ts` fallback + * is for this repository's own tests, which run the plugin from `src/`. + */ +const backgroundStub = (): string => { + const built = fileURLToPath(new URL('./background-stub.js', import.meta.url)) + return existsSync(built) ? built : fileURLToPath(new URL('./background-stub.ts', import.meta.url)) +} diff --git a/packages/mini-lynx-rsbuild-plugin/tsconfig.build.json b/packages/mini-lynx-rsbuild-plugin/tsconfig.build.json new file mode 100644 index 0000000..1623d1c --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/tsconfig.build.json @@ -0,0 +1,9 @@ +{ + "extends": ["./tsconfig.json", "../../tsconfig.build.json"], + "compilerOptions": { + "rootDir": "src", + "outDir": "dist" + }, + "include": ["src/**/*.ts"], + "exclude": ["dist", "node_modules", "**/*.test.ts"] +} diff --git a/packages/mini-lynx-rsbuild-plugin/tsconfig.json b/packages/mini-lynx-rsbuild-plugin/tsconfig.json new file mode 100644 index 0000000..f873862 --- /dev/null +++ b/packages/mini-lynx-rsbuild-plugin/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + // A build-time plugin: it runs under Node, in the app's toolchain, and + // never in the engine. Unlike every other package here it is allowed the + // Node globals, and needs them — the background stub is resolved from disk. + "types": ["node"] + }, + "include": ["src/**/*.ts"] +} diff --git a/packages/mini-lynx/AGENTS.md b/packages/mini-lynx/AGENTS.md index 638a237..316eca0 100644 --- a/packages/mini-lynx/AGENTS.md +++ b/packages/mini-lynx/AGENTS.md @@ -346,6 +346,22 @@ records what it was asked to do and does not do it; an assertion that an element was given `flex-direction: row` is sound, and one about how wide it ended up is not something any test outside a device should be making. +## The relationship with the build + +`@amritk/mini-lynx-rsbuild-plugin` is what turns an app on this runtime into a +`.lynx.bundle`, and two things here are its contract rather than this package's +alone: + +- **`renderPage` installs a global and `removeComponents` tears the tree down.** + The dev loop's reload depends on the second: an edit reloads the whole page, + and the previous tree's effects have to stop. Changing either is a change to + how a dev build behaves on a device. +- **The main-thread chunk is executed, not imported.** Anything the entry needs + at module scope has to work in a context with no module system and no `window` + — which is also why `packages/mini-lynx-rsbuild-plugin/src/build.test.ts` runs + the built chunk in a bare `node:vm` context and will fail if that stops being + true. + ## The relationship with `@amritk/mini` Siblings, not layers. `mini` renders to the DOM, `mini-lynx` renders to Lynx, diff --git a/packages/mini-lynx/AI.md b/packages/mini-lynx/AI.md index 8458a69..1d2953e 100644 --- a/packages/mini-lynx/AI.md +++ b/packages/mini-lynx/AI.md @@ -100,6 +100,28 @@ JSX config in the consuming package (this is **not** the React runtime): { "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "@amritk/mini-lynx" } } ``` +### The build that produces the two chunks + +The bundler that "marks the main-thread chunk" is +[rspeedy](https://lynxjs.org/rspeedy), Lynx's own, and the marking is +`@amritk/mini-lynx-rsbuild-plugin`: + +```ts +// lynx.config.ts +import { pluginMiniLynx } from '@amritk/mini-lynx-rsbuild-plugin' +import { pluginQRCode } from '@lynx-js/qrcode-rsbuild-plugin' +import { defineConfig } from '@lynx-js/rspeedy' + +export default defineConfig({ + source: { entry: { main: './src/main-thread.tsx' } }, + plugins: [pluginQRCode({ fullscreen: true }), pluginMiniLynx({ background: './src/background.ts' })], +}) +``` + +`source.entry` is the **main-thread** entry; the background module is the +plugin's `background` option, not a second entry. `rspeedy dev` prints a QR code +for Lynx Explorer; `rspeedy build` writes `dist/main.lynx.bundle`. + ## Handlers run on the main thread Driving the Element PAPI is what puts this runtime there, so a `bindtap` handler diff --git a/packages/mini-lynx/README.md b/packages/mini-lynx/README.md index 1618571..27b352a 100644 --- a/packages/mini-lynx/README.md +++ b/packages/mini-lynx/README.md @@ -108,6 +108,40 @@ real footgun of a compilerless JSX, and `@amritk/mini`'s scanner catches it (`catchCalledSignals` for a Vite build, `findCalledSignalBindings` for anything else — Lynx builds with rspack). +## Getting it onto a phone + +```bash +npm install -D @amritk/mini-lynx-rsbuild-plugin @lynx-js/rspeedy @lynx-js/qrcode-rsbuild-plugin +``` + +```ts +// lynx.config.ts +import { pluginMiniLynx } from '@amritk/mini-lynx-rsbuild-plugin' +import { pluginQRCode } from '@lynx-js/qrcode-rsbuild-plugin' +import { defineConfig } from '@lynx-js/rspeedy' + +export default defineConfig({ + source: { entry: { main: './src/main-thread.tsx' } }, + plugins: [pluginQRCode({ fullscreen: true }), pluginMiniLynx({ background: './src/background.ts' })], +}) +``` + +`rspeedy dev` then prints a QR code; scan it with +[Lynx Explorer](https://lynxjs.org/guide/start/quick-start.html) and the app is +on the device, reloading when you save. `rspeedy build` writes +`dist/main.lynx.bundle`. + +The plugin exists because a Lynx template is a container with two code slots +rather than a bundle with an entry point, and which code goes in which slot is +the framework's to say — ReactLynx says it in +`@lynx-js/react-rsbuild-plugin`, and there is no framework-agnostic one to +reuse. [`@amritk/mini-lynx-rsbuild-plugin`](../mini-lynx-rsbuild-plugin) is that +wiring for this runtime; a four-file app using it is +[`apps/starter-mini-lynx`](../../apps/starter-mini-lynx), and the whole loop — +what is verified, what a device still has to answer, and what to check when the +phone shows nothing — is +[`docs/mini-lynx-explorer.md`](../../docs/mini-lynx-explorer.md). + ## Testing off-device The platform boundary is one type and a handful of functions, and diff --git a/scripts/consumer-e2e.test.ts b/scripts/consumer-e2e.test.ts index b899641..66788b2 100644 --- a/scripts/consumer-e2e.test.ts +++ b/scripts/consumer-e2e.test.ts @@ -73,6 +73,7 @@ const PUBLISHED = [ '@amritk/mini-helpers', '@amritk/mini-lynx', '@amritk/mini-lynx-native', + '@amritk/mini-lynx-rsbuild-plugin', ] as const /**