diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..9c6eb23
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,20 @@
+name: CI
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+
+jobs:
+ ci:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 22
+ cache: npm
+ - run: npm ci
+ - run: npm run check --workspaces --if-present
+ - run: npm test --workspaces --if-present
+ - run: npm run build --workspace web
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7077d65
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+node_modules/
+.svelte-kit/
+.wrangler/
+dist/
+build/
+*.log
+.env
+.env.*
+!.env.example
+.DS_Store
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 0000000..2bd5a0a
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+22
diff --git a/AGENTS.md b/AGENTS.md
index 8eb9313..7d0f025 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -10,7 +10,7 @@ Positioning: **professional presence** β "what Read.cv should have been, but y
## Current phase
-**Pre-code.** We are in feasibility/direction. Nothing has been scaffolded; the stack is chosen (ADR 0010: TypeScript + SvelteKit) but scaffolding hasn't started. Do not start writing product code without an explicit request from Jacob.
+**Building v1** (Jacob green-lit the build 2026-08-03). The scaffold exists: npm workspaces with `apps/web` (SvelteKit on Cloudflare Workers, atproto OAuth login working end-to-end) and `packages/lexicons` (convention tests over `lexicons/`). Feature work follows the v1 scope in ADR 0008 β don't broaden it.
## Read this first, in this order
diff --git a/README.md b/README.md
index d63560d..a9142a9 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ Your website, at your domain, built from data you already own:
## Status
-π§ **Pre-code. Feasibility & direction phase.** No product code exists yet; what this repo currently holds is research, decisions, and direction:
+π§ **Building v1.** The scaffold is up: `apps/web` (SvelteKit on Cloudflare Workers, atproto OAuth sign-in) and `packages/lexicons` (tests over the [`lexicons/`](lexicons/) schemas). Direction and decisions live in docs:
| Where | What |
|---|---|
diff --git a/apps/web/.dev.vars.example b/apps/web/.dev.vars.example
new file mode 100644
index 0000000..4b0d62f
--- /dev/null
+++ b/apps/web/.dev.vars.example
@@ -0,0 +1,6 @@
+# Copy to .dev.vars (gitignored) to configure local dev secrets.
+# Leave OAUTH_PRIVATE_KEY_JWK unset to use the loopback OAuth client (recommended for dev).
+# Generate a key with:
+# node -e "crypto.subtle.generateKey({name:'ECDSA',namedCurve:'P-256'},true,['sign']).then(async k=>console.log(JSON.stringify(await crypto.subtle.exportKey('jwk',k.privateKey))))"
+# OAUTH_PRIVATE_KEY_JWK={"kty":"EC","crv":"P-256",...}
+# SESSION_SECRET=some-long-random-string
diff --git a/apps/web/.gitignore b/apps/web/.gitignore
new file mode 100644
index 0000000..b844aba
--- /dev/null
+++ b/apps/web/.gitignore
@@ -0,0 +1,25 @@
+node_modules
+
+# Output
+.output
+.vercel
+.netlify
+.wrangler
+/.svelte-kit
+/build
+
+# OS
+.DS_Store
+Thumbs.db
+
+# Env
+.env
+.env.*
+!.env.example
+!.env.test
+.dev.vars
+!.dev.vars.example
+
+# Vite
+vite.config.js.timestamp-*
+vite.config.ts.timestamp-*
diff --git a/apps/web/.npmrc b/apps/web/.npmrc
new file mode 100644
index 0000000..b6f27f1
--- /dev/null
+++ b/apps/web/.npmrc
@@ -0,0 +1 @@
+engine-strict=true
diff --git a/apps/web/.vscode/extensions.json b/apps/web/.vscode/extensions.json
new file mode 100644
index 0000000..28d1e67
--- /dev/null
+++ b/apps/web/.vscode/extensions.json
@@ -0,0 +1,3 @@
+{
+ "recommendations": ["svelte.svelte-vscode"]
+}
diff --git a/apps/web/README.md b/apps/web/README.md
new file mode 100644
index 0000000..64500fb
--- /dev/null
+++ b/apps/web/README.md
@@ -0,0 +1,32 @@
+# web β the Mooring app
+
+SvelteKit (Svelte 5) app serving the admin backend and, eventually, the SSR public sites. Deploys to Cloudflare Workers (ADR 0011) via `@sveltejs/adapter-cloudflare`.
+
+## Local development
+
+```sh
+npm install # from the repo root (npm workspaces)
+npm run db:migrate # apply D1 migrations to the local database
+npm run dev # vite dev with emulated Workers bindings
+```
+
+**Browse at `http://127.0.0.1:5173`, not `localhost`** β with no OAuth key configured, the app runs as an atproto *loopback* OAuth client, and loopback redirect URIs must use `127.0.0.1`.
+
+To exercise the exact production runtime (workerd) instead of vite dev:
+
+```sh
+npm run build && npx wrangler dev
+```
+
+## Configuration
+
+Secrets go in `.dev.vars` locally (see `.dev.vars.example`) and `wrangler secret put` in production:
+
+- `OAUTH_PRIVATE_KEY_JWK` β ES256 private key JWK (JSON). When set, the app is a confidential OAuth client serving its metadata at `/client-metadata.json` and keys at `/jwks.json`. When absent: loopback dev client.
+- `SESSION_SECRET` β HMAC key for the session cookie. Required in production.
+
+## Layout notes
+
+- `src/lib/server/oauth/` β atproto OAuth: `workers-compat.ts` is the shim layer that lets `@atproto/oauth-client-node` run on Workers (see `docs/research/2026-08-03-oauth-workers-spike.md` for why each shim exists), `stores.ts` the D1-backed state/session stores, `client.ts` the client factory.
+- `migrations/` β D1 SQL migrations (`wrangler d1 migrations apply`).
+- The public-site renderer will be kept separable from this app (ADR 0005) when it lands.
diff --git a/apps/web/migrations/0001_oauth.sql b/apps/web/migrations/0001_oauth.sql
new file mode 100644
index 0000000..7bd8821
--- /dev/null
+++ b/apps/web/migrations/0001_oauth.sql
@@ -0,0 +1,13 @@
+-- OAuth client state (pending authorization flows) and sessions (token sets),
+-- stored as JSON per @atproto/oauth-client-node's NodeSavedState/NodeSavedSession.
+CREATE TABLE IF NOT EXISTS oauth_state (
+ key TEXT PRIMARY KEY,
+ value TEXT NOT NULL,
+ updated_at INTEGER NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS oauth_session (
+ key TEXT PRIMARY KEY,
+ value TEXT NOT NULL,
+ updated_at INTEGER NOT NULL
+);
diff --git a/apps/web/package.json b/apps/web/package.json
new file mode 100644
index 0000000..f822a2e
--- /dev/null
+++ b/apps/web/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "web",
+ "private": true,
+ "version": "0.0.1",
+ "type": "module",
+ "scripts": {
+ "dev": "vite dev",
+ "build": "vite build",
+ "preview": "vite preview",
+ "prepare": "svelte-kit sync || echo ''",
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+ "db:migrate": "wrangler d1 migrations apply mooring --local",
+ "deploy": "npm run build && wrangler deploy"
+ },
+ "dependencies": {
+ "@atproto/jwk-jose": "^0.2.4",
+ "@atproto/oauth-client-node": "^0.5.2"
+ },
+ "devDependencies": {
+ "@cloudflare/workers-types": "^5.20260801.1",
+ "@sveltejs/adapter-cloudflare": "^7.2.9",
+ "@sveltejs/kit": "^2.63.0",
+ "@sveltejs/vite-plugin-svelte": "^7.1.2",
+ "svelte": "^5.56.1",
+ "svelte-check": "^4.6.0",
+ "typescript": "^6.0.3",
+ "vite": "^8.0.16",
+ "wrangler": "^4.118.0"
+ }
+}
diff --git a/apps/web/src/app.d.ts b/apps/web/src/app.d.ts
new file mode 100644
index 0000000..a4e09dc
--- /dev/null
+++ b/apps/web/src/app.d.ts
@@ -0,0 +1,24 @@
+// See https://svelte.dev/docs/kit/types#app.d.ts
+// for information about these interfaces
+import type { D1Database } from '@cloudflare/workers-types';
+import type { NodeOAuthClient } from '@atproto/oauth-client-node';
+
+declare global {
+ namespace App {
+ // interface Error {}
+ interface Locals {
+ oauth: NodeOAuthClient;
+ }
+ // interface PageData {}
+ // interface PageState {}
+ interface Platform {
+ env: {
+ DB: D1Database;
+ OAUTH_PRIVATE_KEY_JWK?: string;
+ SESSION_SECRET?: string;
+ };
+ }
+ }
+}
+
+export {};
diff --git a/apps/web/src/app.html b/apps/web/src/app.html
new file mode 100644
index 0000000..6a2bb58
--- /dev/null
+++ b/apps/web/src/app.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ %sveltekit.head%
+
+
+ %sveltekit.body%
+
+
diff --git a/apps/web/src/hooks.server.ts b/apps/web/src/hooks.server.ts
new file mode 100644
index 0000000..12e7bad
--- /dev/null
+++ b/apps/web/src/hooks.server.ts
@@ -0,0 +1,18 @@
+import type { Handle } from '@sveltejs/kit';
+import type { NodeOAuthClient } from '@atproto/oauth-client-node';
+import { createOAuthClient } from '$lib/server/oauth/client';
+
+// One client per isolate. Keyed by origin so a stale cache can't survive a
+// hostname change within an isolate's lifetime (unlikely, but cheap to guard).
+let cached: { origin: string; client: Promise } | undefined;
+
+export const handle: Handle = async ({ event, resolve }) => {
+ const env = event.platform?.env;
+ if (env) {
+ if (cached?.origin !== event.url.origin) {
+ cached = { origin: event.url.origin, client: createOAuthClient(env, event.url.origin) };
+ }
+ event.locals.oauth = await cached.client;
+ }
+ return resolve(event);
+};
diff --git a/apps/web/src/lib/assets/favicon.svg b/apps/web/src/lib/assets/favicon.svg
new file mode 100644
index 0000000..cc5dc66
--- /dev/null
+++ b/apps/web/src/lib/assets/favicon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/web/src/lib/index.ts b/apps/web/src/lib/index.ts
new file mode 100644
index 0000000..856f2b6
--- /dev/null
+++ b/apps/web/src/lib/index.ts
@@ -0,0 +1 @@
+// place files you want to import through the `$lib` alias in this folder.
diff --git a/apps/web/src/lib/server/oauth/client.ts b/apps/web/src/lib/server/oauth/client.ts
new file mode 100644
index 0000000..594acb0
--- /dev/null
+++ b/apps/web/src/lib/server/oauth/client.ts
@@ -0,0 +1,76 @@
+import { NodeOAuthClient, type NodeOAuthClientOptions } from '@atproto/oauth-client-node';
+import { JoseKey } from '@atproto/jwk-jose';
+import { D1SimpleStore } from './stores';
+import { HANDLE_RESOLVER_URL, workersDidResolver, workersFetch } from './workers-compat';
+
+// TODO(v1): switch to 'atproto include:page.mooring.authSite blob:image/*' once
+// the page.mooring.* lexicons are published on-network (ADR 0012 point 10).
+// blob:image/* is a separate scope by design β permission sets cannot carry it.
+export const OAUTH_SCOPE = 'atproto transition:generic';
+
+/**
+ * Build the OAuth client for this deployment.
+ *
+ * With OAUTH_PRIVATE_KEY_JWK set (hosted): a confidential web client whose
+ * metadata is served from /client-metadata.json and keys from /jwks.json.
+ * Without it (local dev): an atproto loopback client β the auth server
+ * synthesizes metadata for http://localhost client_ids, so nothing needs to be
+ * publicly hosted. Loopback redirect URIs must use 127.0.0.1, so browse the dev
+ * server at http://127.0.0.1:5173, not http://localhost:5173.
+ */
+export async function createOAuthClient(
+ env: App.Platform['env'],
+ origin: string
+): Promise {
+ const redirectOrigin = new URL(origin);
+ if (redirectOrigin.hostname === 'localhost') redirectOrigin.hostname = '127.0.0.1';
+ const redirectUri = new URL('/oauth/callback', redirectOrigin).href;
+
+ let clientMetadata: NodeOAuthClientOptions['clientMetadata'];
+ let keyset: NodeOAuthClientOptions['keyset'];
+
+ if (env.OAUTH_PRIVATE_KEY_JWK) {
+ keyset = [await JoseKey.fromImportable(JSON.parse(env.OAUTH_PRIVATE_KEY_JWK), 'mooring-1')];
+ clientMetadata = {
+ client_id: new URL('/client-metadata.json', origin).href,
+ client_name: 'Mooring',
+ client_uri: origin,
+ redirect_uris: [redirectUri],
+ grant_types: ['authorization_code', 'refresh_token'],
+ response_types: ['code'],
+ scope: OAUTH_SCOPE,
+ application_type: 'web',
+ token_endpoint_auth_method: 'private_key_jwt',
+ token_endpoint_auth_signing_alg: 'ES256',
+ dpop_bound_access_tokens: true,
+ jwks_uri: new URL('/jwks.json', origin).href
+ };
+ } else {
+ clientMetadata = {
+ client_id: `http://localhost?${new URLSearchParams({
+ redirect_uri: redirectUri,
+ scope: OAUTH_SCOPE
+ })}`,
+ redirect_uris: [redirectUri],
+ scope: OAUTH_SCOPE,
+ grant_types: ['authorization_code', 'refresh_token'],
+ response_types: ['code'],
+ token_endpoint_auth_method: 'none',
+ application_type: 'native',
+ dpop_bound_access_tokens: true
+ };
+ }
+
+ return new NodeOAuthClient({
+ clientMetadata,
+ keyset,
+ stateStore: new D1SimpleStore(env.DB, 'oauth_state'),
+ sessionStore: new D1SimpleStore(env.DB, 'oauth_session'),
+ handleResolver: HANDLE_RESOLVER_URL,
+ didResolver: workersDidResolver,
+ fetch: workersFetch
+ // requestLock is deliberately absent: cross-isolate locking needs a
+ // Durable Object (or similar); until then we accept the client's warning
+ // and the rare token-refresh race. See the 2026-08-03 spike notes.
+ });
+}
diff --git a/apps/web/src/lib/server/oauth/stores.ts b/apps/web/src/lib/server/oauth/stores.ts
new file mode 100644
index 0000000..9bc0b07
--- /dev/null
+++ b/apps/web/src/lib/server/oauth/stores.ts
@@ -0,0 +1,38 @@
+import type { D1Database } from '@cloudflare/workers-types';
+
+/**
+ * SimpleStore implementation over a D1 table (key TEXT PK, value TEXT JSON,
+ * updated_at INTEGER). Values are the JSON-serializable shapes
+ * @atproto/oauth-client-node hands its stores (NodeSavedState/NodeSavedSession).
+ *
+ * Stores must be persistent on Workers: isolates are ephemeral and requests in
+ * one flow (authorize β callback) can land on different isolates.
+ */
+export class D1SimpleStore {
+ constructor(
+ private readonly db: D1Database,
+ private readonly table: 'oauth_state' | 'oauth_session'
+ ) {}
+
+ async get(key: string): Promise {
+ const row = await this.db
+ .prepare(`SELECT value FROM ${this.table} WHERE key = ?`)
+ .bind(key)
+ .first<{ value: string }>();
+ return row ? (JSON.parse(row.value) as V) : undefined;
+ }
+
+ async set(key: string, value: V): Promise {
+ await this.db
+ .prepare(
+ `INSERT INTO ${this.table} (key, value, updated_at) VALUES (?, ?, unixepoch())
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`
+ )
+ .bind(key, JSON.stringify(value))
+ .run();
+ }
+
+ async del(key: string): Promise {
+ await this.db.prepare(`DELETE FROM ${this.table} WHERE key = ?`).bind(key).run();
+ }
+}
diff --git a/apps/web/src/lib/server/oauth/workers-compat.ts b/apps/web/src/lib/server/oauth/workers-compat.ts
new file mode 100644
index 0000000..6586e79
--- /dev/null
+++ b/apps/web/src/lib/server/oauth/workers-compat.ts
@@ -0,0 +1,61 @@
+/**
+ * Compat layer that lets @atproto/oauth-client-node run on Cloudflare Workers
+ * under `nodejs_compat`. Verified by the 2026-08-03 spike
+ * (docs/research/2026-08-03-oauth-workers-spike.md); every piece goes through
+ * a documented NodeOAuthClient constructor option β no forks, no patching.
+ *
+ * The three incompatibilities, in the order the spike hit them:
+ * 1. The default AtprotoHandleResolverNode needs undici + node:dns (SSRF
+ * wrapping) β resolve handles over HTTP against an AppView instead.
+ * 2. The default DID resolver bakes `redirect: 'error'` into a Request object
+ * before any injected fetch runs, and workerd rejects that at Request
+ * construction β supply our own did:plc/did:web resolver.
+ * 3. XrpcHandleResolver passes `redirect: 'error'` as plain fetch init β
+ * emulate via 'manual' + a 3xx check in an injected fetch.
+ */
+
+import type { NodeOAuthClientOptions } from '@atproto/oauth-client-node';
+
+export const HANDLE_RESOLVER_URL = 'https://public.api.bsky.app';
+
+const PLC_DIRECTORY_URL = 'https://plc.directory/';
+
+type OAuthDidResolver = NonNullable;
+
+// Implemented concretely and cast once: the interface's resolve() is generic
+// over the DID method, which a plain object can't express.
+export const workersDidResolver = {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ async resolve(did: string, options?: { signal?: AbortSignal }): Promise {
+ let url: URL;
+ if (did.startsWith('did:plc:')) {
+ url = new URL(`/${encodeURIComponent(did)}`, PLC_DIRECTORY_URL);
+ } else if (did.startsWith('did:web:')) {
+ const host = decodeURIComponent(did.slice('did:web:'.length));
+ url = new URL(
+ host.includes(':')
+ ? `https://${host.split(':').join('/')}/did.json`
+ : `https://${host}/.well-known/did.json`
+ );
+ } else {
+ throw new Error(`Unsupported DID method: ${did}`);
+ }
+ const res = await fetch(url, {
+ headers: { accept: 'application/did+ld+json,application/json' },
+ signal: options?.signal
+ });
+ if (!res.ok) throw new Error(`DID resolution failed (HTTP ${res.status}) for ${did}`);
+ return res.json();
+ }
+} as OAuthDidResolver;
+
+export const workersFetch: typeof fetch = async (input, init) => {
+ if (init?.redirect === 'error') {
+ const res = await fetch(input, { ...init, redirect: 'manual' });
+ if (res.status >= 300 && res.status < 400) {
+ throw new TypeError(`Fetch redirected (redirect:"error" emulation): HTTP ${res.status}`);
+ }
+ return res;
+ }
+ return fetch(input, init);
+};
diff --git a/apps/web/src/lib/server/session.ts b/apps/web/src/lib/server/session.ts
new file mode 100644
index 0000000..82fd742
--- /dev/null
+++ b/apps/web/src/lib/server/session.ts
@@ -0,0 +1,69 @@
+import type { Cookies } from '@sveltejs/kit';
+
+/**
+ * Session cookie: the user's DID, HMAC-signed so it can't be swapped for
+ * someone else's. The OAuth tokens themselves never leave the server-side
+ * session store; this cookie only selects which stored session to restore.
+ */
+const COOKIE_NAME = 'mooring_session';
+const MAX_AGE = 60 * 60 * 24 * 30;
+
+// Fallback keeps local dev running without setup; anything deployed must set
+// SESSION_SECRET (wrangler secret put SESSION_SECRET).
+const DEV_SECRET = 'mooring-dev-secret-do-not-deploy';
+
+async function hmac(secret: string, data: string): Promise {
+ const key = await crypto.subtle.importKey(
+ 'raw',
+ new TextEncoder().encode(secret),
+ { name: 'HMAC', hash: 'SHA-256' },
+ false,
+ ['sign']
+ );
+ const sig = await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(data));
+ return btoa(String.fromCharCode(...new Uint8Array(sig)))
+ .replaceAll('+', '-')
+ .replaceAll('/', '_')
+ .replaceAll('=', '');
+}
+
+function timingSafeEqual(a: string, b: string): boolean {
+ if (a.length !== b.length) return false;
+ let diff = 0;
+ for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
+ return diff === 0;
+}
+
+export async function setSessionCookie(
+ cookies: Cookies,
+ env: App.Platform['env'],
+ did: string,
+ secure: boolean
+): Promise {
+ const sig = await hmac(env.SESSION_SECRET ?? DEV_SECRET, did);
+ cookies.set(COOKIE_NAME, `${did}.${sig}`, {
+ path: '/',
+ httpOnly: true,
+ sameSite: 'lax',
+ secure,
+ maxAge: MAX_AGE
+ });
+}
+
+export async function readSessionCookie(
+ cookies: Cookies,
+ env: App.Platform['env']
+): Promise {
+ const raw = cookies.get(COOKIE_NAME);
+ if (!raw) return undefined;
+ const dot = raw.lastIndexOf('.');
+ if (dot < 1) return undefined;
+ const did = raw.slice(0, dot);
+ const sig = raw.slice(dot + 1);
+ const expected = await hmac(env.SESSION_SECRET ?? DEV_SECRET, did);
+ return timingSafeEqual(sig, expected) ? did : undefined;
+}
+
+export function clearSessionCookie(cookies: Cookies): void {
+ cookies.delete(COOKIE_NAME, { path: '/' });
+}
diff --git a/apps/web/src/routes/+layout.svelte b/apps/web/src/routes/+layout.svelte
new file mode 100644
index 0000000..9cebde5
--- /dev/null
+++ b/apps/web/src/routes/+layout.svelte
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+{@render children()}
diff --git a/apps/web/src/routes/+page.svelte b/apps/web/src/routes/+page.svelte
new file mode 100644
index 0000000..6d9018f
--- /dev/null
+++ b/apps/web/src/routes/+page.svelte
@@ -0,0 +1,22 @@
+
+ Mooring
+
+
+
+
+ Mooring
+ Your professional presence in the Atmosphere, at your own domain.
+ Sign in with your atproto handle
+
+
+
diff --git a/apps/web/src/routes/admin/+page.server.ts b/apps/web/src/routes/admin/+page.server.ts
new file mode 100644
index 0000000..097b086
--- /dev/null
+++ b/apps/web/src/routes/admin/+page.server.ts
@@ -0,0 +1,39 @@
+import { redirect } from '@sveltejs/kit';
+import type { Actions, PageServerLoad } from './$types';
+import { clearSessionCookie, readSessionCookie } from '$lib/server/session';
+
+export const load: PageServerLoad = async ({ locals, cookies, platform }) => {
+ const did = await readSessionCookie(cookies, platform!.env);
+ if (!did) redirect(302, '/login');
+
+ try {
+ const session = await locals.oauth.restore(did);
+ // Smoke-test call against the user's own PDS through the OAuth session.
+ const res = await session.fetchHandler(
+ `/xrpc/com.atproto.repo.describeRepo?repo=${encodeURIComponent(did)}`,
+ {}
+ );
+ if (!res.ok) throw new Error(`describeRepo returned HTTP ${res.status}`);
+ const repo = (await res.json()) as { handle: string; collections: string[] };
+ return { did, handle: repo.handle, collections: repo.collections };
+ } catch (err) {
+ console.error('session restore failed', err);
+ clearSessionCookie(cookies);
+ redirect(302, '/login');
+ }
+};
+
+export const actions: Actions = {
+ logout: async ({ locals, cookies, platform }) => {
+ const did = await readSessionCookie(cookies, platform!.env);
+ clearSessionCookie(cookies);
+ if (did) {
+ try {
+ await locals.oauth.revoke(did);
+ } catch (err) {
+ console.error('revoke failed (session cleared anyway)', err);
+ }
+ }
+ redirect(302, '/');
+ }
+};
diff --git a/apps/web/src/routes/admin/+page.svelte b/apps/web/src/routes/admin/+page.svelte
new file mode 100644
index 0000000..fdd26d2
--- /dev/null
+++ b/apps/web/src/routes/admin/+page.svelte
@@ -0,0 +1,44 @@
+
+
+
+ Admin β Mooring
+
+
+
+ Welcome aboard
+
+ Signed in as @{data.handle} ({data.did})
+
+
+ Collections in your repo
+ {#if data.collections.length === 0}
+ No collections yet.
+ {:else}
+
+ {#each data.collections as nsid (nsid)}
+ {nsid}
+ {/each}
+
+ {/if}
+
+
+
+
+
diff --git a/apps/web/src/routes/client-metadata.json/+server.ts b/apps/web/src/routes/client-metadata.json/+server.ts
new file mode 100644
index 0000000..3e1f700
--- /dev/null
+++ b/apps/web/src/routes/client-metadata.json/+server.ts
@@ -0,0 +1,9 @@
+import { json } from '@sveltejs/kit';
+import type { RequestEvent } from './$types';
+
+// Served publicly: the authorization server fetches this URL (it is the
+// client_id) to learn who we are. Only meaningful for the hosted client;
+// the dev loopback client's metadata is synthesized by the auth server.
+export function GET({ locals }: RequestEvent): Response {
+ return json(locals.oauth.clientMetadata);
+}
diff --git a/apps/web/src/routes/jwks.json/+server.ts b/apps/web/src/routes/jwks.json/+server.ts
new file mode 100644
index 0000000..4146824
--- /dev/null
+++ b/apps/web/src/routes/jwks.json/+server.ts
@@ -0,0 +1,7 @@
+import { json } from '@sveltejs/kit';
+import type { RequestEvent } from './$types';
+
+// Public keys backing private_key_jwt client authentication.
+export function GET({ locals }: RequestEvent): Response {
+ return json(locals.oauth.jwks);
+}
diff --git a/apps/web/src/routes/login/+page.server.ts b/apps/web/src/routes/login/+page.server.ts
new file mode 100644
index 0000000..afccf54
--- /dev/null
+++ b/apps/web/src/routes/login/+page.server.ts
@@ -0,0 +1,26 @@
+import { fail, redirect } from '@sveltejs/kit';
+import type { Actions } from './$types';
+import { OAUTH_SCOPE } from '$lib/server/oauth/client';
+
+export const actions: Actions = {
+ default: async ({ request, locals }) => {
+ const form = await request.formData();
+ const handle = String(form.get('handle') ?? '').trim();
+ if (!handle) {
+ return fail(400, { handle, message: 'Enter your handle (ex: you.bsky.social).' });
+ }
+
+ let authorizationUrl: URL;
+ try {
+ authorizationUrl = await locals.oauth.authorize(handle, { scope: OAUTH_SCOPE });
+ } catch (err) {
+ console.error('authorize failed', err);
+ return fail(400, {
+ handle,
+ message: `Couldn't start sign-in for β${handle}β. Check the handle and try again.`
+ });
+ }
+
+ redirect(302, authorizationUrl.href);
+ }
+};
diff --git a/apps/web/src/routes/login/+page.svelte b/apps/web/src/routes/login/+page.svelte
new file mode 100644
index 0000000..3b1af21
--- /dev/null
+++ b/apps/web/src/routes/login/+page.svelte
@@ -0,0 +1,58 @@
+
+
+
+ Sign in β Mooring
+
+
+
+ Sign in
+ Use your atproto handle β your data stays yours.
+
+ {#if form?.message}
+ {form.message}
+ {/if}
+
+
+
diff --git a/apps/web/src/routes/oauth/callback/+server.ts b/apps/web/src/routes/oauth/callback/+server.ts
new file mode 100644
index 0000000..243586a
--- /dev/null
+++ b/apps/web/src/routes/oauth/callback/+server.ts
@@ -0,0 +1,17 @@
+import { redirect } from '@sveltejs/kit';
+import type { RequestEvent } from './$types';
+import { setSessionCookie } from '$lib/server/session';
+
+export async function GET({ url, locals, cookies, platform }: RequestEvent): Promise {
+ let did: string;
+ try {
+ const { session } = await locals.oauth.callback(url.searchParams);
+ did = session.did;
+ } catch (err) {
+ console.error('oauth callback failed', err);
+ redirect(302, '/login');
+ }
+
+ await setSessionCookie(cookies, platform!.env, did, url.protocol === 'https:');
+ redirect(302, '/admin');
+}
diff --git a/apps/web/static/robots.txt b/apps/web/static/robots.txt
new file mode 100644
index 0000000..b6dd667
--- /dev/null
+++ b/apps/web/static/robots.txt
@@ -0,0 +1,3 @@
+# allow crawling everything by default
+User-agent: *
+Disallow:
diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json
new file mode 100644
index 0000000..2c2ed3c
--- /dev/null
+++ b/apps/web/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "extends": "./.svelte-kit/tsconfig.json",
+ "compilerOptions": {
+ "rewriteRelativeImportExtensions": true,
+ "allowJs": true,
+ "checkJs": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strict": true,
+ "moduleResolution": "bundler"
+ }
+ // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
+ // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
+ //
+ // To make changes to top-level options such as include and exclude, we recommend extending
+ // the generated config; see https://svelte.dev/docs/kit/configuration#typescript
+}
diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts
new file mode 100644
index 0000000..51401de
--- /dev/null
+++ b/apps/web/vite.config.ts
@@ -0,0 +1,19 @@
+import adapter from '@sveltejs/adapter-cloudflare';
+import { sveltekit } from '@sveltejs/kit/vite';
+import { defineConfig } from 'vite';
+
+export default defineConfig({
+ plugins: [
+ sveltekit({
+ compilerOptions: {
+ // Force runes mode for the project, except for libraries. Can be removed in svelte 6.
+ runes: ({ filename }) =>
+ filename.split(/[/\\]/).includes('node_modules') ? undefined : true
+ },
+
+ // Cloudflare Workers target (ADR 0011). Bindings from wrangler.jsonc
+ // are emulated during `vite dev` via the adapter's platform proxy.
+ adapter: adapter()
+ })
+ ]
+});
diff --git a/apps/web/wrangler.jsonc b/apps/web/wrangler.jsonc
new file mode 100644
index 0000000..053be62
--- /dev/null
+++ b/apps/web/wrangler.jsonc
@@ -0,0 +1,25 @@
+{
+ "$schema": "node_modules/wrangler/config-schema.json",
+ "name": "mooring-web",
+ "main": ".svelte-kit/cloudflare/_worker.js",
+ "compatibility_date": "2026-07-01",
+ "compatibility_flags": ["nodejs_compat"],
+ "assets": {
+ "binding": "ASSETS",
+ "directory": ".svelte-kit/cloudflare"
+ },
+ "d1_databases": [
+ {
+ "binding": "DB",
+ "database_name": "mooring",
+ // Placeholder until the real database exists; local dev (wrangler dev /
+ // vite dev platform proxy) uses a local SQLite file regardless.
+ "database_id": "00000000-0000-0000-0000-000000000000",
+ "migrations_dir": "migrations"
+ }
+ ]
+ // Secrets (set via `wrangler secret put`, or .dev.vars locally):
+ // OAUTH_PRIVATE_KEY_JWK β ES256 private key JWK (JSON) for private_key_jwt;
+ // absent in dev = loopback OAuth client.
+ // SESSION_SECRET β HMAC key for the session cookie.
+}
diff --git a/docs/NEXT.md b/docs/NEXT.md
index c8c94de..1ea1de7 100644
--- a/docs/NEXT.md
+++ b/docs/NEXT.md
@@ -2,19 +2,25 @@
The flight plan. Each item carries enough context to start cold; update this file whenever an item lands (move it to "Done") or a new one is queued. Decisions made while working an item still go through `decisions/` as usual.
-_Last updated: 2026-08-03 (ADR 0012 ratified β `page.mooring.*` schemas accepted; v1 build is next)._
+_Last updated: 2026-08-03 (v1 build started: OAuth-on-Workers spike passed, scaffold up β SvelteKit + Workers + lexicon tests, OAuth login working end-to-end)._
## Where things stand
-Feasibility is done and the verdict was **build it** (see `FEASIBILITY.md`). All founding decisions are recorded: PD-1..8 in `decisions/product-decisions.md`, ADRs 0001β0012 in `decisions/adr/` β all Accepted, including ADR 0008 (v1 scope), ADR 0010 (tech stack: TypeScript + SvelteKit, first-party `@atproto/*`, direct PDS reads for v1, BEAM benched for v2 services), ADR 0011 (hosting: Cloudflare Workers + Cloudflare for SaaS; DB: SQLite-family via D1 hosted / file self-host), and ADR 0012 (`page.mooring.*` record schemas β draft lexicons in `lexicons/page/mooring/`). The product is **Mooring** at **mooring.page** (domain secured); the repo keeps the codename Fahrenheit. No product code exists yet β scaffolding is unblocked but starts only on Jacob's explicit request.
+Feasibility is done and the verdict was **build it** (see `FEASIBILITY.md`). All founding decisions are recorded: PD-1..8 in `decisions/product-decisions.md`, ADRs 0001β0012 in `decisions/adr/` β all Accepted, including ADR 0008 (v1 scope), ADR 0010 (tech stack: TypeScript + SvelteKit, first-party `@atproto/*`, direct PDS reads for v1, BEAM benched for v2 services), ADR 0011 (hosting: Cloudflare Workers + Cloudflare for SaaS; DB: SQLite-family via D1 hosted / file self-host), and ADR 0012 (`page.mooring.*` record schemas β draft lexicons in `lexicons/page/mooring/`). The product is **Mooring** at **mooring.page** (domain secured); the repo keeps the codename Fahrenheit. **The v1 build is underway** (Jacob green-lit 2026-08-03): npm workspaces with `apps/web` (SvelteKit + adapter-cloudflare, atproto OAuth sign-in with the Workers compat layer, D1-backed stores) and `packages/lexicons` (convention tests), plus CI.
## Queued, roughly in order
-### 1. Build v1 (per ADR 0008 β the scope is ratified; don't re-scope)
+### 1. Continue v1 (per ADR 0008 β the scope is ratified; don't re-scope)
-OAuth login β read-only adapters for Bluesky, standard.site (+ `pub.leaflet.*` legacy fallback), sifa β one professional-presence theme β authored pages/config in our lexicon (ADR 0012; drafts in `lexicons/page/mooring/`) β hosted on Cloudflare Workers (ADR 0011), free subdomain, paid custom domain. **First scaffolding step is the ADR 0011 spike:** verify `@atproto/oauth-client-node` under Workers `nodejs_compat`; fall back to `@atcute` (already approved, Blento-proven) if it doesn't fly. Deferred list lives in the ADR; resist scope creep.
+Done so far: OAuth login (loopback dev client; hosted-client path ready pending a real key + deploy) with D1-backed state/session stores; lexicon convention tests. Remaining, roughly in dependency order:
-Carried over from the schema work (ADR 0012 details): add sifa-style lexicon convention tests to the scaffold (NSIDβpath, constraint checks); check during the OAuth spike whether blob upload (site icon) needs a `blob:` scope beyond the repo permission; **before the first real user records ship** β a lexicon.community sanity-check post, then publish the lexicons on-network (`com.atproto.lexicon.schema`, rkey = NSID, `_lexicon.mooring.page` DNS TXT). Until published, the drafts stay freely editable.
+- **Read-only adapters**: Bluesky posts, standard.site documents (+ `pub.leaflet.*` legacy fallback), sifa profile β direct PDS reads behind a thin deletion-honoring cache (ADR 0010 Β§4).
+- **Site/page authoring**: write `page.mooring.site` / `page.mooring.page` records from the admin (empty site record on first login = working site).
+- **The one professional-presence theme** (renderer kept separable per ADR 0005).
+- **Hosting wiring**: real D1 database + first `wrangler deploy`, wildcard subdomains, then Cloudflare for SaaS custom domains with `_mooring` DNS-TXT DID verification (ADR 0011).
+- **First real deployed login** is the acceptance test for the OAuth stack (`callback()` wasn't exercisable in the spike); test against a self-hosted PDS too, and set a `SESSION_SECRET`.
+- **Before the first real user records ship**: lexicon.community sanity-check post, then publish the lexicons on-network (`com.atproto.lexicon.schema`, rkey = NSID, `_lexicon.mooring.page` DNS TXT) and switch `OAUTH_SCOPE` to `atproto include:page.mooring.authSite blob:image/*`. Until published, the drafts stay freely editable.
+- Later, when token-refresh races become real: a Durable-Object `requestLock` for the OAuth client.
## Standing / background
@@ -25,6 +31,7 @@ Carried over from the schema work (ADR 0012 details): add sifa-style lexicon con
## Done
+- 2026-08-03 β v1 build started. **OAuth-on-Workers spike passed** (ADR 0011 Β§6): `@atproto/oauth-client-node@0.5.2` runs under `nodejs_compat` with a 3-shim compat layer via documented options (HTTP handle resolver, custom DID resolver, redirect-'error' fetch emulation); @atcute fallback not needed. Blob-scope question answered: site-icon upload needs `blob:image/*` requested separately (can't live in a permission set). Research: `research/2026-08-03-oauth-workers-spike.md`. **Scaffold landed**: npm workspaces; `apps/web` (SvelteKit/Svelte 5 + adapter-cloudflare, wrangler + D1 migrations, OAuth login/callback/admin routes, HMAC-signed session cookie) smoke-tested on workerd β login POST returns a real bsky.social authorization URL with state in local D1; `packages/lexicons` (17 convention tests: NSIDβpath, createdAt, 10Γ maxLength, permission-set integrity, sample-record validation incl. open-union + negative cases); GitHub Actions CI (check/test/build).
- 2026-08-03 β Schemas decided: ADR 0012 **Accepted**: two v1 record types β `page.mooring.site` (`key: any`, default site at rkey `self`, layout = embedded ordered `sections` open union, theme mirroring standard.site's color roles, empty record = working site) and `page.mooring.page` (`key: tid`, open `content` union with markdown member, rendering-only `visibility`), plus the `authSite` permission set; `.source` reserved, unshipped. Drafts in `lexicons/page/mooring/`, machine-validated with `@atproto/lexicon`. Evolution policy: add-optional-only. Prior art: `research/2026-07-31-lexicon-prior-art.md` (lexicon.community had nothing site-shaped). (PR #6 + ratification follow-up)
- 2026-07-30 β Hosting decided: ADR 0011 **Accepted** (ratified by Jacob same day): Cloudflare Workers + Cloudflare for SaaS as hosted target (~$5/mo launch, ~2%-of-revenue custom-domain COGS at scale); DB finalized SQLite-family (D1 hosted / file+Litestream self-host β closes ADR 0010 Β§5's provisional note); VPS+Caddy (wisp.place recipe) as first-class self-host path; `_mooring. TXT did:β¦` verification. Ruled out: Fly.io (dominated), Vercel ($20 floor, DNS coupling, worst scale curve), Railway (20-domain/service cap, checked at Jacob's request). Research: `research/2026-07-30-hosting-infra.md`.
- 2026-07-30 β Trademark screen on "Mooring": **passed**. US side clean β the only live software-class mark is "ONLINE MOORING" (boat-mooring ASP for harbormasters, different services); bare MOORING marks all dead. EU screened via secondary sources, then confirmed same day by Jacob's manual TMview check (classes 9/35/38/42 β clear); no residuals. Detail appended to `research/2026-07-30-naming.md`. Brand spend fully unblocked.
diff --git a/docs/research/2026-08-03-oauth-workers-spike.md b/docs/research/2026-08-03-oauth-workers-spike.md
new file mode 100644
index 0000000..a2cadf8
--- /dev/null
+++ b/docs/research/2026-08-03-oauth-workers-spike.md
@@ -0,0 +1,50 @@
+# Spike: `@atproto/oauth-client-node` on Cloudflare Workers (`nodejs_compat`)
+
+**Checkpoint date:** 2026-08-03. The named spike from ADR 0011 Β§6, run before scaffolding commits. Method: a minimal Worker executed in the real workerd runtime via `wrangler dev` (local mode), driving the client through key generation, construction, and a live `authorize()` against bsky.social.
+
+## Verdict: it flies β with a small compat layer
+
+`@atproto/oauth-client-node@0.5.2` (pulling `@atproto/oauth-client@0.8.2`, `@atproto/jwk-jose@0.2.4`) completes a full `client.authorize()` under workerd with `nodejs_compat`: handle β DID β PDS resolution, authorization-server metadata discovery, and a pushed authorization request (PAR) accepted by bsky.social returning a real `request_uri`. Bundle size 3.4 MB raw / **697 KB gzipped** β comfortably under the 10 MB Workers limit. No fork, no monkey-patching: every fix goes through documented constructor options. The @atcute fallback is **not needed** (it remains the named fallback if pre-1.0 churn breaks these seams β the options used are public API, but pinning + changelog discipline per ADR 0010 applies doubly here).
+
+## The compat layer (three shims, ~40 lines)
+
+What breaks out of the box, and the supported escape hatch for each:
+
+1. **Default handle resolver requires Node internals.** `NodeOAuthClient`'s default `AtprotoHandleResolverNode` wraps fetch in unicast SSRF protection (undici + `node:dns`) and throws `Unicast SSRF protection requires Node.js 20.6+` at construction under workerd.
+ β Pass `handleResolver: ''` (e.g. `https://public.api.bsky.app`), which resolves handles over HTTP via `com.atproto.identity.resolveHandle`.
+2. **Default DID resolver is unfixable via fetch injection.** `DidPlcMethod`/`DidWebMethod` (in `@atproto-labs/did-resolver`) hard-code `redirect: 'error'`, and their `bindFetch` wrapper bakes it into a `Request` object *before* calling any injected fetch β workerd rejects `new Request(url, {redirect:'error'})` at construction ("error" is deliberately unimplemented at the edge).
+ β Pass a custom `didResolver` (~25 lines: `GET https://plc.directory/` for did:plc, `.well-known/did.json` for did:web, plain fetch, `accept: application/did+ld+json,application/json`). `createDidResolver` wraps it in the caching layer automatically. Upstream could fix this by using `redirect:'manual'` + status check; worth an issue when we have a repro repo public.
+3. **`XrpcHandleResolver` passes `redirect:'error'` as plain init** (interceptable, unlike β2).
+ β Pass a `fetch` option that rewrites `redirect:'error'` β `'manual'` and throws on 3xx.
+
+Also confirmed working under workerd: `JoseKey.generate(['ES256'])` (kty=EC, P-256), `private_key_jwt` client-assertion signing, DPoP key handling β the whole `jose`/node-crypto path.
+
+## Caveats for the scaffold
+
+- **`requestLock` warning is real on Workers.** The client warns `No lock mechanism provided. Credentials might get revoked.` In-memory locks are meaningless across Worker isolates; token refresh needs a cross-isolate lock eventually (Durable Objects being the natural home) or acceptance of the rare refresh race at v1 traffic. State/session stores likewise must be persistent (D1), not in-memory.
+- **`callback()`/token exchange was not exercised** β it requires an interactive login. Risk is low (same signing + fetch primitives already proven), but the first end-to-end login through the scaffold is the true finish line; treat it as the acceptance test.
+- **Test matrix (ADR 0007) still owed**: the spike ran against bsky.social only; self-hosted PDS + `transition:generic` fallback remain to be tested from the scaffold.
+- Spike used a **loopback client** (`client_id: http://localhost?...`, auth method `none`) for the green run; the web-client path with hosted `client-metadata.json` + `jwks.json` got as far as bsky.social fetching our (not yet existing) metadata URL and erroring server-side β i.e., the client-side path is proven, the metadata endpoints just need to exist, which they will in the scaffold.
+- `wrangler dev` local mode runs the real workerd binary β same engine as production β but a deployed smoke test on an actual `workers.dev` route is still worth doing once the scaffold deploys.
+
+## Blob scope for the site icon (carried-over ADR 0012 check)
+
+Answered: `com.atproto.repo.uploadBlob` requires a separate **`blob:` scope** (mime-scoped, e.g. `blob:image/*`) β repo/collection permission alone does not cover uploads, and **blob permissions cannot be included in a permission set** ("The `blob:*/*` permission β¦ must always be requested separately" β permission-sets guide). So Mooring's OAuth scope request is:
+
+```
+atproto include:page.mooring.authSite blob:image/*
+```
+
+`page.mooring.authSite` (ADR 0012) stays as-is; no schema change needed.
+
+## Sources
+
+- Spike code: carried into the scaffold as the Workers OAuth compat module (originally scratchpad `oauth-spike/`, results reproduced here)
+- https://atproto.com/guides/permission-sets (scopes & permission sets; blob exclusion)
+- https://app.unpkg.com/@atproto/oauth-scopes@0.3.1/files/src/atproto-oauth-scope.ts (blob scope syntax)
+- Workers `redirect:'error'` rejection message: workerd fetch implementation (surfaced verbatim in spike runs)
+- ADR 0011 Β§6 (spike definition), ADR 0010 Β§2 (@atcute as approved fallback)
+
+## So what
+
+Scaffolding proceeds on first-party `@atproto/oauth-client-node` with the three-shim compat module, pinned versions, D1-backed stores, and `blob:image/*` requested alongside the permission set. The @atcute fallback stays in the back pocket; the ADR 0011 decision stands unchanged.
diff --git a/docs/research/README.md b/docs/research/README.md
index 508f68a..2fb7d05 100644
--- a/docs/research/README.md
+++ b/docs/research/README.md
@@ -13,5 +13,6 @@ Findings from research sessions, preserved so future sessions (human or agent) d
| [`2026-07-30-comparable-stacks.md`](2026-07-30-comparable-stacks.md) | 2026-07-30 | What 8 comparable atproto apps run on; custom-domain serving patterns |
| [`2026-07-30-hosting-infra.md`](2026-07-30-hosting-infra.md) | 2026-07-30 | Hosted infra target + cost model: Cloudflare vs VPS+Caddy vs Vercel vs Fly |
| [`2026-07-31-lexicon-prior-art.md`](2026-07-31-lexicon-prior-art.md) | 2026-07-31 | Schema-design prior art: site.standard/sifa conventions; Blento/Linkat/wisp/Leaflet record models |
+| [`2026-08-03-oauth-workers-spike.md`](2026-08-03-oauth-workers-spike.md) | 2026-08-03 | ADR 0011 Β§6 spike: `@atproto/oauth-client-node` on Workers β passes with a 3-shim compat layer; blob scope answer |
Conventions: one dated file per topic, source URLs inline, and an honest "so what" at the end of each. When you re-research a topic, add a new dated file rather than editing the old one, and update this index.
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..1e777e6
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,3615 @@
+{
+ "name": "fahrenheit",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "fahrenheit",
+ "license": "AGPL-3.0-only",
+ "workspaces": [
+ "apps/*",
+ "packages/*"
+ ],
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "apps/web": {
+ "version": "0.0.1",
+ "dependencies": {
+ "@atproto/jwk-jose": "^0.2.4",
+ "@atproto/oauth-client-node": "^0.5.2"
+ },
+ "devDependencies": {
+ "@cloudflare/workers-types": "^5.20260801.1",
+ "@sveltejs/adapter-cloudflare": "^7.2.9",
+ "@sveltejs/kit": "^2.63.0",
+ "@sveltejs/vite-plugin-svelte": "^7.1.2",
+ "svelte": "^5.56.1",
+ "svelte-check": "^4.6.0",
+ "typescript": "^6.0.3",
+ "vite": "^8.0.16",
+ "wrangler": "^4.118.0"
+ }
+ },
+ "node_modules/@atproto-labs/did-resolver": {
+ "version": "0.3.7",
+ "resolved": "https://registry.npmjs.org/@atproto-labs/did-resolver/-/did-resolver-0.3.7.tgz",
+ "integrity": "sha512-F3M3U5cU1QSAXX3J5auGEc5N2pgDgpirAjvyDFsytXuyWfrjWfTPd/H+DZrrED7gK+noW0cAWtxxjdX7/cTSVQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto-labs/fetch": "^0.3.5",
+ "@atproto-labs/pipe": "^0.2.4",
+ "@atproto-labs/simple-store": "^0.5.1",
+ "@atproto-labs/simple-store-memory": "^0.2.6",
+ "@atproto/did": "^0.5.4",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto-labs/fetch": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@atproto-labs/fetch/-/fetch-0.3.5.tgz",
+ "integrity": "sha512-iDFZEoNqfL17EVKE+uNzdUD7YF8LWhEhxeBtP6x+PNuAxoXv3ip9vLmB8nNzNxFwVn++FipfDtSiPqmziv1bdA==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto-labs/pipe": "^0.2.4"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto-labs/fetch-node": {
+ "version": "0.3.7",
+ "resolved": "https://registry.npmjs.org/@atproto-labs/fetch-node/-/fetch-node-0.3.7.tgz",
+ "integrity": "sha512-WZvjXIeEHGeOPmeckyGiSGeoHhkvzwnKtSrRSxgnHakkNqlKNLmPbUIYOIiJgiYgBSOCbse5NpPLRu3Zdw2+gA==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto-labs/fetch": "^0.3.5",
+ "@atproto-labs/pipe": "^0.2.4",
+ "ipaddr.js": "^2.1.0",
+ "undici_v6": "npm:undici@^6.x",
+ "undici_v7": "npm:undici@^7.x",
+ "undici_v8": "npm:undici@^8.x"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto-labs/handle-resolver": {
+ "version": "0.4.8",
+ "resolved": "https://registry.npmjs.org/@atproto-labs/handle-resolver/-/handle-resolver-0.4.8.tgz",
+ "integrity": "sha512-38I+j8Efs+cCgW/NX9RFKKu7qv/AF+FqxlKS8sWjXlNZSHQZqPj5cnKVQhSsJCs4ypPB84iKch8w4/STd33bLg==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto-labs/simple-store": "^0.5.1",
+ "@atproto-labs/simple-store-memory": "^0.2.6",
+ "@atproto/did": "^0.5.4",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto-labs/handle-resolver-node": {
+ "version": "0.2.8",
+ "resolved": "https://registry.npmjs.org/@atproto-labs/handle-resolver-node/-/handle-resolver-node-0.2.8.tgz",
+ "integrity": "sha512-S4HR3s15TP85LpBvK2pfmJgXRFEX9rPFpcRfBPeW1Rh2Bj8ixN5VZwOgABz2fHTyMidEZLyFGxc0G5HlVh0aWw==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto-labs/fetch-node": "^0.3.7",
+ "@atproto-labs/handle-resolver": "^0.4.8",
+ "@atproto/did": "^0.5.4"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto-labs/identity-resolver": {
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/@atproto-labs/identity-resolver/-/identity-resolver-0.4.7.tgz",
+ "integrity": "sha512-lKDaiBHoxrqTOFdSKAAPpplEtbbFrH4djGjnXJtOSMnZ46k7+G7AkCr1xycGGPOBYfyF54zRnTp0Tt8iu86qWg==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto-labs/did-resolver": "^0.3.7",
+ "@atproto-labs/handle-resolver": "^0.4.8"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto-labs/pipe": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@atproto-labs/pipe/-/pipe-0.2.4.tgz",
+ "integrity": "sha512-n67jCcrC+ouAeO10cWkpPzzLMlDi/lDCU30Us+LGqhOPhT6c4t5ASdBLQi9W3jUQtRzQBt3G9zipF+xKWNvVbw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto-labs/simple-store": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/@atproto-labs/simple-store/-/simple-store-0.5.1.tgz",
+ "integrity": "sha512-vfvoDhu6ds6BT3Pqe+d2/LBU1WpDRtt69y6zltlfMCoucPm82m1j50/Wb6xTvv+oZ+2j0JyZVXsmXQ12SWYQJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto-labs/simple-store-memory": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/@atproto-labs/simple-store-memory/-/simple-store-memory-0.2.6.tgz",
+ "integrity": "sha512-DD1v7MEfYF3BAcEpMTTpzfBLWLoI2HuyBhku2YpjHoqPrRrhCtE1alkxfPHjtjJVIjuU/XNU0cF/wB3+5FiKsA==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto-labs/simple-store": "^0.5.1",
+ "lru-cache": "^10.2.0"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto/common-web": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/@atproto/common-web/-/common-web-0.5.8.tgz",
+ "integrity": "sha512-GiYY2Jgbg1aWe9QGT3TswC/wZNicipBDz0nFo4FrP6XqENEJJRxGKAf/zjvqbesfIQFhHXi1VbSFY7GStB8v8w==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto/lex-data": "^0.1.7",
+ "@atproto/lex-json": "^0.1.6",
+ "@atproto/syntax": "^0.7.3",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto/did": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/@atproto/did/-/did-0.5.4.tgz",
+ "integrity": "sha512-BlnwQ+obL+4ZA71KH/EzZ3TY+cpSxnLiUI85mjBJIQwvDF/oN2sQA18wIj9jpduviIt2b/cMtlJuzHjzBkfXvw==",
+ "license": "MIT",
+ "dependencies": {
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto/jwk": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/@atproto/jwk/-/jwk-0.7.4.tgz",
+ "integrity": "sha512-tq7TUDmNfe1yDfpRgdGQMJdl9TUlJmREQNCag9yg5w8Evu+TOiFiLgiOCbo7X4ouRPSgd1DpOzXbUa8UyKKMZA==",
+ "license": "MIT",
+ "dependencies": {
+ "multiformats": "^13.0.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto/jwk-jose": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@atproto/jwk-jose/-/jwk-jose-0.2.4.tgz",
+ "integrity": "sha512-gzDoA0JTwnc0ZJOBLM7WX9xFxtynRS2K1Bofb8epzoMWDQvyvfbPcfkdPrKFM7NXCFUVpGpBnsCB8KFPTf1rCg==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto/jwk": "^0.7.4",
+ "jose": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto/jwk-webcrypto": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/@atproto/jwk-webcrypto/-/jwk-webcrypto-0.3.4.tgz",
+ "integrity": "sha512-UsFIUozqnRecXPo6HgKV4PW4FqYHxX1V3iAe0rRV6Q2RSfYD8V2mZ89pv8NpvJynnaqJArBQ7HZlcg0F4tRYhA==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto/jwk": "^0.7.4",
+ "@atproto/jwk-jose": "^0.2.4",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto/lex-data": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/@atproto/lex-data/-/lex-data-0.1.7.tgz",
+ "integrity": "sha512-kW/dPLqo/WgCLV+XESR4JKwV6c1rZWJGOfuPupZGTjEDAKoBbKXdaEzX9/1vKQYbZ9U3j0DS/n7OFFK7wBugyQ==",
+ "license": "MIT",
+ "dependencies": {
+ "multiformats": "^13.0.0",
+ "tslib": "^2.8.1",
+ "unicode-segmenter": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto/lex-json": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/@atproto/lex-json/-/lex-json-0.1.6.tgz",
+ "integrity": "sha512-mvrAd0lbyuecIHjyld8QN6MN6CBf4j0GCxLzegsvLh0SvDf+GbYWklkcQqmITL44yFQOwmA/QNIQj0Uvh7+R/g==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto/lex-data": "^0.1.7",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto/lexicon": {
+ "version": "0.7.10",
+ "resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.7.10.tgz",
+ "integrity": "sha512-HH/3d3z5Qt0JoJ9iOuLP/YT++6lb5wWMQsvgQ2TGfgkbuzDQ6AX6X1H5uJ9luPci4/LaADfpwLZfeqyy/Hjfaw==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto/common-web": "^0.5.8",
+ "@atproto/syntax": "^0.7.3",
+ "multiformats": "^13.0.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto/oauth-client": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/@atproto/oauth-client/-/oauth-client-0.8.2.tgz",
+ "integrity": "sha512-clYhVu/Y0prv3JGu8a4IOnC9jjwwkXFwgySgDXBpgStJ/JNmtH2Sss9XLVq5CDoAZBVLxdb/oT1W1iQJrkoTpA==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto-labs/did-resolver": "^0.3.7",
+ "@atproto-labs/fetch": "^0.3.5",
+ "@atproto-labs/handle-resolver": "^0.4.8",
+ "@atproto-labs/identity-resolver": "^0.4.7",
+ "@atproto-labs/simple-store": "^0.5.1",
+ "@atproto-labs/simple-store-memory": "^0.2.6",
+ "@atproto/did": "^0.5.4",
+ "@atproto/jwk": "^0.7.4",
+ "@atproto/oauth-types": "^0.7.5",
+ "@atproto/xrpc": "^0.8.9",
+ "core-js": "^3",
+ "multiformats": "^13.0.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto/oauth-client-node": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@atproto/oauth-client-node/-/oauth-client-node-0.5.2.tgz",
+ "integrity": "sha512-rTGhniY1ukH3CcJqZ6GcV3GLybwY1JxhkC3au/ksnpuHQ9Yttrng67cZRcIw6gQWGWrGzEGOqXX/+Z41i/WyRw==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto-labs/did-resolver": "^0.3.7",
+ "@atproto-labs/handle-resolver-node": "^0.2.8",
+ "@atproto-labs/simple-store": "^0.5.1",
+ "@atproto/did": "^0.5.4",
+ "@atproto/jwk": "^0.7.4",
+ "@atproto/jwk-jose": "^0.2.4",
+ "@atproto/jwk-webcrypto": "^0.3.4",
+ "@atproto/oauth-client": "^0.8.2",
+ "@atproto/oauth-types": "^0.7.5"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto/oauth-types": {
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/@atproto/oauth-types/-/oauth-types-0.7.5.tgz",
+ "integrity": "sha512-x75O0HsKB1IGfBikAQrrTX6EL8Rt4Q0+wMcwhZQRGPk/N/WqbYbsW3Powj4R8ZJKSfWCpVfaw32Piu1pTi891Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto/did": "^0.5.4",
+ "@atproto/jwk": "^0.7.4",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto/syntax": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/@atproto/syntax/-/syntax-0.7.3.tgz",
+ "integrity": "sha512-7LU8Ra79L5wCqVAZZst2352VMMwkU4KNagVMm6pnURrY/uS7+HrJl3XCuA4V2Gy2dEpkt1r6DBxlsP43/VjDBw==",
+ "license": "MIT",
+ "dependencies": {
+ "iso-datestring-validator": "^2.2.2",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@atproto/xrpc": {
+ "version": "0.8.9",
+ "resolved": "https://registry.npmjs.org/@atproto/xrpc/-/xrpc-0.8.9.tgz",
+ "integrity": "sha512-3jRiAuHCqYFoT8Nv25xFRmgrfmoo84yBnB5PfVP95JoRP+szIkwHS6mq72ZETYbWmLA1tNyR5QVEHrhHZ1LQhw==",
+ "license": "MIT",
+ "dependencies": {
+ "@atproto/lexicon": "^0.7.10",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@cloudflare/kv-asset-handler": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.5.0.tgz",
+ "integrity": "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==",
+ "dev": true,
+ "license": "MIT OR Apache-2.0",
+ "engines": {
+ "node": ">=22.0.0"
+ }
+ },
+ "node_modules/@cloudflare/unenv-preset": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.16.1.tgz",
+ "integrity": "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw==",
+ "dev": true,
+ "license": "MIT OR Apache-2.0",
+ "peerDependencies": {
+ "unenv": "2.0.0-rc.24",
+ "workerd": ">1.20260305.0 <2.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "workerd": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@cloudflare/workerd-darwin-64": {
+ "version": "1.20260730.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260730.1.tgz",
+ "integrity": "sha512-+MBHmPaiTe2KajryW0T24rZvWFxb41hD3d8anNzQqHzft6vSEb18+sp0znSwxgij7ApPhSM1+vhkNg4f3YMguA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-darwin-arm64": {
+ "version": "1.20260730.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260730.1.tgz",
+ "integrity": "sha512-SBHKntPkKvNPgaCrTe99xC1CAl8ygJDzlYfK0LbuJ1muKadIw35WnhO0wu894fKBtllsVQdNzDLee+cm0ppLSQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-linux-64": {
+ "version": "1.20260730.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260730.1.tgz",
+ "integrity": "sha512-ouyPOSMbiKPeSwUJUvxtMcxGAXs2J4aPE4T5ABIYX5ClcQx5j5bbHTmnqOQEY8sAuLTPjH7dY+iB6UI5ISlwwA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-linux-arm64": {
+ "version": "1.20260730.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260730.1.tgz",
+ "integrity": "sha512-YQ+Mi78U3TPdgBPtwq+Sm6rJU+Ihl2y0pjYtuuKkdmUbYzL7oLR6Xqq9wljhasnuCFICssDJaqhMep5WizYoEQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-windows-64": {
+ "version": "1.20260730.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260730.1.tgz",
+ "integrity": "sha512-27fAN+vUECW1oYVc1KOcHYpkL8COM2Uxtxql7TL595kxbjoqS5yckw7NLz7bTf2pALFCZWjqXDjZGJ/xbG4ZKQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workers-types": {
+ "version": "5.20260801.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-5.20260801.1.tgz",
+ "integrity": "sha512-XCv5xWi47WQOK0LpLa6997Mrpz8Ct+nZmp/M5Xp8Z4BFsarf7nYjkznGOcOoYK5m1GfbMFEEuQ2OIZnbIWoe9A==",
+ "dev": true,
+ "license": "MIT OR Apache-2.0"
+ },
+ "node_modules/@cspotcode/source-map-support": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.11.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz",
+ "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz",
+ "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz",
+ "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz",
+ "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz",
+ "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz",
+ "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz",
+ "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz",
+ "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz",
+ "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz",
+ "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz",
+ "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz",
+ "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz",
+ "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz",
+ "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz",
+ "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz",
+ "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz",
+ "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz",
+ "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz",
+ "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz",
+ "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz",
+ "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz",
+ "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz",
+ "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz",
+ "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz",
+ "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz",
+ "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz",
+ "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@fahrenheit/lexicons": {
+ "resolved": "packages/lexicons",
+ "link": true
+ },
+ "node_modules/@img/colour": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
+ "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.2.tgz",
+ "integrity": "sha512-eEieHsMksAW4IiO5NzauESRl2D2qz3J/kwUxUrSfV06A93eEaRfMpHXyUb1mAqrR7i8U9A0GRqE9pjn6u1Jjpg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.3.1"
+ }
+ },
+ "node_modules/@img/sharp-darwin-x64": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.2.tgz",
+ "integrity": "sha512-BaktuGPCeHJMARpodR8jK4uKiZrPAy9WrfQW0sdI37clracq8Bp01AYS3SZgi5FS/y5twa9t4+LIuuxQjqRrWw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.3.1"
+ }
+ },
+ "node_modules/@img/sharp-freebsd-wasm32": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.2.tgz",
+ "integrity": "sha512-YoAxdnd8hPUkvLHd3bWY+YA8nw3xM/RyRopYucNsWHVSan8NLVM3X2volsfoRDcXdUJPg6tXahSd7HXPK7lRnw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "dependencies": {
+ "@img/sharp-wasm32": "0.35.2"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.1.tgz",
+ "integrity": "sha512-4V/M3roRMTYjiwZY9IOVQOE8OyeCxFAkYmyZDrZl51uOKjibm3oeEJ4WAmLxutAfzFbC9jqUiPs2gbnGflH+7g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.1.tgz",
+ "integrity": "sha512-c0/DxItpJv2+dGhgycJBBgotdqruGYDvA79drdh0MD1dFpy7JzJ/PlXwi1H4rFf0eTy8tgbI91aHDnZIceY3jQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.1.tgz",
+ "integrity": "sha512-aGGy9aWzXgHBG7HNyQPWorZthlp7+x6fDRoPAQbGO3ThcttuTyKIx3NuSHb6zb4gBNq6/yNn9f1cy9nFKS/Vmg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.1.tgz",
+ "integrity": "sha512-JznefmcK9j1JKPz8AkQDh89kjojubyfOasWBPKfzMIhPwsgDy9evpE/naJTXXXmghS1iFwR8u/kTwh/I2/+GCw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-ppc64": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.1.tgz",
+ "integrity": "sha512-1EkwGNCZk6iWNCMWqrvdJ+r1j0PT1zIz60CNPhYnJlK/zyeWqlsPZIe+ocBVqPF8k/Ssee/NCk+tE9Ryrko6ng==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-riscv64": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.1.tgz",
+ "integrity": "sha512-Ilays+w2bXdnxzxtQdmXR62u8o8GYa3eL4+Gr+1KiE4xperMZUslRaVPJwwPkzlHEjGfXAfRVAa/7CYCtSqsBw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.1.tgz",
+ "integrity": "sha512-VfBwVHQTbRoj4XlpA/KLZ7ltgMpz+4WSejFzQ+GnoImjo1PtEJ59QB2qR1xQEeRPYIkNrPIm2L4cICMvz4C2ew==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.1.tgz",
+ "integrity": "sha512-+c8ukgwU62DS54nCAjw7keOfHUkmr0B5QHEdcOqRnodF/MNXJbVI8Eopoj4B/0H8Asr65I+A4Amrn7a85/md6A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.1.tgz",
+ "integrity": "sha512-qlKb/pwbkAi1WMsJrYHk7CuDrd12s27U2QnRhFYUoJNrRCmkosMTttuRFat/DDB3IlDm5qE1TJgZ4JDnHX8Ldw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.1.tgz",
+ "integrity": "sha512-yO21HwoUVLN8Qa+/SBjQLMYwBWAVJjeGPNe+hc0OUeMeifEtJqu5a1c4HayE1nNpDih9y3/KkoltfkDodmKAlg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.2.tgz",
+ "integrity": "sha512-SE4kzF2mepn6z+6E7L6lsV8FzuLL6IPQdyX8ZiwROAG/G8td+hP/m7FsFPwidtrF19gvajuC9l6TxAVcsA4S7A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.3.1"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm64": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.2.tgz",
+ "integrity": "sha512-af12Pnd0ZGu2HfP8NayB0kk6eC/lrfbQE6HlR4jD+34wdJ1Vw9TF6TMn6ZvffT+WgqVsl0hRbmNvz2u/23VmwA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.3.1"
+ }
+ },
+ "node_modules/@img/sharp-linux-ppc64": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.2.tgz",
+ "integrity": "sha512-hYSBm7zcNtDCozCxQHYZJiu63b/bXsgRZuOxCIBZsStMM9Vap47iFHdbX4kCvQsblPB/k+clhELpdQJHQLSHvg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-ppc64": "1.3.1"
+ }
+ },
+ "node_modules/@img/sharp-linux-riscv64": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.2.tgz",
+ "integrity": "sha512-qQt0Kc13+Hoan/Awq/qMSQw3L+RI1NCRPgD5cUJ/1WSSmIoysLOc72jlRM3E0OHN9Yr313jgeQ2T+zW+F03QFA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-riscv64": "1.3.1"
+ }
+ },
+ "node_modules/@img/sharp-linux-s390x": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.2.tgz",
+ "integrity": "sha512-E4fLLfRPzDLlEeDaTzI98OFLcv++WL5ChLLMwPoVd0CIoZQqupBSNbOisPL5am9XsbQ9T84+iiMpUvbFtkunbA==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.3.1"
+ }
+ },
+ "node_modules/@img/sharp-linux-x64": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.2.tgz",
+ "integrity": "sha512-gi0zFJJRLswfCZmHtJdikXPOc5u7qamSOS3NHedLqLd4W8Q0NqjdBr6TTRIgsfFjqfTsHFgdfvJ9LwqSgcHiAA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.3.1"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.2.tgz",
+ "integrity": "sha512-siWbOW1u6HFnFLrp0waKyW7VEf7jYvcDWdrXEFa8AkdAQgEvuu5Fz8/Y70w9EeqAdwDtfU012BhEHHaDqvQNzg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.1"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.2.tgz",
+ "integrity": "sha512-YBqMMcjDi4QGYiSn4vNOYBhmlC4z5AXqkOUUqI2e0AFA4urNv4ESgOgwNl3K+4etQhha0twXlzeF20bbULm9Yg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.3.1"
+ }
+ },
+ "node_modules/@img/sharp-wasm32": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.2.tgz",
+ "integrity": "sha512-Mrv4JQNYVQ94xH+jzZ9r+gowleN8mv2FTgKT+PI6bx5C0G8TdNYndu161pg2i7uoBwxy2ImPMHrJOM2LZef7Bw==",
+ "dev": true,
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.11.1"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-webcontainers-wasm32": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.2.tgz",
+ "integrity": "sha512-QNV27pxs9wpApEiCfvHM1RDoP1w1+2KrUWWDPEhEwg+latvOrfuhWrHWZKwdSFwU6jh3myjw/yOCRsUIuOft3g==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@img/sharp-wasm32": "0.35.2"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-arm64": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.2.tgz",
+ "integrity": "sha512-BiVRYc/t6/Vl3e1hBx0hugG4oN9Pydf4fgMSpxTQJmwGUg/YoXTWHiFeRymHfCZzifxu4F4rpk/I67D0LQ20wQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-ia32": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.2.tgz",
+ "integrity": "sha512-YYEhx9PImCC7T0tI8JDMi4DB9LwLCXCU5OWNYEXAxh5Q1ShKkyC6byxzoBJ3gEFDnH2lQckWuDe70G7mB2XJog==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-x64": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.2.tgz",
+ "integrity": "sha512-imoOyBcoM/iiUr4J6VPpCNjPnjvP/Gks95898yB8YqoGGYmHYbOyCuNv9FMhFgtaiHFGbHW8bxKqRV6VjtXThQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@oxc-project/types": {
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.142.0.tgz",
+ "integrity": "sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/Boshen"
+ }
+ },
+ "node_modules/@polka/url": {
+ "version": "1.0.0-next.29",
+ "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
+ "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@poppinss/colors": {
+ "version": "4.1.6",
+ "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz",
+ "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^4.1.5"
+ }
+ },
+ "node_modules/@poppinss/dumper": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz",
+ "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@poppinss/colors": "^4.1.5",
+ "@sindresorhus/is": "^7.0.2",
+ "supports-color": "^10.0.0"
+ }
+ },
+ "node_modules/@poppinss/exception": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz",
+ "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@rolldown/binding-android-arm64": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.2.tgz",
+ "integrity": "sha512-l7x215OGvo1s52JWmR8U/DAVzEDWBCIbTm28aeJV/WDTSHgcKXaZTuBT0hJMs5NggilfJTW3clZVvd24yfKJxA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-arm64": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.2.tgz",
+ "integrity": "sha512-9u9Xv6c1AJZT0FfwH5vrMG5Jjcwhc1MlyrPu0XfTqkzsmqfks2M6W/o5XwAJgVVN/jHpqqngC1WevHKKTIUtIA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-x64": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.2.tgz",
+ "integrity": "sha512-9W1mbGZAfW3oqd85bhBkmpyHCCzL1TeG/zFFP3vg7b0rlly8cxOcre5nXwz+LHazCwac2MNWgPdPCHndABjpWQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-freebsd-x64": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.2.tgz",
+ "integrity": "sha512-0p1lhiCSCyaerFwtrdZQUx7NqGk6LQnaRKWX7tFQqwQgvX0rjM15cIkm3pax1UpEakK14C4mOxx/jSqCBdBRqQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.2.tgz",
+ "integrity": "sha512-e+cOJXrJ2L3zx6YzqPg+f6Wbk3V1cKB8bOhbaYdVYN3DdquzNdRAmrbETz1qnt5yp/c7JNlNjmITiA2cVneQ7w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-gnu": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.2.tgz",
+ "integrity": "sha512-JsSMsj6sNat/MuhG5fnBD7QgbtpHKVe30x5/bAVirDHdhoQRXJkF6xc0Jqk8O4fiCUQAzMOoH9wZi3m60c8wtg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-musl": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.2.tgz",
+ "integrity": "sha512-B5G/zJdHaoJn9vD50eGHWkiWfmq8Uhi3IiLPJTzmZTrAalk1bztUikSXo0qga18ibE0IXboyeMUnhPjhAJ45wQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-ppc64-gnu": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.2.tgz",
+ "integrity": "sha512-6mC/awzKka8W6EoekjegpfGkjz8jXWDX63pqu/HYVpyKtZfu65Jsh4QAH3Kej3CAv/c1oGX7psTmFEbr0mDxLA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-s390x-gnu": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.2.tgz",
+ "integrity": "sha512-412MX9fJLdA1IK28EZnc8jYv2HRTleOZgfLQumJ5zy7OeJLZlg/CETwFaXjNmGVxG51cFHpKLqb5LKvBC+HsHA==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-gnu": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.2.tgz",
+ "integrity": "sha512-Q/+HI/ToJafZ1iCqGgVQXUEkIjufHCTF0gBQ2a5o3cg7GJ2h0qyq3nvvSmU+bGda2/7ygXpTY4TM6gO9OhQ0ZA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-musl": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.2.tgz",
+ "integrity": "sha512-ZKp/w41n6wCvxzxQHtQSbuphfX3Y4cCvbjkKHusrLx4lh+JWLTU7StSltO/DKARISzbj368d+qUaCjI8K2wzXw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-openharmony-arm64": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.2.tgz",
+ "integrity": "sha512-pxE6xD4KS3eAROkKK5yrhB9/3+vhlhVGMvlQLbdpzrBGDbKrnzx3RLwPaHvasLo6jgaiBLn7e04Df9C4tYhjmA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-arm64-msvc": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.2.tgz",
+ "integrity": "sha512-4MqEue5re+xIZzAWsB8sj0P1kqZySWqIuN4t6QaIO/YA6SFwySOLruvWQFzfmqk8LBK2P30KCSJwf6mJCZZ5/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-x64-msvc": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.2.tgz",
+ "integrity": "sha512-NweNxxD0Nf9t8v7kodun45Ijp3EIwYY+uydPP6qBEYvfBqhIjN6dZMzlQja3tqX/aLs3F3Uz+AxDpKgRhpOZQg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz",
+ "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@sindresorhus/is": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz",
+ "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/is?sponsor=1"
+ }
+ },
+ "node_modules/@speed-highlight/core": {
+ "version": "1.2.23",
+ "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.23.tgz",
+ "integrity": "sha512-iRoq6i6JDJP6Mt2A5JaPvzw0pgYHH6k92ij+yXiTrB7T2y9N789aWE3EHWj/5ztlJBokcCBja3iYLVdu5wgnkg==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/@standard-schema/spec": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
+ "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@sveltejs/acorn-typescript": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.11.tgz",
+ "integrity": "sha512-LFuZUkjJ9iF7JZye/aG5XM0SFcQ5VyL0oVX4WJ9dc0Va3R3s0OauX1BESVCb+YN/ol8TAfqGDDAQsTG627Y5kw==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^8.9.0"
+ }
+ },
+ "node_modules/@sveltejs/adapter-cloudflare": {
+ "version": "7.2.9",
+ "resolved": "https://registry.npmjs.org/@sveltejs/adapter-cloudflare/-/adapter-cloudflare-7.2.9.tgz",
+ "integrity": "sha512-LEfLRYKZIiNYBPYk9Cu4dFCCIX37NO96jESNRDv7yr3vvblKU4Yh05FPUMRSrOWFKtG6bJcGIvdG/M2DSf4D1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cloudflare/workers-types": "^4.20250507.0",
+ "worktop": "0.8.0-next.18"
+ },
+ "peerDependencies": {
+ "@sveltejs/kit": "^2.0.0",
+ "wrangler": "^4.0.0"
+ }
+ },
+ "node_modules/@sveltejs/adapter-cloudflare/node_modules/@cloudflare/workers-types": {
+ "version": "4.20260702.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260702.1.tgz",
+ "integrity": "sha512-mOhf5TUEB1m2vPrxtqoIGfz0fUC9xyxRDx5gWHy5s+OCo6dcV+g7wI1R7gYCMFohhqF/2y2xeKVwMwCJjfn/WA==",
+ "dev": true,
+ "license": "MIT OR Apache-2.0"
+ },
+ "node_modules/@sveltejs/kit": {
+ "version": "2.70.2",
+ "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.70.2.tgz",
+ "integrity": "sha512-RzRoRpuR2KXqc5yMO0akQHDZeT4AslOlznGITURsqHaVbtyYP4Wn3eE3gxj9JcDyNYO0crkxhdwFHc+2vkVm6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@standard-schema/spec": "^1.0.0",
+ "@sveltejs/acorn-typescript": "^1.0.9",
+ "@types/cookie": "^0.6.0",
+ "acorn": "^8.16.0",
+ "cookie": "^0.6.0",
+ "devalue": "^5.8.1",
+ "esm-env": "^1.2.2",
+ "kleur": "^4.1.5",
+ "magic-string": "^0.30.5",
+ "mrmime": "^2.0.0",
+ "set-cookie-parser": "^3.0.0",
+ "sirv": "^3.0.0"
+ },
+ "bin": {
+ "svelte-kit": "svelte-kit.js"
+ },
+ "engines": {
+ "node": ">=18.13"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0",
+ "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0",
+ "svelte": "^4.0.0 || ^5.0.0-next.0",
+ "typescript": "^5.3.3 || ^6.0.0",
+ "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@sveltejs/load-config": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@sveltejs/load-config/-/load-config-0.2.1.tgz",
+ "integrity": "sha512-5m3B2cbqQ4TbwW6Xkh66Ntw6dD7gNc77cCxABTTesWcq9jxIzMgTk97pZx5vEtvQx8iokgi7GIphqZe+PGwcZA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 18.0.0"
+ }
+ },
+ "node_modules/@sveltejs/vite-plugin-svelte": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-7.2.0.tgz",
+ "integrity": "sha512-1SpkuMSRLfugrVX+IrKfE1RUegzo8AQzKQ6qQPfVzbcWi5IhuTPaKb5ZrLpucleFznkc4/RTeSPoRnGWFxX+EQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deepmerge": "^4.3.1",
+ "magic-string": "^0.30.21",
+ "obug": "^2.1.0",
+ "vitefu": "^1.1.2"
+ },
+ "engines": {
+ "node": "^20.19 || ^22.12 || >=24"
+ },
+ "peerDependencies": {
+ "svelte": "^5.46.4",
+ "vite": "^8.0.0-beta.7 || ^8.0.0"
+ }
+ },
+ "node_modules/@types/chai": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
+ "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/deep-eql": "*",
+ "assertion-error": "^2.0.1"
+ }
+ },
+ "node_modules/@types/cookie": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/deep-eql": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
+ "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@vitest/expect": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz",
+ "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@standard-schema/spec": "^1.1.0",
+ "@types/chai": "^5.2.2",
+ "@vitest/spy": "4.1.10",
+ "@vitest/utils": "4.1.10",
+ "chai": "^6.2.2",
+ "tinyrainbow": "^3.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/mocker": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz",
+ "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/spy": "4.1.10",
+ "estree-walker": "^3.0.3",
+ "magic-string": "^0.30.21"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "msw": "^2.4.9",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "msw": {
+ "optional": true
+ },
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vitest/pretty-format": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz",
+ "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyrainbow": "^3.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/runner": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz",
+ "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/utils": "4.1.10",
+ "pathe": "^2.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/snapshot": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz",
+ "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "4.1.10",
+ "@vitest/utils": "4.1.10",
+ "magic-string": "^0.30.21",
+ "pathe": "^2.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/spy": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz",
+ "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/utils": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz",
+ "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "4.1.10",
+ "convert-source-map": "^2.0.0",
+ "tinyrainbow": "^3.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
+ "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/aria-query": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz",
+ "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/assertion-error": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/blake3-wasm": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz",
+ "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/chai": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
+ "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
+ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "readdirp": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cookie": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/core-js": {
+ "version": "3.49.0",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz",
+ "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/devalue": {
+ "version": "5.9.0",
+ "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.9.0.tgz",
+ "integrity": "sha512-RWrqdArjvPbsATEhOPUo6Wndc/iWnkWKlhIrdlF3zMMYo/c3CVtoaVAyLtWxz5h8nSlkHzxnzV2uLydPXmtF+A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/error-stack-parser-es": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz",
+ "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz",
+ "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/esbuild": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
+ "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.28.1",
+ "@esbuild/android-arm": "0.28.1",
+ "@esbuild/android-arm64": "0.28.1",
+ "@esbuild/android-x64": "0.28.1",
+ "@esbuild/darwin-arm64": "0.28.1",
+ "@esbuild/darwin-x64": "0.28.1",
+ "@esbuild/freebsd-arm64": "0.28.1",
+ "@esbuild/freebsd-x64": "0.28.1",
+ "@esbuild/linux-arm": "0.28.1",
+ "@esbuild/linux-arm64": "0.28.1",
+ "@esbuild/linux-ia32": "0.28.1",
+ "@esbuild/linux-loong64": "0.28.1",
+ "@esbuild/linux-mips64el": "0.28.1",
+ "@esbuild/linux-ppc64": "0.28.1",
+ "@esbuild/linux-riscv64": "0.28.1",
+ "@esbuild/linux-s390x": "0.28.1",
+ "@esbuild/linux-x64": "0.28.1",
+ "@esbuild/netbsd-arm64": "0.28.1",
+ "@esbuild/netbsd-x64": "0.28.1",
+ "@esbuild/openbsd-arm64": "0.28.1",
+ "@esbuild/openbsd-x64": "0.28.1",
+ "@esbuild/openharmony-arm64": "0.28.1",
+ "@esbuild/sunos-x64": "0.28.1",
+ "@esbuild/win32-arm64": "0.28.1",
+ "@esbuild/win32-ia32": "0.28.1",
+ "@esbuild/win32-x64": "0.28.1"
+ }
+ },
+ "node_modules/esm-env": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
+ "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/esrap": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.3.0.tgz",
+ "integrity": "sha512-GQ/7RN8uOtEfNpzZzBMTzW9JBcX42oaSVtPzdF+6cEL8pqIL094iUpr9jzYGn4O4P/1S60dJ6izyT8F4LYARng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.4.15"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/types": "^8.2.0"
+ },
+ "peerDependenciesMeta": {
+ "@typescript-eslint/types": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
+ "node_modules/expect-type": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz",
+ "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/ipaddr.js": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.4.0.tgz",
+ "integrity": "sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/is-reference": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
+ "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.6"
+ }
+ },
+ "node_modules/iso-datestring-validator": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/iso-datestring-validator/-/iso-datestring-validator-2.2.2.tgz",
+ "integrity": "sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==",
+ "license": "MIT"
+ },
+ "node_modules/jose": {
+ "version": "5.10.0",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz",
+ "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/lightningcss": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz",
+ "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.33.0",
+ "lightningcss-darwin-arm64": "1.33.0",
+ "lightningcss-darwin-x64": "1.33.0",
+ "lightningcss-freebsd-x64": "1.33.0",
+ "lightningcss-linux-arm-gnueabihf": "1.33.0",
+ "lightningcss-linux-arm64-gnu": "1.33.0",
+ "lightningcss-linux-arm64-musl": "1.33.0",
+ "lightningcss-linux-x64-gnu": "1.33.0",
+ "lightningcss-linux-x64-musl": "1.33.0",
+ "lightningcss-win32-arm64-msvc": "1.33.0",
+ "lightningcss-win32-x64-msvc": "1.33.0"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz",
+ "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz",
+ "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz",
+ "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz",
+ "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz",
+ "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz",
+ "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz",
+ "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz",
+ "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz",
+ "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz",
+ "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz",
+ "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/locate-character": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
+ "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/miniflare": {
+ "version": "5.20260730.0-alpha",
+ "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-5.20260730.0-alpha.tgz",
+ "integrity": "sha512-8/dspSXDshP6nSkCpjKO7BYc2qZoYSXm7iM+QxY7qJyJpAB3onnQSaiu0cvKJlfuMGwULl55hG69FJCcCMXU1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cspotcode/source-map-support": "0.8.1",
+ "sharp": "0.35.2",
+ "undici": "7.28.0",
+ "workerd": "1.20260730.1",
+ "ws": "8.21.0",
+ "youch": "4.1.0-beta.10"
+ },
+ "engines": {
+ "node": ">=22.0.0"
+ }
+ },
+ "node_modules/mri": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
+ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mrmime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
+ "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/multiformats": {
+ "version": "13.4.2",
+ "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.4.2.tgz",
+ "integrity": "sha512-eh6eHCrRi1+POZ3dA+Dq1C6jhP1GNtr9CRINMb67OKzqW9I5DUuZM/3jLPlzhgpGeiNUlEGEbkCYChXMCc/8DQ==",
+ "license": "Apache-2.0 OR MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.17",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz",
+ "integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/obug": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz",
+ "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==",
+ "dev": true,
+ "funding": [
+ "https://github.com/sponsors/sxzz",
+ "https://opencollective.com/debug"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/path-to-regexp": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
+ "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/pathe": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.25",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz",
+ "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.16",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
+ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.18.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/regexparam": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/regexparam/-/regexparam-3.0.0.tgz",
+ "integrity": "sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/rolldown": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.2.tgz",
+ "integrity": "sha512-opwpo1tQBAcpSUJDt94B7hhLNGOKjCdE//XXjeLrnx9b83bjnw45tXdg1b09yEw/VLFBJGZpwRULMmOZo7ol+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oxc-project/types": "=0.142.0",
+ "@rolldown/pluginutils": "^1.0.0"
+ },
+ "bin": {
+ "rolldown": "bin/cli.mjs"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "optionalDependencies": {
+ "@rolldown/binding-android-arm64": "1.2.2",
+ "@rolldown/binding-darwin-arm64": "1.2.2",
+ "@rolldown/binding-darwin-x64": "1.2.2",
+ "@rolldown/binding-freebsd-x64": "1.2.2",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.2.2",
+ "@rolldown/binding-linux-arm64-gnu": "1.2.2",
+ "@rolldown/binding-linux-arm64-musl": "1.2.2",
+ "@rolldown/binding-linux-ppc64-gnu": "1.2.2",
+ "@rolldown/binding-linux-s390x-gnu": "1.2.2",
+ "@rolldown/binding-linux-x64-gnu": "1.2.2",
+ "@rolldown/binding-linux-x64-musl": "1.2.2",
+ "@rolldown/binding-openharmony-arm64": "1.2.2",
+ "@rolldown/binding-win32-arm64-msvc": "1.2.2",
+ "@rolldown/binding-win32-x64-msvc": "1.2.2"
+ }
+ },
+ "node_modules/sade": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
+ "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mri": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/set-cookie-parser": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.1.2.tgz",
+ "integrity": "sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/sharp": {
+ "version": "0.35.2",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.2.tgz",
+ "integrity": "sha512-FVtFjtBCMiJS6yb5CX7Sop45WFMpeGw6oRKuJnXYgf/f1ms/D7LE/ZUSNxnW7rZ/dbslQWYkoqFHGPaDBtaK4w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@img/colour": "^1.1.0",
+ "detect-libc": "^2.1.2",
+ "semver": "^7.8.4"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.35.2",
+ "@img/sharp-darwin-x64": "0.35.2",
+ "@img/sharp-freebsd-wasm32": "0.35.2",
+ "@img/sharp-libvips-darwin-arm64": "1.3.1",
+ "@img/sharp-libvips-darwin-x64": "1.3.1",
+ "@img/sharp-libvips-linux-arm": "1.3.1",
+ "@img/sharp-libvips-linux-arm64": "1.3.1",
+ "@img/sharp-libvips-linux-ppc64": "1.3.1",
+ "@img/sharp-libvips-linux-riscv64": "1.3.1",
+ "@img/sharp-libvips-linux-s390x": "1.3.1",
+ "@img/sharp-libvips-linux-x64": "1.3.1",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.1",
+ "@img/sharp-libvips-linuxmusl-x64": "1.3.1",
+ "@img/sharp-linux-arm": "0.35.2",
+ "@img/sharp-linux-arm64": "0.35.2",
+ "@img/sharp-linux-ppc64": "0.35.2",
+ "@img/sharp-linux-riscv64": "0.35.2",
+ "@img/sharp-linux-s390x": "0.35.2",
+ "@img/sharp-linux-x64": "0.35.2",
+ "@img/sharp-linuxmusl-arm64": "0.35.2",
+ "@img/sharp-linuxmusl-x64": "0.35.2",
+ "@img/sharp-webcontainers-wasm32": "0.35.2",
+ "@img/sharp-win32-arm64": "0.35.2",
+ "@img/sharp-win32-ia32": "0.35.2",
+ "@img/sharp-win32-x64": "0.35.2"
+ }
+ },
+ "node_modules/siginfo": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
+ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/sirv": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz",
+ "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@polka/url": "^1.0.0-next.24",
+ "mrmime": "^2.0.0",
+ "totalist": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stackback": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
+ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/std-env": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz",
+ "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/supports-color": {
+ "version": "10.2.2",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz",
+ "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/svelte": {
+ "version": "5.56.8",
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.56.8.tgz",
+ "integrity": "sha512-PY8LOw7xP6c8IOiVqdo0sbbZVYhXRSfklOQLAUyGBKqjTX0wx/z4l/9J+PmBpmlLnxzEb1NqltxQ5/wZme/Cmg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/remapping": "^2.3.4",
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@sveltejs/acorn-typescript": "^1.0.10",
+ "@types/estree": "^1.0.5",
+ "@types/trusted-types": "^2.0.7",
+ "acorn": "^8.12.1",
+ "aria-query": "5.3.1",
+ "axobject-query": "^4.1.0",
+ "clsx": "^2.1.1",
+ "devalue": "^5.8.1",
+ "esm-env": "^1.2.1",
+ "esrap": "^2.2.12",
+ "is-reference": "^3.0.3",
+ "locate-character": "^3.0.0",
+ "magic-string": "^0.30.11",
+ "zimmerframe": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/svelte-check": {
+ "version": "4.7.4",
+ "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.7.4.tgz",
+ "integrity": "sha512-IW9ot9YqAoyv8FvyN+eb4ZTe8zgcKZrJLNYU6dzSKkGwEBsSPc4K7lmQ8bKn8W2YMXM6WDfZSSVOaGtekyUfOQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "@sveltejs/load-config": "^0.2.1",
+ "chokidar": "^4.0.1",
+ "fdir": "^6.2.0",
+ "picocolors": "^1.0.0",
+ "sade": "^1.7.4"
+ },
+ "bin": {
+ "svelte-check": "bin/svelte-check"
+ },
+ "engines": {
+ "node": ">= 18.0.0"
+ },
+ "peerDependencies": {
+ "svelte": "^4.0.0 || ^5.0.0-next.0",
+ "typescript": "^5.0.0 || ^6.0.0"
+ }
+ },
+ "node_modules/tinybench": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
+ "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tinyexec": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz",
+ "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyrainbow": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz",
+ "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/totalist": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
+ "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
+ "node_modules/typescript": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
+ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz",
+ "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.18.1"
+ }
+ },
+ "node_modules/undici_v6": {
+ "name": "undici",
+ "version": "6.28.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz",
+ "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.17"
+ }
+ },
+ "node_modules/undici_v7": {
+ "name": "undici",
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz",
+ "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.18.1"
+ }
+ },
+ "node_modules/undici_v8": {
+ "name": "undici",
+ "version": "8.10.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.0.tgz",
+ "integrity": "sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=22.19.0"
+ }
+ },
+ "node_modules/unenv": {
+ "version": "2.0.0-rc.24",
+ "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz",
+ "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pathe": "^2.0.3"
+ }
+ },
+ "node_modules/unicode-segmenter": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/unicode-segmenter/-/unicode-segmenter-0.14.5.tgz",
+ "integrity": "sha512-jHGmj2LUuqDcX3hqY12Ql+uhUTn8huuxNZGq7GvtF6bSybzH3aFgedYu/KTzQStEgt1Ra2F3HxadNXsNjb3m3g==",
+ "license": "MIT"
+ },
+ "node_modules/vite": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.0.tgz",
+ "integrity": "sha512-pn+CFpM0lwDeKwmOq1ZaBK/9sjorZcgqxki6MbY/jPEVd9vichIlmlD4HmQ5wdP5EgqQCFRaACBxMC7uEGc6lQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "lightningcss": "^1.33.0",
+ "picomatch": "^4.0.5",
+ "postcss": "^8.5.23",
+ "rolldown": "~1.2.0",
+ "tinyglobby": "^0.2.17"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "@vitejs/devtools": "^0.4.0",
+ "esbuild": "^0.27.0 || ^0.28.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "@vitejs/devtools": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vitefu": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz",
+ "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==",
+ "dev": true,
+ "license": "MIT",
+ "workspaces": [
+ "tests/deps/*",
+ "tests/projects/*",
+ "tests/projects/workspace/packages/*"
+ ],
+ "peerDependencies": {
+ "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vitest": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz",
+ "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/expect": "4.1.10",
+ "@vitest/mocker": "4.1.10",
+ "@vitest/pretty-format": "4.1.10",
+ "@vitest/runner": "4.1.10",
+ "@vitest/snapshot": "4.1.10",
+ "@vitest/spy": "4.1.10",
+ "@vitest/utils": "4.1.10",
+ "es-module-lexer": "^2.0.0",
+ "expect-type": "^1.3.0",
+ "magic-string": "^0.30.21",
+ "obug": "^2.1.1",
+ "pathe": "^2.0.3",
+ "picomatch": "^4.0.3",
+ "std-env": "^4.0.0-rc.1",
+ "tinybench": "^2.9.0",
+ "tinyexec": "^1.0.2",
+ "tinyglobby": "^0.2.15",
+ "tinyrainbow": "^3.1.0",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0",
+ "why-is-node-running": "^2.3.0"
+ },
+ "bin": {
+ "vitest": "vitest.mjs"
+ },
+ "engines": {
+ "node": "^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "@edge-runtime/vm": "*",
+ "@opentelemetry/api": "^1.9.0",
+ "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
+ "@vitest/browser-playwright": "4.1.10",
+ "@vitest/browser-preview": "4.1.10",
+ "@vitest/browser-webdriverio": "4.1.10",
+ "@vitest/coverage-istanbul": "4.1.10",
+ "@vitest/coverage-v8": "4.1.10",
+ "@vitest/ui": "4.1.10",
+ "happy-dom": "*",
+ "jsdom": "*",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@edge-runtime/vm": {
+ "optional": true
+ },
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@types/node": {
+ "optional": true
+ },
+ "@vitest/browser-playwright": {
+ "optional": true
+ },
+ "@vitest/browser-preview": {
+ "optional": true
+ },
+ "@vitest/browser-webdriverio": {
+ "optional": true
+ },
+ "@vitest/coverage-istanbul": {
+ "optional": true
+ },
+ "@vitest/coverage-v8": {
+ "optional": true
+ },
+ "@vitest/ui": {
+ "optional": true
+ },
+ "happy-dom": {
+ "optional": true
+ },
+ "jsdom": {
+ "optional": true
+ },
+ "vite": {
+ "optional": false
+ }
+ }
+ },
+ "node_modules/web": {
+ "resolved": "apps/web",
+ "link": true
+ },
+ "node_modules/why-is-node-running": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
+ "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "siginfo": "^2.0.0",
+ "stackback": "0.0.2"
+ },
+ "bin": {
+ "why-is-node-running": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/workerd": {
+ "version": "1.20260730.1",
+ "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260730.1.tgz",
+ "integrity": "sha512-zmfNIjwYSWFY5chGBOjWtH3xAE7p97FTC6vR4Ep98290ho6AeAR/NVcBD274YCLEUYzqm8yxdtZlxMybU8a3jA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "workerd": "bin/workerd"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "optionalDependencies": {
+ "@cloudflare/workerd-darwin-64": "1.20260730.1",
+ "@cloudflare/workerd-darwin-arm64": "1.20260730.1",
+ "@cloudflare/workerd-linux-64": "1.20260730.1",
+ "@cloudflare/workerd-linux-arm64": "1.20260730.1",
+ "@cloudflare/workerd-windows-64": "1.20260730.1"
+ }
+ },
+ "node_modules/worktop": {
+ "version": "0.8.0-next.18",
+ "resolved": "https://registry.npmjs.org/worktop/-/worktop-0.8.0-next.18.tgz",
+ "integrity": "sha512-+TvsA6VAVoMC3XDKR5MoC/qlLqDixEfOBysDEKnPIPou/NvoPWCAuXHXMsswwlvmEuvX56lQjvELLyLuzTKvRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mrmime": "^2.0.0",
+ "regexparam": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/wrangler": {
+ "version": "4.118.0",
+ "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.118.0.tgz",
+ "integrity": "sha512-9pkBw/b8zWqGx2S+oLhgHMR1M/4VOE8SynUFABnGWiSFGlcOQ4xiI/B71Xf66RYP2xzngU37IQFPtUruij3lYw==",
+ "dev": true,
+ "license": "MIT OR Apache-2.0",
+ "dependencies": {
+ "@cloudflare/kv-asset-handler": "0.5.0",
+ "@cloudflare/unenv-preset": "2.16.1",
+ "blake3-wasm": "2.1.5",
+ "esbuild": "0.28.1",
+ "miniflare": "5.20260730.0-alpha",
+ "path-to-regexp": "6.3.0",
+ "unenv": "2.0.0-rc.24",
+ "workerd": "1.20260730.1"
+ },
+ "bin": {
+ "cf-wrangler": "bin/cf-wrangler.js",
+ "wrangler": "bin/wrangler.js",
+ "wrangler2": "bin/wrangler.js"
+ },
+ "engines": {
+ "node": ">=22.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.3"
+ },
+ "peerDependencies": {
+ "@cloudflare/workers-types": "^5.20260730.1"
+ },
+ "peerDependenciesMeta": {
+ "@cloudflare/workers-types": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ws": {
+ "version": "8.21.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz",
+ "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/youch": {
+ "version": "4.1.0-beta.10",
+ "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz",
+ "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@poppinss/colors": "^4.1.5",
+ "@poppinss/dumper": "^0.6.4",
+ "@speed-highlight/core": "^1.2.7",
+ "cookie": "^1.0.2",
+ "youch-core": "^0.3.3"
+ }
+ },
+ "node_modules/youch-core": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz",
+ "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@poppinss/exception": "^1.2.2",
+ "error-stack-parser-es": "^1.0.5"
+ }
+ },
+ "node_modules/youch/node_modules/cookie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
+ "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/zimmerframe": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz",
+ "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/zod": {
+ "version": "3.25.76",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "packages/lexicons": {
+ "name": "@fahrenheit/lexicons",
+ "version": "0.0.1",
+ "dependencies": {
+ "@atproto/lexicon": "^0.7.10"
+ },
+ "devDependencies": {
+ "typescript": "^6.0.3",
+ "vitest": "^4.1.10"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..6be50b0
--- /dev/null
+++ b/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "fahrenheit",
+ "private": true,
+ "type": "module",
+ "description": "Mooring β a personal/professional website builder for the Atmosphere. Workspace root; the apps live in apps/, shared packages in packages/.",
+ "license": "AGPL-3.0-only",
+ "engines": {
+ "node": ">=22"
+ },
+ "workspaces": [
+ "apps/*",
+ "packages/*"
+ ],
+ "scripts": {
+ "dev": "npm run dev --workspace web",
+ "build": "npm run build --workspace web",
+ "check": "npm run check --workspaces --if-present",
+ "test": "npm test --workspaces --if-present"
+ }
+}
diff --git a/packages/lexicons/package.json b/packages/lexicons/package.json
new file mode 100644
index 0000000..36a0b4c
--- /dev/null
+++ b/packages/lexicons/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "@fahrenheit/lexicons",
+ "private": true,
+ "version": "0.0.1",
+ "type": "module",
+ "description": "Loader and convention tests for the page.mooring.* lexicons (source of truth: /lexicons at the repo root).",
+ "main": "src/index.ts",
+ "scripts": {
+ "test": "vitest run"
+ },
+ "dependencies": {
+ "@atproto/lexicon": "^0.7.10"
+ },
+ "devDependencies": {
+ "typescript": "^6.0.3",
+ "vitest": "^4.1.10"
+ }
+}
diff --git a/packages/lexicons/src/index.ts b/packages/lexicons/src/index.ts
new file mode 100644
index 0000000..22e7299
--- /dev/null
+++ b/packages/lexicons/src/index.ts
@@ -0,0 +1,35 @@
+import { readFileSync, readdirSync, statSync } from 'node:fs';
+import { join, relative, sep } from 'node:path';
+import { fileURLToPath } from 'node:url';
+import { parseLexiconDoc, type LexiconDoc } from '@atproto/lexicon';
+
+/** Absolute path of the repo-root lexicons/ directory (the source of truth). */
+export const lexiconsDir = fileURLToPath(new URL('../../../lexicons', import.meta.url));
+
+export interface LoadedLexicon {
+ /** Path relative to lexicons/, e.g. page/mooring/site.json */
+ relPath: string;
+ /** NSID implied by the file path, e.g. page.mooring.site */
+ pathNsid: string;
+ doc: LexiconDoc;
+}
+
+function walk(dir: string): string[] {
+ return readdirSync(dir).flatMap((name) => {
+ const full = join(dir, name);
+ if (statSync(full).isDirectory()) return walk(full);
+ return name.endsWith('.json') ? [full] : [];
+ });
+}
+
+/** Load and parse every lexicon document under lexicons/. */
+export function loadLexicons(): LoadedLexicon[] {
+ return walk(lexiconsDir)
+ .sort()
+ .map((full) => {
+ const relPath = relative(lexiconsDir, full);
+ const pathNsid = relPath.replace(/\.json$/, '').split(sep).join('.');
+ const doc = parseLexiconDoc(JSON.parse(readFileSync(full, 'utf8')));
+ return { relPath, pathNsid, doc };
+ });
+}
diff --git a/packages/lexicons/tests/conventions.test.ts b/packages/lexicons/tests/conventions.test.ts
new file mode 100644
index 0000000..6c5cecc
--- /dev/null
+++ b/packages/lexicons/tests/conventions.test.ts
@@ -0,0 +1,148 @@
+import { describe, expect, it } from 'vitest';
+import { Lexicons } from '@atproto/lexicon';
+import { loadLexicons } from '../src/index';
+
+const loaded = loadLexicons();
+const lexicons = new Lexicons(loaded.map((l) => l.doc));
+
+// Walk any JSON value, yielding every nested object.
+function* objects(value: unknown): Generator> {
+ if (Array.isArray(value)) {
+ for (const item of value) yield* objects(item);
+ } else if (value !== null && typeof value === 'object') {
+ yield value as Record;
+ for (const item of Object.values(value)) yield* objects(item);
+ }
+}
+
+describe('lexicon conventions', () => {
+ it('found the page.mooring.* documents', () => {
+ expect(loaded.map((l) => l.doc.id)).toEqual([
+ 'page.mooring.authSite',
+ 'page.mooring.page',
+ 'page.mooring.site'
+ ]);
+ });
+
+ it.each(loaded)('$relPath: NSID matches file path', ({ pathNsid, doc }) => {
+ expect(doc.id).toBe(pathNsid);
+ });
+
+ it.each(loaded)('$relPath: record defs require createdAt (format datetime)', ({ doc }) => {
+ for (const def of Object.values(doc.defs)) {
+ if (def.type !== 'record') continue;
+ expect(def.record.required).toContain('createdAt');
+ expect(def.record.properties?.createdAt).toMatchObject({
+ type: 'string',
+ format: 'datetime'
+ });
+ }
+ });
+
+ it.each(loaded)('$relPath: maxLength is 10Γ maxGraphemes wherever both appear', ({ doc }) => {
+ for (const obj of objects(doc.defs)) {
+ if (obj.type === 'string' && typeof obj.maxGraphemes === 'number') {
+ expect(obj.maxLength, JSON.stringify(obj)).toBe((obj.maxGraphemes as number) * 10);
+ }
+ }
+ });
+
+ it('authSite permissions reference only record types that exist here', () => {
+ const recordNsids = loaded
+ .filter((l) => Object.values(l.doc.defs).some((d) => d.type === 'record'))
+ .map((l) => l.doc.id);
+ const authSite = loaded.find((l) => l.doc.id === 'page.mooring.authSite')!;
+ const main = authSite.doc.defs.main as unknown as {
+ type: string;
+ permissions: { resource: string; collection?: string[] }[];
+ };
+ expect(main.type).toBe('permission-set');
+ for (const permission of main.permissions) {
+ expect(permission.resource).toBe('repo');
+ expect(permission.collection).toBeDefined();
+ for (const nsid of permission.collection!) {
+ expect(recordNsids).toContain(nsid);
+ }
+ }
+ });
+});
+
+describe('sample record validation', () => {
+ const now = '2026-08-03T12:00:00.000Z';
+
+ it('accepts an empty site record (empty record = working site)', () => {
+ expect(() =>
+ lexicons.assertValidRecord('page.mooring.site', {
+ $type: 'page.mooring.site',
+ createdAt: now
+ })
+ ).not.toThrow();
+ });
+
+ it('accepts a configured site record', () => {
+ expect(() =>
+ lexicons.assertValidRecord('page.mooring.site', {
+ $type: 'page.mooring.site',
+ name: 'Wind & Wing',
+ description: 'Notes from the airship.',
+ sections: [
+ { $type: 'page.mooring.site#heroSection', tagline: 'Moored, not anchored.' },
+ { $type: 'page.mooring.site#writingSection', limit: 10 },
+ { $type: 'page.mooring.site#careerSection', parts: ['positions', 'education'] },
+ // Open union: unknown members from other lexicons must pass.
+ { $type: 'com.example.custom#weatherSection', station: 'KSEA' }
+ ],
+ theme: {
+ preset: 'classic',
+ colors: {
+ background: { $type: 'page.mooring.site#rgb', r: 250, g: 250, b: 245 },
+ accent: { $type: 'page.mooring.site#rgb', r: 30, g: 90, b: 160 }
+ }
+ },
+ discoverable: true,
+ createdAt: now
+ })
+ ).not.toThrow();
+ });
+
+ it('accepts a markdown page record', () => {
+ expect(() =>
+ lexicons.assertValidRecord('page.mooring.page', {
+ $type: 'page.mooring.page',
+ path: '/about',
+ title: 'About',
+ content: { $type: 'page.mooring.page#markdown', text: '# Hello\n\nWind bless you.' },
+ visibility: 'public',
+ createdAt: now
+ })
+ ).not.toThrow();
+ });
+
+ it('rejects an out-of-range rgb component', () => {
+ expect(() =>
+ lexicons.assertValidRecord('page.mooring.site', {
+ $type: 'page.mooring.site',
+ theme: {
+ colors: { accent: { $type: 'page.mooring.site#rgb', r: 300, g: 0, b: 0 } }
+ },
+ createdAt: now
+ })
+ ).toThrow();
+ });
+
+ it('rejects a page without a title', () => {
+ expect(() =>
+ lexicons.assertValidRecord('page.mooring.page', {
+ $type: 'page.mooring.page',
+ path: '/about',
+ createdAt: now
+ })
+ ).toThrow();
+ });
+
+ it('rejects a site record without createdAt', () => {
+ expect(() =>
+ lexicons.assertValidRecord('page.mooring.site', { $type: 'page.mooring.site' })
+ ).toThrow();
+ });
+});
diff --git a/packages/lexicons/tsconfig.json b/packages/lexicons/tsconfig.json
new file mode 100644
index 0000000..9660de6
--- /dev/null
+++ b/packages/lexicons/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "strict": true,
+ "skipLibCheck": true,
+ "types": ["node"],
+ "noEmit": true
+ },
+ "include": ["src", "tests"]
+}