@crvouga/mockingbird-service-cloudcontrol 1.12.1 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../core/src/mount.ts", "../../../core/src/timeline.ts", "../../../sqlite/src/default.ts", "../../../sqlite/src/migrate.ts", "../../../sqlite/src/schema.ts", "../../../../node_modules/.bun/fast-xml-parser@5.11.2/node_modules/fast-xml-parser/src/util.js", "../../../../node_modules/.bun/fast-xml-parser@5.11.2/node_modules/fast-xml-parser/src/validator.js", "../../../../node_modules/.bun/@nodable+entities@3.1.0/node_modules/@nodable/entities/src/entities.js", "../../../../node_modules/.bun/@nodable+entities@3.1.0/node_modules/@nodable/entities/src/EntityDecoder.js", "../../../../node_modules/.bun/fast-xml-parser@5.11.2/node_modules/fast-xml-parser/src/xmlparser/OptionsBuilder.js", "../../../../node_modules/.bun/fast-xml-parser@5.11.2/node_modules/fast-xml-parser/src/xmlparser/xmlNode.js", "../../../../node_modules/.bun/xml-naming@0.3.0/node_modules/xml-naming/src/index.js", "../../../../node_modules/.bun/fast-xml-parser@5.11.2/node_modules/fast-xml-parser/src/xmlparser/DocTypeReader.js", "../../../../node_modules/.bun/anynum@1.0.1/node_modules/anynum/digitTable.js", "../../../../node_modules/.bun/anynum@1.0.1/node_modules/anynum/anynum.js", "../../../../node_modules/.bun/strnum@2.4.2/node_modules/strnum/strnum.js", "../../../../node_modules/.bun/fast-xml-parser@5.11.2/node_modules/fast-xml-parser/src/ignoreAttributes.js", "../../../../node_modules/.bun/path-expression-matcher@1.6.2/node_modules/path-expression-matcher/src/Expression.js", "../../../../node_modules/.bun/path-expression-matcher@1.6.2/node_modules/path-expression-matcher/src/ExpressionSet.js", "../../../../node_modules/.bun/path-expression-matcher@1.6.2/node_modules/path-expression-matcher/src/Matcher.js", "../../../../node_modules/.bun/is-unsafe@2.0.2/node_modules/is-unsafe/src/contexts/html.js", "../../../../node_modules/.bun/is-unsafe@2.0.2/node_modules/is-unsafe/src/contexts/xml.js", "../../../../node_modules/.bun/is-unsafe@2.0.2/node_modules/is-unsafe/src/contexts/svg.js", "../../../../node_modules/.bun/is-unsafe@2.0.2/node_modules/is-unsafe/src/contexts/sql.js", "../../../../node_modules/.bun/is-unsafe@2.0.2/node_modules/is-unsafe/src/contexts/shell.js", "../../../../node_modules/.bun/is-unsafe@2.0.2/node_modules/is-unsafe/src/contexts/redos.js", "../../../../node_modules/.bun/is-unsafe@2.0.2/node_modules/is-unsafe/src/contexts/nosql.js", "../../../../node_modules/.bun/is-unsafe@2.0.2/node_modules/is-unsafe/src/contexts/log.js", "../../../../node_modules/.bun/is-unsafe@2.0.2/node_modules/is-unsafe/src/contexts/sql-strict.js", "../../../../node_modules/.bun/is-unsafe@2.0.2/node_modules/is-unsafe/src/index.js", "../../../../node_modules/.bun/fast-xml-parser@5.11.2/node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js", "../../../../node_modules/.bun/fast-xml-parser@5.11.2/node_modules/fast-xml-parser/src/xmlparser/node2json.js", "../../../../node_modules/.bun/fast-xml-parser@5.11.2/node_modules/fast-xml-parser/src/xmlparser/XMLParser.js", "../../../../node_modules/.bun/fast-xml-parser@5.11.2/node_modules/fast-xml-parser/src/fxp.js", "../../core/src/aws-xml.ts", "../../core/src/collection.ts", "../../core/src/ids.ts", "../../../openapi/core/src/refs.ts", "../../../openapi/core/src/types.ts", "../../../openapi/core/src/document.ts", "../../../openapi/metadata/src/types.ts", "../../../openapi/metadata/src/read.ts", "../../../../node_modules/.bun/hono@4.13.11/node_modules/hono/dist/request/constants.js", "../../../../node_modules/.bun/hono@4.13.11/node_modules/hono/dist/utils/buffer.js", "../../../../node_modules/.bun/hono@4.13.11/node_modules/hono/dist/utils/body.js", "../../../../node_modules/.bun/hono@4.13.11/node_modules/hono/dist/utils/url.js", "../../../../node_modules/.bun/hono@4.13.11/node_modules/hono/dist/request.js", "../../../../node_modules/.bun/hono@4.13.11/node_modules/hono/dist/router/utils.js", "../../../../node_modules/.bun/hono@4.13.11/node_modules/hono/dist/router/reg-exp-router/router.js", "../../../../node_modules/.bun/hono@4.13.11/node_modules/hono/dist/router/trie-router/node.js", "../../core/src/journal.ts", "../../core/src/path.ts", "../../core/src/service.ts", "../../core/src/aws-protocol.ts", "../../core/src/clock.ts", "../../core/src/controls.ts", "../../core/src/rng.ts", "../../core/src/faults.ts", "../../core/src/latency.ts", "../../core/src/namespace-controls.ts", "../../core/src/signing.ts", "../../core/src/surface.ts", "../../core/src/control.ts", "../../core/src/credentials.ts", "../../core/src/metrics.ts", "../../core/src/outbound.ts", "../../core/src/admin-client.ts", "../../core/src/admin-ui.ts", "../../core/src/snapshot.ts", "../../core/src/state-view.ts", "../../core/src/version.ts", "../../core/src/webhooks.ts", "../../core/src/runtime.ts", "../src/generated/openapi.ts", "../src/runtime.ts", "../src/index.ts"],
4
+ "sourcesContent": ["import type { FetchAPI, FetchHandler } from \"./index.js\"\n\nconst prefixes = new WeakMap<Request, string>()\n\n/** Trusted mount metadata stays on the Request, never in a spoofable HTTP header. */\nexport const requestBaseUrl = (request: Request): string =>\n new URL(request.url).origin + (prefixes.get(request) ?? \"\")\n\nexport const forwardMountContext = (source: Request, target: Request): Request => {\n const prefix = prefixes.get(source)\n if (prefix !== undefined) prefixes.set(target, prefix)\n return target\n}\n\nexport type MountedAPI = FetchAPI & {\n readonly prefix: string\n GET: FetchHandler\n POST: FetchHandler\n PUT: FetchHandler\n PATCH: FetchHandler\n DELETE: FetchHandler\n HEAD: FetchHandler\n OPTIONS: FetchHandler\n}\n\n/** Embed a native API under an application's origin without owning another listener or state. */\nexport function mount(\n api: FetchAPI,\n path: string,\n relativePath?: (request: Request) => string,\n): MountedAPI {\n const prefix = path.replace(/\\/+$/, \"\")\n if (!/^\\/(?:[A-Za-z0-9_-]+\\/)*[A-Za-z0-9_-]+$/.test(prefix))\n throw new Error(\"mount prefix must be an absolute path of plain segments\")\n const fetch: FetchHandler = async (incoming) => {\n const url = new URL(incoming.url)\n if (url.pathname !== prefix && !url.pathname.startsWith(`${prefix}/`))\n return Response.json({ error: \"not_found\" }, { status: 404 })\n url.pathname = url.pathname.slice(prefix.length) || \"/\"\n const request = new Request(url, incoming)\n const publicPrefix = (prefixes.get(incoming) ?? \"\") + prefix\n prefixes.set(request, publicPrefix)\n const suffix = relativePath?.(request) ?? \"\"\n const response = await api.fetch(request)\n const local = (value: string) =>\n value.startsWith(\"/\") &&\n !value.startsWith(\"//\") &&\n value !== publicPrefix &&\n !value.startsWith(`${publicPrefix}/`)\n ? `${publicPrefix}${suffix && value !== suffix && !value.startsWith(`${suffix}/`) ? suffix : \"\"}${value}`\n : value\n const headers = new Headers(response.headers)\n const location = headers.get(\"location\")\n if (location) headers.set(\"location\", local(location))\n const links = headers.get(\"link\")\n if (links)\n headers.set(\n \"link\",\n links.replace(/<([^>]+)>/g, (_, value: string) => {\n const target = new URL(value, url)\n if (target.origin === url.origin) target.pathname = local(target.pathname)\n return `<${target.href}>`\n }),\n )\n const cookies = headers.getSetCookie()\n if (cookies.length) {\n headers.delete(\"set-cookie\")\n for (const cookie of cookies)\n headers.append(\n \"set-cookie\",\n cookie.replace(\n /(;\\s*Path=)(\\/[^;]*)/gi,\n (_, lead: string, value: string) => lead + local(value),\n ),\n )\n }\n if (\n incoming.method !== \"HEAD\" &&\n response.body &&\n // Media types are case-insensitive (RFC 9110 \u00A78.3.1), and whitespace may precede \";\".\n headers.get(\"content-type\")?.split(\";\")[0]?.trim().toLowerCase() === \"text/html\"\n ) {\n const html = rewriteHtml(await response.text(), local)\n headers.delete(\"content-length\")\n headers.delete(\"content-encoding\")\n headers.delete(\"etag\")\n return new Response(html, {\n status: response.status,\n statusText: response.statusText,\n headers,\n })\n }\n return new Response(incoming.method === \"HEAD\" ? null : response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n })\n }\n return {\n prefix,\n fetch,\n GET: fetch,\n POST: fetch,\n PUT: fetch,\n PATCH: fetch,\n DELETE: fetch,\n HEAD: fetch,\n OPTIONS: fetch,\n }\n}\n\n/** Rewrite root-relative URLs in the markup a mounted API serves so they stay under the mount. */\nconst rewriteHtml = (html: string, local: (value: string) => string): string =>\n html\n .replace(\n /(\\b(?:href|action|formaction|src)\\s*=\\s*[\"'])(\\/[^\"']*)([\"'])/gi,\n (_, lead: string, value: string, quote: string) => lead + local(value) + quote,\n )\n // srcset is a comma-separated list of \"url [descriptor]\" candidates.\n .replace(\n /(\\bsrcset\\s*=\\s*)([\"'])([^\"']*)\\2/gi,\n (_, lead: string, quote: string, list: string) =>\n lead +\n quote +\n list.replace(\n /(^|,)(\\s*)(\\/[^\\s,]*)/g,\n (_, comma: string, space: string, value: string) => comma + space + local(value),\n ) +\n quote,\n )\n // <meta http-equiv=\"refresh\" content=\"5; url=/path\"> navigates like a link.\n .replace(/<meta\\b[^>]*>/gi, (tag) =>\n /\\bhttp-equiv\\s*=\\s*[\"']?refresh\\b/i.test(tag)\n ? tag.replace(\n /(\\bcontent\\s*=\\s*)([\"'])(.*?)\\2/i,\n (_, lead: string, quote: string, content: string) =>\n lead +\n quote +\n content.replace(\n /^(\\s*\\d*(?:\\.\\d*)?\\s*[;,]\\s*(?:url\\s*=\\s*)?[\"']?)(\\/[^\"'\\s]*)/i,\n (_, start: string, value: string) => start + local(value),\n ) +\n quote,\n )\n : tag,\n )\n .replace(\n /(url\\(\\s*[\"']?)(\\/[^\\s)'\";]*)([\"']?\\s*\\))/gi,\n (_, lead: string, value: string, end: string) => lead + local(value) + end,\n )\n", "/** A stable identifier for a point in a {@link Timeline}. */\nexport type CheckpointId = string\n\n/** An immutable node in a timeline's checkpoint DAG. */\nexport type Checkpoint<T> = Readonly<{\n id: CheckpointId\n branch: string\n parent: CheckpointId | null\n /** Logical time supplied by the timeline's injected clock. */\n at: number\n value: T\n}>\n\nexport type TimelineOptions = {\n /** Logical clock used to stamp checkpoints. Defaults to a deterministic counter. */\n now?: () => number\n /** Maximum retained checkpoints. Branch heads are never collected. Default 1,000. */\n maxCheckpoints?: number\n /** Customize deterministic checkpoint IDs. */\n id?: (sequence: number) => CheckpointId\n}\n\nexport type CommitOptions = {\n branch?: string\n /** Parent checkpoint. Defaults to the selected branch's current head. */\n parent?: CheckpointId | null\n}\n\nexport type ForkOptions = {\n /** Checkpoint to fork from. Defaults to the main branch's head. */\n from?: CheckpointId\n}\n\nconst BRANCH_PATTERN = /^[A-Za-z0-9_.-]{1,64}$/\n\n/**\n * Small, storage-agnostic checkpoint DAG shared by service runtimes. Its values may be immutable\n * records, namespace images, or copy-on-write SQL engine snapshots.\n *\n * Values are retained by reference. Engines can therefore use persistent/COW snapshots while\n * simpler services can use immutable values. IDs and GC order are deterministic, and all IO\n * (the logical clock) is injected.\n */\nexport class Timeline<T> {\n readonly maxCheckpoints: number\n private readonly now: () => number\n private readonly makeId: (sequence: number) => CheckpointId\n private readonly nodes = new Map<CheckpointId, Checkpoint<T>>()\n private readonly heads = new Map<string, CheckpointId>()\n /** Unreferenced nodes in the exact order they became collectible. */\n private readonly evictable = new Set<CheckpointId>()\n /** Branch heads plus explicit retainers. Absent means zero. */\n private readonly references = new Map<CheckpointId, number>()\n private readonly explicitPins = new Map<CheckpointId, number>()\n private sequence = 0\n\n constructor(options: TimelineOptions = {}) {\n const max = options.maxCheckpoints ?? 1_000\n if (!Number.isSafeInteger(max) || max < 1)\n throw new RangeError(\"maxCheckpoints must be a positive integer\")\n this.maxCheckpoints = max\n this.now = options.now ?? (() => this.sequence)\n this.makeId = options.id ?? ((sequence) => `cp_${sequence.toString(36).padStart(8, \"0\")}`)\n }\n\n /** Capture a new immutable value and move `branch` to it. */\n commit(value: T, options: CommitOptions = {}): Checkpoint<T> {\n const branch = options.branch ?? \"main\"\n this.assertBranch(branch)\n const parent = options.parent === undefined ? (this.heads.get(branch) ?? null) : options.parent\n if (parent !== null && !this.nodes.has(parent)) throw new RangeError(`no checkpoint ${parent}`)\n const id = this.makeId(++this.sequence)\n if (this.nodes.has(id)) throw new RangeError(`duplicate checkpoint id ${id}`)\n const checkpoint = Object.freeze({ id, branch, parent, at: this.now(), value })\n this.nodes.set(id, checkpoint)\n this.moveHead(branch, id)\n this.collect(this.maxCheckpoints)\n return checkpoint\n }\n\n /** Create a branch pointer without copying its checkpoint value. */\n fork(branch: string, options: ForkOptions = {}): Checkpoint<T> | undefined {\n this.assertBranch(branch)\n if (this.heads.has(branch)) throw new RangeError(`branch already exists: ${branch}`)\n const from = options.from ?? this.heads.get(\"main\")\n if (from === undefined) return undefined\n const checkpoint = this.get(from)\n this.moveHead(branch, checkpoint.id)\n return checkpoint\n }\n\n /** Move a branch pointer to an existing checkpoint. */\n checkout(branch: string, id: CheckpointId): Checkpoint<T> {\n this.assertBranch(branch)\n const checkpoint = this.get(id)\n this.moveHead(branch, checkpoint.id)\n return checkpoint\n }\n\n get(id: CheckpointId): Checkpoint<T> {\n const checkpoint = this.nodes.get(id)\n if (!checkpoint) throw new RangeError(`no checkpoint ${id}`)\n return checkpoint\n }\n\n head(branch = \"main\"): Checkpoint<T> | undefined {\n const id = this.heads.get(branch)\n return id === undefined ? undefined : this.get(id)\n }\n\n hasBranch(branch: string): boolean {\n return this.heads.has(branch)\n }\n\n branches(): Readonly<Record<string, CheckpointId>> {\n return Object.freeze(\n Object.fromEntries([...this.heads].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))),\n )\n }\n\n checkpoints(): readonly Checkpoint<T>[] {\n return [...this.nodes.values()]\n }\n\n /** Number of retained checkpoints without allocating an array. */\n get size(): number {\n return this.nodes.size\n }\n\n /** Pin a checkpoint independently of branch heads (used by compatibility snapshot handles). */\n retain(id: CheckpointId): Checkpoint<T> {\n const checkpoint = this.get(id)\n this.explicitPins.set(id, (this.explicitPins.get(id) ?? 0) + 1)\n this.addReference(id)\n return checkpoint\n }\n\n /** Release one explicit pin. Branch heads remain pinned until moved or deleted. */\n release(id: CheckpointId): boolean {\n if (!this.nodes.has(id)) return false\n const pins = this.explicitPins.get(id) ?? 0\n if (pins === 0) return false\n if (pins === 1) this.explicitPins.delete(id)\n else this.explicitPins.set(id, pins - 1)\n this.removeReference(id)\n this.collect(this.maxCheckpoints)\n return true\n }\n\n deleteBranch(branch: string): boolean {\n if (branch === \"main\") throw new RangeError(\"cannot delete main branch\")\n const previous = this.heads.get(branch)\n const deleted = this.heads.delete(branch)\n if (previous !== undefined) this.removeReference(previous)\n this.collect(this.maxCheckpoints)\n return deleted\n }\n\n /**\n * Deterministically discard oldest unpinned checkpoints. Collection is O(number removed):\n * commits never scan pinned nodes or the retained history. Parents are metadata rather than a\n * storage dependency, so a retained node remains usable after pruning.\n */\n gc(max = this.maxCheckpoints): CheckpointId[] {\n if (!Number.isSafeInteger(max) || max < 1)\n throw new RangeError(\"max must be a positive integer\")\n const removed: CheckpointId[] = []\n this.collect(max, removed)\n return removed\n }\n\n private collect(max: number, removed?: CheckpointId[]): void {\n while (this.nodes.size > max && this.evictable.size > 0) {\n const id = this.evictable.values().next().value as CheckpointId\n this.evictable.delete(id)\n this.nodes.delete(id)\n removed?.push(id)\n }\n }\n\n private moveHead(branch: string, id: CheckpointId): void {\n const previous = this.heads.get(branch)\n if (previous === id) return\n if (previous !== undefined) this.removeReference(previous)\n this.heads.set(branch, id)\n this.addReference(id)\n }\n\n private addReference(id: CheckpointId): void {\n this.references.set(id, (this.references.get(id) ?? 0) + 1)\n this.evictable.delete(id)\n }\n\n private removeReference(id: CheckpointId): void {\n const next = (this.references.get(id) ?? 0) - 1\n if (next > 0) this.references.set(id, next)\n else {\n this.references.delete(id)\n if (this.nodes.has(id)) this.evictable.add(id)\n }\n }\n\n private assertBranch(branch: string): void {\n if (!BRANCH_PATTERN.test(branch)) throw new RangeError(`branch must match ${BRANCH_PATTERN}`)\n }\n}\n", "import { Database } from \"@crvouga/mockingbird-service-sqlite\"\nimport type { SqliteClient } from \"./client.js\"\n\n/** Construct the default in-memory SQLite client (`@crvouga/mockingbird-service-sqlite`). */\nexport const createDefaultSqlite = (): SqliteClient => new Database()\n\n/** Use the injected client, or fall back to {@link createDefaultSqlite}. */\nexport const resolveSqlite = (sqlite?: SqliteClient): SqliteClient =>\n sqlite ?? createDefaultSqlite()\n", "import type { SqliteClient } from \"./client.js\"\n\n/** One named, ordered schema change applied exactly once per client. */\nexport type Migration = {\n /** Stable id stored in `schema_migrations`. Must be unique across the list. */\n id: string\n sql: string\n}\n\nconst ensureMigrationsTable = (sqlite: SqliteClient) => {\n sqlite.exec(`\n CREATE TABLE IF NOT EXISTS schema_migrations (\n id TEXT PRIMARY KEY NOT NULL,\n applied_at INTEGER NOT NULL\n )\n `)\n}\n\nconst assertUniqueIds = (migrations: readonly Migration[]) => {\n const seen = new Set<string>()\n for (const { id } of migrations) {\n if (seen.has(id)) throw new Error(`migrate: duplicate migration id \"${id}\"; ids must be unique`)\n seen.add(id)\n }\n}\n\n/**\n * Apply pending migrations in order inside a single transaction.\n *\n * Idempotent: already-applied ids are skipped. Re-running with the same list\n * is a no-op after the first successful boot.\n *\n * @throws {Error} If two migrations in the list share an id; nothing is applied.\n */\nexport const migrate = (sqlite: SqliteClient, migrations: readonly Migration[]): void => {\n assertUniqueIds(migrations)\n ensureMigrationsTable(sqlite)\n const applied = new Set(\n sqlite\n .prepare(\"SELECT id FROM schema_migrations\")\n .all<{ id: string }>()\n .map((row) => row.id),\n )\n const pending = migrations.filter((migration) => !applied.has(migration.id))\n if (pending.length === 0) return\n\n const insert = sqlite.prepare(\"INSERT INTO schema_migrations (id, applied_at) VALUES (?, ?)\")\n const now = Math.floor(Date.now() / 1000)\n sqlite.transaction(() => {\n for (const migration of pending) {\n sqlite.exec(migration.sql)\n insert.run(migration.id, now)\n }\n })\n}\n\n/**\n * Applied migration ids in application order: by `applied_at`, then `rowid`.\n * `schema_migrations` is a rowid table, so `rowid` follows insertion order and\n * breaks same-second ties in the order the migrations ran.\n */\nexport const listAppliedMigrations = (sqlite: SqliteClient): string[] => {\n ensureMigrationsTable(sqlite)\n return sqlite\n .prepare(\"SELECT id FROM schema_migrations ORDER BY applied_at ASC, rowid ASC\")\n .all<{ id: string }>()\n .map((row) => row.id)\n}\n", "import type { SqliteClient } from \"./client.js\"\nimport { type Migration, migrate } from \"./migrate.js\"\n\n/**\n * Core Mockingbird service schema: namespaced JSON records and counters.\n *\n * Applied on every service boot via {@link migrateCore}.\n */\nexport const CORE_MIGRATIONS: readonly Migration[] = [\n {\n id: \"20260322_core_records_sequences\",\n sql: `\n CREATE TABLE IF NOT EXISTS mockingbird_records (\n namespace TEXT NOT NULL,\n collection TEXT NOT NULL,\n id TEXT NOT NULL,\n seq INTEGER NOT NULL,\n value TEXT NOT NULL,\n PRIMARY KEY (namespace, collection, id)\n );\n CREATE INDEX IF NOT EXISTS mockingbird_records_seq\n ON mockingbird_records (namespace, collection, seq);\n CREATE TABLE IF NOT EXISTS mockingbird_sequences (\n namespace TEXT NOT NULL,\n name TEXT NOT NULL,\n kind TEXT NOT NULL,\n value INTEGER NOT NULL,\n PRIMARY KEY (namespace, name, kind)\n );\n `,\n },\n]\n\n/**\n * Table and index names from the unfinished product rename.\n * Renamed in place so a database created under those names keeps its rows.\n */\nconst LEGACY_TABLES = [\n [\"emulates_records\", \"mockingbird_records\"],\n [\"emulators_records\", \"mockingbird_records\"],\n [\"emulates_sequences\", \"mockingbird_sequences\"],\n [\"emulators_sequences\", \"mockingbird_sequences\"],\n] as const\nconst LEGACY_INDEXES = [\n [\"emulates_records_seq\", \"mockingbird_records_seq\"],\n [\"emulators_records_seq\", \"mockingbird_records_seq\"],\n] as const\n\nconst namesOf = (sqlite: SqliteClient, type: \"table\" | \"index\"): Set<string> =>\n new Set(\n sqlite\n .prepare(\"SELECT name FROM sqlite_master WHERE type = ?\")\n .all<{ name: string }>(type)\n .map((row) => row.name),\n )\n\n/** Apply {@link CORE_MIGRATIONS}, then rename a database that still uses the former table names. */\nexport const migrateCore = (sqlite: SqliteClient): void => {\n migrate(sqlite, CORE_MIGRATIONS)\n const tables = namesOf(sqlite, \"table\")\n const indexes = namesOf(sqlite, \"index\")\n sqlite.transaction(() => {\n for (const [from, to] of LEGACY_TABLES) {\n if (!tables.has(from) || tables.has(to)) continue\n sqlite.exec(`ALTER TABLE ${from} RENAME TO ${to}`)\n tables.delete(from)\n tables.add(to)\n }\n for (const [from, to] of LEGACY_INDEXES) {\n if (!indexes.has(from) || indexes.has(to)) continue\n // The sqlite port accepts ALTER TABLE, not ALTER INDEX.\n sqlite.exec(`DROP INDEX ${from}`)\n sqlite.exec(`CREATE INDEX ${to} ON mockingbird_records (namespace, collection, seq)`)\n indexes.delete(from)\n indexes.add(to)\n }\n })\n}\n\n/** Delete every record and sequence belonging to `namespace`. */\nexport const clearNamespace = (sqlite: SqliteClient, namespace: string): void => {\n sqlite.transaction(() => {\n sqlite.prepare(\"DELETE FROM mockingbird_records WHERE namespace = ?\").run(namespace)\n sqlite.prepare(\"DELETE FROM mockingbird_sequences WHERE namespace = ?\").run(namespace)\n })\n}\n", "'use strict';\n\nconst nameStartChar = ':A-Za-z_\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02FF\\\\u0370-\\\\u037D\\\\u037F-\\\\u1FFF\\\\u200C-\\\\u200D\\\\u2070-\\\\u218F\\\\u2C00-\\\\u2FEF\\\\u3001-\\\\uD7FF\\\\uF900-\\\\uFDCF\\\\uFDF0-\\\\uFFFD';\nconst nameChar = nameStartChar + '\\\\-.\\\\d\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040';\nexport const nameRegexp = '[' + nameStartChar + '][' + nameChar + ']*';\nconst regexName = new RegExp('^' + nameRegexp + '$');\n\nexport function getAllMatches(string, regex) {\n const matches = [];\n let match = regex.exec(string);\n while (match) {\n const allmatches = [];\n allmatches.startIndex = regex.lastIndex - match[0].length;\n const len = match.length;\n for (let index = 0; index < len; index++) {\n allmatches.push(match[index]);\n }\n matches.push(allmatches);\n match = regex.exec(string);\n }\n return matches;\n}\n\nexport const isName = function (string) {\n const match = regexName.exec(string);\n return !(match === null || typeof match === 'undefined');\n}\n\nexport function isExist(v) {\n return typeof v !== 'undefined';\n}\n\nexport function isEmptyObject(obj) {\n return Object.keys(obj).length === 0;\n}\n\nexport function getValue(v) {\n if (exports.isExist(v)) {\n return v;\n } else {\n return '';\n }\n}\n\n/**\n * Dangerous property names that could lead to prototype pollution or security issues\n */\nexport const DANGEROUS_PROPERTY_NAMES = [\n // '__proto__',\n // 'constructor',\n // 'prototype',\n 'hasOwnProperty',\n 'toString',\n 'valueOf',\n '__defineGetter__',\n '__defineSetter__',\n '__lookupGetter__',\n '__lookupSetter__'\n];\n\nexport const criticalProperties = [\"__proto__\", \"constructor\", \"prototype\"];", "'use strict';\n\nimport { isName } from './util.js';\n\nconst defaultOptions = {\n allowBooleanAttributes: false, //A tag can have attributes without any value\n unpairedTags: []\n};\n\n//const tagsPattern = new RegExp(\"<\\\\/?([\\\\w:\\\\-_\\.]+)\\\\s*\\/?>\",\"g\");\nexport function validate(xmlData, options) {\n options = Object.assign({}, defaultOptions, options);\n\n //xmlData = xmlData.replace(/(\\r\\n|\\n|\\r)/gm,\"\");//make it single line\n //xmlData = xmlData.replace(/(^\\s*<\\?xml.*?\\?>)/g,\"\");//Remove XML starting tag\n //xmlData = xmlData.replace(/(<!DOCTYPE[\\s\\w\\\"\\.\\/\\-\\:]+(\\[.*\\])*\\s*>)/g,\"\");//Remove DOCTYPE\n const tags = [];\n let tagFound = false;\n\n //indicates that the root tag has been closed (aka. depth 0 has been reached)\n let reachedRoot = false;\n\n if (xmlData[0] === '\\ufeff') {\n // check for byte order mark (BOM)\n xmlData = xmlData.substr(1);\n }\n\n for (let i = 0; i < xmlData.length; i++) {\n\n if (xmlData[i] === '<' && xmlData[i + 1] === '?') {\n i += 2;\n i = readPI(xmlData, i);\n if (i.err) return i;\n } else if (xmlData[i] === '<') {\n //starting of tag\n //read until you reach to '>' avoiding any '>' in attribute value\n let tagStartPos = i;\n i++;\n\n if (xmlData[i] === '!') {\n i = readCommentAndCDATA(xmlData, i);\n continue;\n } else {\n let closingTag = false;\n if (xmlData[i] === '/') {\n //closing tag\n closingTag = true;\n i++;\n }\n //read tagname\n let tagName = '';\n for (; i < xmlData.length &&\n xmlData[i] !== '>' &&\n xmlData[i] !== ' ' &&\n xmlData[i] !== '\\t' &&\n xmlData[i] !== '\\n' &&\n xmlData[i] !== '\\r'; i++\n ) {\n tagName += xmlData[i];\n }\n tagName = tagName.trim();\n //console.log(tagName);\n\n if (tagName[tagName.length - 1] === '/') {\n //self closing tag without attributes\n tagName = tagName.substring(0, tagName.length - 1);\n //continue;\n i--;\n }\n if (!validateTagName(tagName)) {\n let msg;\n if (tagName.trim().length === 0) {\n msg = \"Invalid space after '<'.\";\n } else {\n msg = \"Tag '\" + tagName + \"' is an invalid name.\";\n }\n return getErrorObject('InvalidTag', msg, getLineNumberForPosition(xmlData, i));\n }\n\n const result = readAttributeStr(xmlData, i);\n if (result === false) {\n return getErrorObject('InvalidAttr', \"Attributes for '\" + tagName + \"' have open quote.\", getLineNumberForPosition(xmlData, i));\n }\n let attrStr = result.value;\n i = result.index;\n\n if (attrStr[attrStr.length - 1] === '/') {\n //self closing tag\n const attrStrStart = i - attrStr.length;\n attrStr = attrStr.substring(0, attrStr.length - 1);\n const isValid = validateAttributeString(attrStr, options);\n if (isValid === true) {\n tagFound = true;\n //continue; //text may presents after self closing tag\n } else {\n //the result from the nested function returns the position of the error within the attribute\n //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute\n //this gives us the absolute index in the entire xml, which we can use to find the line at last\n return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, attrStrStart + isValid.err.line));\n }\n } else if (closingTag) {\n if (!result.tagClosed) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' doesn't have proper closing.\", getLineNumberForPosition(xmlData, i));\n } else if (attrStr.trim().length > 0) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' can't have attributes or invalid starting.\", getLineNumberForPosition(xmlData, tagStartPos));\n } else if (tags.length === 0) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' has not been opened.\", getLineNumberForPosition(xmlData, tagStartPos));\n } else {\n const otg = tags.pop();\n if (tagName !== otg.tagName) {\n let openPos = getLineNumberForPosition(xmlData, otg.tagStartPos);\n return getErrorObject('InvalidTag',\n \"Expected closing tag '\" + otg.tagName + \"' (opened in line \" + openPos.line + \", col \" + openPos.col + \") instead of closing tag '\" + tagName + \"'.\",\n getLineNumberForPosition(xmlData, tagStartPos));\n }\n\n //when there are no more tags, we reached the root level.\n if (tags.length == 0) {\n reachedRoot = true;\n }\n }\n } else {\n const isValid = validateAttributeString(attrStr, options);\n if (isValid !== true) {\n //the result from the nested function returns the position of the error within the attribute\n //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute\n //this gives us the absolute index in the entire xml, which we can use to find the line at last\n return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, i - attrStr.length + isValid.err.line));\n }\n\n //if the root level has been reached before ...\n if (reachedRoot === true) {\n return getErrorObject('InvalidXml', 'Multiple possible root nodes found.', getLineNumberForPosition(xmlData, i));\n } else if (options.unpairedTags.indexOf(tagName) !== -1) {\n //don't push into stack\n } else {\n tags.push({ tagName, tagStartPos });\n }\n tagFound = true;\n }\n\n //skip tag text value\n //It may include comments and CDATA value\n for (i++; i < xmlData.length; i++) {\n if (xmlData[i] === '<') {\n if (xmlData[i + 1] === '!') {\n //comment or CADATA\n i++;\n i = readCommentAndCDATA(xmlData, i);\n continue;\n } else if (xmlData[i + 1] === '?') {\n i = readPI(xmlData, ++i);\n if (i.err) return i;\n } else {\n break;\n }\n } else if (xmlData[i] === '&') {\n const afterAmp = validateAmpersand(xmlData, i);\n if (afterAmp == -1)\n return getErrorObject('InvalidChar', \"char '&' is not expected.\", getLineNumberForPosition(xmlData, i));\n i = afterAmp;\n } else {\n if (reachedRoot === true && !isWhiteSpace(xmlData[i])) {\n return getErrorObject('InvalidXml', \"Extra text at the end\", getLineNumberForPosition(xmlData, i));\n }\n }\n } //end of reading tag text value\n if (xmlData[i] === '<') {\n i--;\n }\n }\n } else {\n if (isWhiteSpace(xmlData[i])) {\n continue;\n }\n return getErrorObject('InvalidChar', \"char '\" + xmlData[i] + \"' is not expected.\", getLineNumberForPosition(xmlData, i));\n }\n }\n\n if (!tagFound) {\n return getErrorObject('InvalidXml', 'Start tag expected.', 1);\n } else if (tags.length == 1) {\n return getErrorObject('InvalidTag', \"Unclosed tag '\" + tags[0].tagName + \"'.\", getLineNumberForPosition(xmlData, tags[0].tagStartPos));\n } else if (tags.length > 0) {\n return getErrorObject('InvalidXml', \"Invalid '\" +\n JSON.stringify(tags.map(t => t.tagName), null, 4).replace(/\\r?\\n/g, '') +\n \"' found.\", { line: 1, col: 1 });\n }\n\n return true;\n};\n\nfunction isWhiteSpace(char) {\n return char === ' ' || char === '\\t' || char === '\\n' || char === '\\r';\n}\n/**\n * Read Processing insstructions and skip\n * @param {*} xmlData\n * @param {*} i\n */\nfunction readPI(xmlData, i) {\n const start = i;\n for (; i < xmlData.length; i++) {\n if (xmlData[i] == '?' || xmlData[i] == ' ') {\n //tagname\n const tagname = xmlData.substr(start, i - start);\n if (i > 5 && tagname === 'xml') {\n return getErrorObject('InvalidXml', 'XML declaration allowed only at the start of the document.', getLineNumberForPosition(xmlData, i));\n } else if (xmlData[i] == '?' && xmlData[i + 1] == '>') {\n //check if valid attribut string\n i++;\n break;\n } else {\n continue;\n }\n }\n }\n return i;\n}\n\nfunction readCommentAndCDATA(xmlData, i) {\n if (xmlData.length > i + 5 && xmlData[i + 1] === '-' && xmlData[i + 2] === '-') {\n //comment\n for (i += 3; i < xmlData.length; i++) {\n if (xmlData[i] === '-' && xmlData[i + 1] === '-' && xmlData[i + 2] === '>') {\n i += 2;\n break;\n }\n }\n } else if (\n xmlData.length > i + 8 &&\n xmlData[i + 1] === 'D' &&\n xmlData[i + 2] === 'O' &&\n xmlData[i + 3] === 'C' &&\n xmlData[i + 4] === 'T' &&\n xmlData[i + 5] === 'Y' &&\n xmlData[i + 6] === 'P' &&\n xmlData[i + 7] === 'E'\n ) {\n let angleBracketsCount = 1;\n for (i += 8; i < xmlData.length; i++) {\n if (xmlData[i] === '<') {\n angleBracketsCount++;\n } else if (xmlData[i] === '>') {\n angleBracketsCount--;\n if (angleBracketsCount === 0) {\n break;\n }\n }\n }\n } else if (\n xmlData.length > i + 9 &&\n xmlData[i + 1] === '[' &&\n xmlData[i + 2] === 'C' &&\n xmlData[i + 3] === 'D' &&\n xmlData[i + 4] === 'A' &&\n xmlData[i + 5] === 'T' &&\n xmlData[i + 6] === 'A' &&\n xmlData[i + 7] === '['\n ) {\n for (i += 8; i < xmlData.length; i++) {\n if (xmlData[i] === ']' && xmlData[i + 1] === ']' && xmlData[i + 2] === '>') {\n i += 2;\n break;\n }\n }\n }\n\n return i;\n}\n\nconst doubleQuote = '\"';\nconst singleQuote = \"'\";\n\n/**\n * Keep reading xmlData until '<' is found outside the attribute value.\n * @param {string} xmlData\n * @param {number} i\n */\nfunction readAttributeStr(xmlData, i) {\n let attrStr = '';\n let startChar = '';\n let tagClosed = false;\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === doubleQuote || xmlData[i] === singleQuote) {\n if (startChar === '') {\n startChar = xmlData[i];\n } else if (startChar !== xmlData[i]) {\n //if vaue is enclosed with double quote then single quotes are allowed inside the value and vice versa\n } else {\n startChar = '';\n }\n } else if (xmlData[i] === '>') {\n if (startChar === '') {\n tagClosed = true;\n break;\n }\n }\n attrStr += xmlData[i];\n }\n if (startChar !== '') {\n return false;\n }\n\n return {\n value: attrStr,\n index: i,\n tagClosed: tagClosed\n };\n}\n\n/**\n * Walk `attrStr` once, left to right, splitting it into attribute tokens.\n *\n * This replaces a regex that used to do the same job\n * (`(\\s*)([^\\s=]+)(\\s*=)?(\\s*(['\"])(([\\s\\S])*?)\\5)?`). That regex led with an\n * optional whitespace group followed by a required \"non-whitespace\" group.\n * On a long run of whitespace that never resolves into an attribute name\n * (e.g. a tag with thousands of trailing spaces before `>`), the engine\n * backtracks the whitespace group one character at a time before giving up\n * and moving to the next starting position \u2014 one full backtrack per\n * position, which is quadratic in the length of the run.\n *\n * A single forward-only scan can never backtrack, so it can't be made slow\n * this way no matter how much whitespace the input contains \u2014 it's always\n * proportional to the length of the string, once.\n *\n * Each returned token mirrors the shape the old regex match array had, so\n * the validation logic below (which reads token[1]..token[6]) didn't need\n * to change:\n * token.startIndex - where this token begins in attrStr\n * token[1] - leading whitespace before the name\n * token[2] - the attribute name\n * token[3] - whitespace + '=' if present, else undefined\n * token[4] - marker (any defined value) if a quoted value was found\n * token[5] - the quote character used ('\"' or \"'\")\n * token[6] - the value's text, without the surrounding quotes\n *\n * A malformed leading character (e.g. a stray '=' with no name before it)\n * is simply skipped over, one character at a time \u2014 the same outcome the\n * old regex produced by failing to match at that position and retrying at\n * the next one.\n */\nfunction scanAttributeTokens(attrStr) {\n const tokens = [];\n const len = attrStr.length;\n let i = 0;\n\n while (i < len) {\n const tokenStart = i;\n\n // Leading whitespace before the name.\n while (i < len && isWhiteSpace(attrStr[i])) i++;\n if (i >= len) break; // trailing whitespace only \u2014 nothing left to read\n\n if (attrStr[i] === '=') {\n // No name before this '=' \u2014 not a valid attribute start. Move past\n // just this one character and try again from the next position.\n i = tokenStart + 1;\n continue;\n }\n\n const leadingWs = attrStr.slice(tokenStart, i);\n\n // Attribute name \u2014 everything up to the next whitespace or '='.\n const nameStart = i;\n while (i < len && !isWhiteSpace(attrStr[i]) && attrStr[i] !== '=') i++;\n const name = attrStr.slice(nameStart, i);\n\n // Optional whitespace + '='.\n let equalsGroup; // whitespace + '=' text, or undefined if absent\n let j = i;\n while (j < len && isWhiteSpace(attrStr[j])) j++;\n if (j < len && attrStr[j] === '=') {\n equalsGroup = attrStr.slice(i, j + 1);\n i = j + 1;\n }\n\n // Optional whitespace + quoted value.\n let quoteChar;\n let value;\n let k = i;\n while (k < len && isWhiteSpace(attrStr[k])) k++;\n if (k < len && (attrStr[k] === '\"' || attrStr[k] === \"'\")) {\n const valueStart = k + 1;\n const closeIdx = attrStr.indexOf(attrStr[k], valueStart);\n if (closeIdx !== -1) {\n quoteChar = attrStr[k];\n value = attrStr.slice(valueStart, closeIdx);\n i = closeIdx + 1;\n }\n // No closing quote found anywhere in the rest of the string \u2014 leave\n // quoteChar/value undefined, same as the old regex's group failing\n // to match a backreference-less run.\n }\n\n const token = { startIndex: tokenStart };\n token[1] = leadingWs;\n token[2] = name;\n token[3] = equalsGroup;\n token[4] = quoteChar !== undefined ? true : undefined;\n token[5] = quoteChar;\n token[6] = value;\n tokens.push(token);\n }\n\n return tokens;\n}\n\n//attr, =\"sd\", a=\"amit's\", a=\"sd\"b=\"saf\", ab cd=\"\"\n\nfunction validateAttributeString(attrStr, options) {\n //console.log(\"start:\"+attrStr+\":end\");\n\n //if(attrStr.trim().length === 0) return true; //empty string\n\n const matches = scanAttributeTokens(attrStr);\n const attrNames = {};\n\n for (let i = 0; i < matches.length; i++) {\n if (matches[i][1].length === 0) {\n //nospace before attribute name: a=\"sd\"b=\"saf\"\n return getErrorObject('InvalidAttr', \"Attribute '\" + matches[i][2] + \"' has no space in starting.\", getPositionFromMatch(matches[i]))\n } else if (matches[i][3] !== undefined && matches[i][4] === undefined) {\n return getErrorObject('InvalidAttr', \"Attribute '\" + matches[i][2] + \"' is without value.\", getPositionFromMatch(matches[i]));\n } else if (matches[i][3] === undefined && !options.allowBooleanAttributes) {\n //independent attribute: ab\n return getErrorObject('InvalidAttr', \"boolean attribute '\" + matches[i][2] + \"' is not allowed.\", getPositionFromMatch(matches[i]));\n }\n /* else if(matches[i][6] === undefined){//attribute without value: ab=\n return { err: { code:\"InvalidAttr\",msg:\"attribute \" + matches[i][2] + \" has no value assigned.\"}};\n } */\n const attrName = matches[i][2];\n if (!validateAttrName(attrName)) {\n return getErrorObject('InvalidAttr', \"Attribute '\" + attrName + \"' is an invalid name.\", getPositionFromMatch(matches[i]));\n }\n if (!Object.prototype.hasOwnProperty.call(attrNames, attrName)) {\n //check for duplicate attribute.\n attrNames[attrName] = 1;\n } else {\n return getErrorObject('InvalidAttr', \"Attribute '\" + attrName + \"' is repeated.\", getPositionFromMatch(matches[i]));\n }\n }\n\n return true;\n}\n\nfunction validateNumberAmpersand(xmlData, i) {\n let re = /\\d/;\n if (xmlData[i] === 'x') {\n i++;\n re = /[\\da-fA-F]/;\n }\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === ';')\n return i;\n if (!xmlData[i].match(re))\n break;\n }\n return -1;\n}\n\nfunction validateAmpersand(xmlData, i) {\n // https://www.w3.org/TR/xml/#dt-charref\n i++;\n if (xmlData[i] === ';')\n return -1;\n if (xmlData[i] === '#') {\n i++;\n return validateNumberAmpersand(xmlData, i);\n }\n let count = 0;\n for (; i < xmlData.length; i++, count++) {\n if (xmlData[i].match(/\\w/) && count < 20)\n continue;\n if (xmlData[i] === ';')\n break;\n return -1;\n }\n return i;\n}\n\nfunction getErrorObject(code, message, lineNumber) {\n return {\n err: {\n code: code,\n msg: message,\n line: lineNumber.line || lineNumber,\n col: lineNumber.col,\n },\n };\n}\n\nfunction validateAttrName(attrName) {\n return isName(attrName);\n}\n\n// const startsWithXML = /^xml/i;\n\nfunction validateTagName(tagname) {\n return isName(tagname) /* && !tagname.match(startsWithXML) */;\n}\n\n//this function returns the line number for the character at the given index\nfunction getLineNumberForPosition(xmlData, index) {\n const lines = xmlData.substring(0, index).split(/\\r?\\n/);\n return {\n line: lines.length,\n\n // column number is last line's length + 1, because column numbering starts at 1:\n col: lines[lines.length - 1].length + 1\n };\n}\n\n//this function returns the position of the first character of match within attrStr\nfunction getPositionFromMatch(match) {\n return match.startIndex + match[1].length;\n}", "// ---------------------------------------------------------------------------\n// Complete HTML5 named entity reference\n// Organized by logical categories for easy maintenance and selective importing\n// ---------------------------------------------------------------------------\n\n/**\n * Basic Latin & Special Characters\n * @type {Record<string, string>}\n */\nexport const BASIC_LATIN = {\n amp: '&',\n AMP: '&',\n lt: '<',\n LT: '<',\n gt: '>',\n GT: '>',\n quot: '\"',\n QUOT: '\"',\n apos: \"'\",\n lsquo: '\u2018',\n rsquo: '\u2019',\n ldquo: '\u201C',\n rdquo: '\u201D',\n lsquor: '\u201A',\n rsquor: '\u2019',\n ldquor: '\u201E',\n bdquo: '\u201E',\n comma: ',',\n period: '.',\n colon: ':',\n semi: ';',\n excl: '!',\n quest: '?',\n num: '#',\n dollar: '$',\n percent: '%',\n ast: '*',\n commat: '@',\n lowbar: '_',\n verbar: '|',\n vert: '|',\n sol: '/',\n bsol: '\\\\',\n lbrace: '{',\n rbrace: '}',\n lbrack: '[',\n rbrack: ']',\n lpar: '(',\n rpar: ')',\n nbsp: '\\u00a0',\n iexcl: '\u00A1',\n cent: '\u00A2',\n pound: '\u00A3',\n curren: '\u00A4',\n yen: '\u00A5',\n brvbar: '\u00A6',\n sect: '\u00A7',\n uml: '\u00A8',\n copy: '\u00A9',\n COPY: '\u00A9',\n ordf: '\u00AA',\n laquo: '\u00AB',\n not: '\u00AC',\n shy: '\\u00ad',\n reg: '\u00AE',\n REG: '\u00AE',\n macr: '\u00AF',\n deg: '\u00B0',\n plusmn: '\u00B1',\n sup2: '\u00B2',\n sup3: '\u00B3',\n acute: '\u00B4',\n micro: '\u00B5',\n para: '\u00B6',\n middot: '\u00B7',\n cedil: '\u00B8',\n sup1: '\u00B9',\n ordm: '\u00BA',\n raquo: '\u00BB',\n frac14: '\u00BC',\n frac12: '\u00BD',\n half: '\u00BD',\n frac34: '\u00BE',\n iquest: '\u00BF',\n times: '\u00D7',\n div: '\u00F7',\n divide: '\u00F7',\n};\n\n/**\n * Latin Extended & Accented Letters (A-Z)\n * @type {Record<string, string>}\n */\nexport const LATIN_ACCENTS = {\n Agrave: '\u00C0',\n agrave: '\u00E0',\n Aacute: '\u00C1',\n aacute: '\u00E1',\n Acirc: '\u00C2',\n acirc: '\u00E2',\n Atilde: '\u00C3',\n atilde: '\u00E3',\n Auml: '\u00C4',\n auml: '\u00E4',\n Aring: '\u00C5',\n aring: '\u00E5',\n AElig: '\u00C6',\n aelig: '\u00E6',\n Ccedil: '\u00C7',\n ccedil: '\u00E7',\n Egrave: '\u00C8',\n egrave: '\u00E8',\n Eacute: '\u00C9',\n eacute: '\u00E9',\n Ecirc: '\u00CA',\n ecirc: '\u00EA',\n Euml: '\u00CB',\n euml: '\u00EB',\n Igrave: '\u00CC',\n igrave: '\u00EC',\n Iacute: '\u00CD',\n iacute: '\u00ED',\n Icirc: '\u00CE',\n icirc: '\u00EE',\n Iuml: '\u00CF',\n iuml: '\u00EF',\n ETH: '\u00D0',\n eth: '\u00F0',\n Ntilde: '\u00D1',\n ntilde: '\u00F1',\n Ograve: '\u00D2',\n ograve: '\u00F2',\n Oacute: '\u00D3',\n oacute: '\u00F3',\n Ocirc: '\u00D4',\n ocirc: '\u00F4',\n Otilde: '\u00D5',\n otilde: '\u00F5',\n Ouml: '\u00D6',\n ouml: '\u00F6',\n Oslash: '\u00D8',\n oslash: '\u00F8',\n Ugrave: '\u00D9',\n ugrave: '\u00F9',\n Uacute: '\u00DA',\n uacute: '\u00FA',\n Ucirc: '\u00DB',\n ucirc: '\u00FB',\n Uuml: '\u00DC',\n uuml: '\u00FC',\n Yacute: '\u00DD',\n yacute: '\u00FD',\n THORN: '\u00DE',\n thorn: '\u00FE',\n szlig: '\u00DF',\n yuml: '\u00FF',\n Yuml: '\u0178',\n};\n\n/**\n * Latin Extended (Letters with diacritics)\n * @type {Record<string, string>}\n */\nexport const LATIN_EXTENDED = {\n Amacr: '\u0100',\n amacr: '\u0101',\n Abreve: '\u0102',\n abreve: '\u0103',\n Aogon: '\u0104',\n aogon: '\u0105',\n Cacute: '\u0106',\n cacute: '\u0107',\n Ccirc: '\u0108',\n ccirc: '\u0109',\n Cdot: '\u010A',\n cdot: '\u010B',\n Ccaron: '\u010C',\n ccaron: '\u010D',\n Dcaron: '\u010E',\n dcaron: '\u010F',\n Dstrok: '\u0110',\n dstrok: '\u0111',\n Emacr: '\u0112',\n emacr: '\u0113',\n Ecaron: '\u011A',\n ecaron: '\u011B',\n Edot: '\u0116',\n edot: '\u0117',\n Eogon: '\u0118',\n eogon: '\u0119',\n Gcirc: '\u011C',\n gcirc: '\u011D',\n Gbreve: '\u011E',\n gbreve: '\u011F',\n Gdot: '\u0120',\n gdot: '\u0121',\n Gcedil: '\u0122',\n Hcirc: '\u0124',\n hcirc: '\u0125',\n Hstrok: '\u0126',\n hstrok: '\u0127',\n Itilde: '\u0128',\n itilde: '\u0129',\n Imacr: '\u012A',\n imacr: '\u012B',\n Iogon: '\u012E',\n iogon: '\u012F',\n Idot: '\u0130',\n IJlig: '\u0132',\n ijlig: '\u0133',\n Jcirc: '\u0134',\n jcirc: '\u0135',\n Kcedil: '\u0136',\n kcedil: '\u0137',\n kgreen: '\u0138',\n Lacute: '\u0139',\n lacute: '\u013A',\n Lcedil: '\u013B',\n lcedil: '\u013C',\n Lcaron: '\u013D',\n lcaron: '\u013E',\n Lmidot: '\u013F',\n lmidot: '\u0140',\n Lstrok: '\u0141',\n lstrok: '\u0142',\n Nacute: '\u0143',\n nacute: '\u0144',\n Ncaron: '\u0147',\n ncaron: '\u0148',\n Ncedil: '\u0145',\n ncedil: '\u0146',\n ENG: '\u014A',\n eng: '\u014B',\n Omacr: '\u014C',\n omacr: '\u014D',\n Odblac: '\u0150',\n odblac: '\u0151',\n OElig: '\u0152',\n oelig: '\u0153',\n Racute: '\u0154',\n racute: '\u0155',\n Rcaron: '\u0158',\n rcaron: '\u0159',\n Rcedil: '\u0156',\n rcedil: '\u0157',\n Sacute: '\u015A',\n sacute: '\u015B',\n Scirc: '\u015C',\n scirc: '\u015D',\n Scedil: '\u015E',\n scedil: '\u015F',\n Scaron: '\u0160',\n scaron: '\u0161',\n Tcedil: '\u0162',\n tcedil: '\u0163',\n Tcaron: '\u0164',\n tcaron: '\u0165',\n Tstrok: '\u0166',\n tstrok: '\u0167',\n Utilde: '\u0168',\n utilde: '\u0169',\n Umacr: '\u016A',\n umacr: '\u016B',\n Ubreve: '\u016C',\n ubreve: '\u016D',\n Uring: '\u016E',\n uring: '\u016F',\n Udblac: '\u0170',\n udblac: '\u0171',\n Uogon: '\u0172',\n uogon: '\u0173',\n Wcirc: '\u0174',\n wcirc: '\u0175',\n Ycirc: '\u0176',\n ycirc: '\u0177',\n Zacute: '\u0179',\n zacute: '\u017A',\n Zdot: '\u017B',\n zdot: '\u017C',\n Zcaron: '\u017D',\n zcaron: '\u017E',\n};\n\n/**\n * Greek Letters\n * @type {Record<string, string>}\n */\nexport const GREEK = {\n Alpha: '\u0391',\n alpha: '\u03B1',\n Beta: '\u0392',\n beta: '\u03B2',\n Gamma: '\u0393',\n gamma: '\u03B3',\n Delta: '\u0394',\n delta: '\u03B4',\n Epsilon: '\u0395',\n epsilon: '\u03B5',\n epsiv: '\u03F5',\n varepsilon: '\u03F5',\n Zeta: '\u0396',\n zeta: '\u03B6',\n Eta: '\u0397',\n eta: '\u03B7',\n Theta: '\u0398',\n theta: '\u03B8',\n thetasym: '\u03D1',\n vartheta: '\u03D1',\n Iota: '\u0399',\n iota: '\u03B9',\n Kappa: '\u039A',\n kappa: '\u03BA',\n kappav: '\u03F0',\n varkappa: '\u03F0',\n Lambda: '\u039B',\n lambda: '\u03BB',\n Mu: '\u039C',\n mu: '\u03BC',\n Nu: '\u039D',\n nu: '\u03BD',\n Xi: '\u039E',\n xi: '\u03BE',\n Omicron: '\u039F',\n omicron: '\u03BF',\n Pi: '\u03A0',\n pi: '\u03C0',\n piv: '\u03D6',\n varpi: '\u03D6',\n Rho: '\u03A1',\n rho: '\u03C1',\n rhov: '\u03F1',\n varrho: '\u03F1',\n Sigma: '\u03A3',\n sigma: '\u03C3',\n sigmaf: '\u03C2',\n sigmav: '\u03C2',\n varsigma: '\u03C2',\n Tau: '\u03A4',\n tau: '\u03C4',\n Upsilon: '\u03A5',\n upsilon: '\u03C5',\n upsi: '\u03C5',\n Upsi: '\u03D2',\n upsih: '\u03D2',\n Phi: '\u03A6',\n phi: '\u03C6',\n phiv: '\u03D5',\n varphi: '\u03D5',\n Chi: '\u03A7',\n chi: '\u03C7',\n Psi: '\u03A8',\n psi: '\u03C8',\n Omega: '\u03A9',\n omega: '\u03C9',\n ohm: '\u03A9',\n Gammad: '\u03DC',\n gammad: '\u03DD',\n digamma: '\u03DD',\n};\n\n/**\n * Cyrillic Letters\n * @type {Record<string, string>}\n */\nexport const CYRILLIC = {\n Afr: '\uD835\uDD04',\n afr: '\uD835\uDD1E',\n Acy: '\u0410',\n acy: '\u0430',\n Bcy: '\u0411',\n bcy: '\u0431',\n Vcy: '\u0412',\n vcy: '\u0432',\n Gcy: '\u0413',\n gcy: '\u0433',\n Dcy: '\u0414',\n dcy: '\u0434',\n IEcy: '\u0415',\n iecy: '\u0435',\n IOcy: '\u0401',\n iocy: '\u0451',\n ZHcy: '\u0416',\n zhcy: '\u0436',\n Zcy: '\u0417',\n zcy: '\u0437',\n Icy: '\u0418',\n icy: '\u0438',\n Jcy: '\u0419',\n jcy: '\u0439',\n Kcy: '\u041A',\n kcy: '\u043A',\n Lcy: '\u041B',\n lcy: '\u043B',\n Mcy: '\u041C',\n mcy: '\u043C',\n Ncy: '\u041D',\n ncy: '\u043D',\n Ocy: '\u041E',\n ocy: '\u043E',\n Pcy: '\u041F',\n pcy: '\u043F',\n Rcy: '\u0420',\n rcy: '\u0440',\n Scy: '\u0421',\n scy: '\u0441',\n Tcy: '\u0422',\n tcy: '\u0442',\n Ucy: '\u0423',\n ucy: '\u0443',\n Fcy: '\u0424',\n fcy: '\u0444',\n KHcy: '\u0425',\n khcy: '\u0445',\n TScy: '\u0426',\n tscy: '\u0446',\n CHcy: '\u0427',\n chcy: '\u0447',\n SHcy: '\u0428',\n shcy: '\u0448',\n SHCHcy: '\u0429',\n shchcy: '\u0449',\n HARDcy: '\u042A',\n hardcy: '\u044A',\n Ycy: '\u042B',\n ycy: '\u044B',\n SOFTcy: '\u042C',\n softcy: '\u044C',\n Ecy: '\u042D',\n ecy: '\u044D',\n YUcy: '\u042E',\n yucy: '\u044E',\n YAcy: '\u042F',\n yacy: '\u044F',\n DJcy: '\u0402',\n djcy: '\u0452',\n GJcy: '\u0403',\n gjcy: '\u0453',\n Jukcy: '\u0404',\n jukcy: '\u0454',\n DScy: '\u0405',\n dscy: '\u0455',\n Iukcy: '\u0406',\n iukcy: '\u0456',\n YIcy: '\u0407',\n yicy: '\u0457',\n Jsercy: '\u0408',\n jsercy: '\u0458',\n LJcy: '\u0409',\n ljcy: '\u0459',\n NJcy: '\u040A',\n njcy: '\u045A',\n TSHcy: '\u040B',\n tshcy: '\u045B',\n KJcy: '\u040C',\n kjcy: '\u045C',\n Ubrcy: '\u040E',\n ubrcy: '\u045E',\n DZcy: '\u040F',\n dzcy: '\u045F',\n};\n\n/**\n * Mathematical Operators & Relations\n * @type {Record<string, string>}\n */\nexport const MATH = {\n plus: '+',\n pm: '\u00B1',\n times: '\u00D7',\n div: '\u00F7',\n divide: '\u00F7',\n sdot: '\u22C5',\n star: '\u2606',\n starf: '\u2605',\n bigstar: '\u2605',\n lowast: '\u2217',\n ast: '*',\n midast: '*',\n compfn: '\u2218',\n smallcircle: '\u2218',\n bullet: '\u2022',\n bull: '\u2022',\n nbsp: '\\u00a0',\n hellip: '\u2026',\n mldr: '\u2026',\n prime: '\u2032',\n Prime: '\u2033',\n tprime: '\u2034',\n bprime: '\u2035',\n backprime: '\u2035',\n minus: '\u2212',\n minusd: '\u2238',\n dotminus: '\u2238',\n plusdo: '\u2214',\n dotplus: '\u2214',\n plusmn: '\u00B1',\n minusplus: '\u2213',\n mnplus: '\u2213',\n mp: '\u2213',\n setminus: '\u2216',\n smallsetminus: '\u2216',\n Backslash: '\u2216',\n setmn: '\u2216',\n ssetmn: '\u2216',\n lowbar: '_',\n verbar: '|',\n vert: '|',\n VerticalLine: '|',\n colon: ':',\n Colon: '\u2237',\n Proportion: '\u2237',\n ratio: '\u2236',\n equals: '=',\n ne: '\u2260',\n nequiv: '\u2262',\n equiv: '\u2261',\n Congruent: '\u2261',\n sim: '\u223C',\n thicksim: '\u223C',\n thksim: '\u223C',\n sime: '\u2243',\n simeq: '\u2243',\n TildeEqual: '\u2243',\n asymp: '\u2248',\n approx: '\u2248',\n thickapprox: '\u2248',\n thkap: '\u2248',\n TildeTilde: '\u2248',\n ncong: '\u2247',\n cong: '\u2245',\n TildeFullEqual: '\u2245',\n asympeq: '\u224D',\n CupCap: '\u224D',\n bump: '\u224E',\n Bumpeq: '\u224E',\n HumpDownHump: '\u224E',\n bumpe: '\u224F',\n bumpeq: '\u224F',\n HumpEqual: '\u224F',\n le: '\u2264',\n LessEqual: '\u2264',\n ge: '\u2265',\n GreaterEqual: '\u2265',\n lesseqgtr: '\u22DA',\n lesseqqgtr: '\u2A8B',\n greater: '>',\n less: '<',\n};\n\n/**\n * Mathematical Operators (Advanced)\n * @type {Record<string, string>}\n */\nexport const MATH_ADVANCED = {\n alefsym: '\u2135',\n aleph: '\u2135',\n beth: '\u2136',\n gimel: '\u2137',\n daleth: '\u2138',\n forall: '\u2200',\n ForAll: '\u2200',\n part: '\u2202',\n PartialD: '\u2202',\n exist: '\u2203',\n Exists: '\u2203',\n nexist: '\u2204',\n nexists: '\u2204',\n empty: '\u2205',\n emptyset: '\u2205',\n emptyv: '\u2205',\n varnothing: '\u2205',\n nabla: '\u2207',\n Del: '\u2207',\n isin: '\u2208',\n isinv: '\u2208',\n in: '\u2208',\n Element: '\u2208',\n notin: '\u2209',\n notinva: '\u2209',\n ni: '\u220B',\n niv: '\u220B',\n SuchThat: '\u220B',\n ReverseElement: '\u220B',\n notni: '\u220C',\n notniva: '\u220C',\n prod: '\u220F',\n Product: '\u220F',\n coprod: '\u2210',\n Coproduct: '\u2210',\n sum: '\u2211',\n Sum: '\u2211',\n minus: '\u2212',\n mp: '\u2213',\n plusdo: '\u2214',\n dotplus: '\u2214',\n setminus: '\u2216',\n lowast: '\u2217',\n radic: '\u221A',\n Sqrt: '\u221A',\n prop: '\u221D',\n propto: '\u221D',\n Proportional: '\u221D',\n varpropto: '\u221D',\n infin: '\u221E',\n infintie: '\u29DD',\n ang: '\u2220',\n angle: '\u2220',\n angmsd: '\u2221',\n measuredangle: '\u2221',\n angsph: '\u2222',\n mid: '\u2223',\n VerticalBar: '\u2223',\n nmid: '\u2224',\n nsmid: '\u2224',\n npar: '\u2226',\n parallel: '\u2225',\n spar: '\u2225',\n nparallel: '\u2226',\n nspar: '\u2226',\n and: '\u2227',\n wedge: '\u2227',\n or: '\u2228',\n vee: '\u2228',\n cap: '\u2229',\n cup: '\u222A',\n int: '\u222B',\n Integral: '\u222B',\n conint: '\u222E',\n ContourIntegral: '\u222E',\n Conint: '\u222F',\n DoubleContourIntegral: '\u222F',\n Cconint: '\u2230',\n there4: '\u2234',\n therefore: '\u2234',\n Therefore: '\u2234',\n becaus: '\u2235',\n because: '\u2235',\n Because: '\u2235',\n ratio: '\u2236',\n Proportion: '\u2237',\n minusd: '\u2238',\n dotminus: '\u2238',\n mDDot: '\u223A',\n homtht: '\u223B',\n sim: '\u223C',\n bsimg: '\u223D',\n backsim: '\u223D',\n ac: '\u223E',\n mstpos: '\u223E',\n acd: '\u223F',\n VerticalTilde: '\u2240',\n wr: '\u2240',\n wreath: '\u2240',\n nsime: '\u2244',\n nsimeq: '\u2244',\n ncong: '\u2247',\n simne: '\u2246',\n ncongdot: '\u2A6D\u0338',\n ngsim: '\u2275',\n nsim: '\u2241',\n napprox: '\u2249',\n nap: '\u2249',\n ngeq: '\u2271',\n nge: '\u2271',\n nleq: '\u2270',\n nle: '\u2270',\n ngtr: '\u226F',\n ngt: '\u226F',\n nless: '\u226E',\n nlt: '\u226E',\n nprec: '\u2280',\n npr: '\u2280',\n nsucc: '\u2281',\n nsc: '\u2281',\n};\n\n/**\n * Arrows\n * @type {Record<string, string>}\n */\nexport const ARROWS = {\n larr: '\u2190',\n leftarrow: '\u2190',\n LeftArrow: '\u2190',\n uarr: '\u2191',\n uparrow: '\u2191',\n UpArrow: '\u2191',\n rarr: '\u2192',\n rightarrow: '\u2192',\n RightArrow: '\u2192',\n darr: '\u2193',\n downarrow: '\u2193',\n DownArrow: '\u2193',\n harr: '\u2194',\n leftrightarrow: '\u2194',\n LeftRightArrow: '\u2194',\n varr: '\u2195',\n updownarrow: '\u2195',\n UpDownArrow: '\u2195',\n nwarr: '\u2196',\n nwarrow: '\u2196',\n UpperLeftArrow: '\u2196',\n nearr: '\u2197',\n nearrow: '\u2197',\n UpperRightArrow: '\u2197',\n searr: '\u2198',\n searrow: '\u2198',\n LowerRightArrow: '\u2198',\n swarr: '\u2199',\n swarrow: '\u2199',\n LowerLeftArrow: '\u2199',\n lArr: '\u21D0',\n Leftarrow: '\u21D0',\n uArr: '\u21D1',\n Uparrow: '\u21D1',\n rArr: '\u21D2',\n Rightarrow: '\u21D2',\n dArr: '\u21D3',\n Downarrow: '\u21D3',\n hArr: '\u21D4',\n Leftrightarrow: '\u21D4',\n iff: '\u21D4',\n vArr: '\u21D5',\n Updownarrow: '\u21D5',\n lAarr: '\u21DA',\n Lleftarrow: '\u21DA',\n rAarr: '\u21DB',\n Rrightarrow: '\u21DB',\n lrarr: '\u21C6',\n leftrightarrows: '\u21C6',\n rlarr: '\u21C4',\n rightleftarrows: '\u21C4',\n lrhar: '\u21CB',\n leftrightharpoons: '\u21CB',\n ReverseEquilibrium: '\u21CB',\n rlhar: '\u21CC',\n rightleftharpoons: '\u21CC',\n Equilibrium: '\u21CC',\n udarr: '\u21C5',\n UpArrowDownArrow: '\u21C5',\n duarr: '\u21F5',\n DownArrowUpArrow: '\u21F5',\n llarr: '\u21C7',\n leftleftarrows: '\u21C7',\n rrarr: '\u21C9',\n rightrightarrows: '\u21C9',\n ddarr: '\u21CA',\n downdownarrows: '\u21CA',\n har: '\u21BD',\n lhard: '\u21BD',\n leftharpoondown: '\u21BD',\n lharu: '\u21BC',\n leftharpoonup: '\u21BC',\n rhard: '\u21C1',\n rightharpoondown: '\u21C1',\n rharu: '\u21C0',\n rightharpoonup: '\u21C0',\n lsh: '\u21B0',\n Lsh: '\u21B0',\n rsh: '\u21B1',\n Rsh: '\u21B1',\n ldsh: '\u21B2',\n rdsh: '\u21B3',\n hookleftarrow: '\u21A9',\n hookrightarrow: '\u21AA',\n mapstoleft: '\u21A4',\n mapstoup: '\u21A5',\n map: '\u21A6',\n mapsto: '\u21A6',\n mapstodown: '\u21A7',\n crarr: '\u21B5',\n nleftarrow: '\u219A',\n nleftrightarrow: '\u21AE',\n nrightarrow: '\u219B',\n nrarr: '\u219B',\n larrtl: '\u21A2',\n rarrtl: '\u21A3',\n leftarrowtail: '\u21A2',\n rightarrowtail: '\u21A3',\n twoheadleftarrow: '\u219E',\n twoheadrightarrow: '\u21A0',\n Larr: '\u219E',\n Rarr: '\u21A0',\n larrhk: '\u21A9',\n rarrhk: '\u21AA',\n larrlp: '\u21AB',\n looparrowleft: '\u21AB',\n rarrlp: '\u21AC',\n looparrowright: '\u21AC',\n harrw: '\u21AD',\n leftrightsquigarrow: '\u21AD',\n nrarrw: '\u219D\u0338',\n rarrw: '\u219D',\n rightsquigarrow: '\u219D',\n larrbfs: '\u291F',\n rarrbfs: '\u2920',\n nvHarr: '\u2904',\n nvlArr: '\u2902',\n nvrArr: '\u2903',\n larrfs: '\u291D',\n rarrfs: '\u291E',\n Map: '\u2905',\n larrsim: '\u2973',\n rarrsim: '\u2974',\n harrcir: '\u2948',\n Uarrocir: '\u2949',\n lurdshar: '\u294A',\n ldrdhar: '\u2967',\n ldrushar: '\u294B',\n rdldhar: '\u2969',\n lrhard: '\u296D',\n uharr: '\u21BE',\n uharl: '\u21BF',\n dharr: '\u21C2',\n dharl: '\u21C3',\n Uarr: '\u219F',\n Darr: '\u21A1',\n zigrarr: '\u21DD',\n nwArr: '\u21D6',\n neArr: '\u21D7',\n seArr: '\u21D8',\n swArr: '\u21D9',\n nharr: '\u21AE',\n nhArr: '\u21CE',\n nlarr: '\u219A',\n nlArr: '\u21CD',\n nrArr: '\u21CF',\n larrb: '\u21E4',\n LeftArrowBar: '\u21E4',\n rarrb: '\u21E5',\n RightArrowBar: '\u21E5',\n};\n\n/**\n * Geometric Shapes\n * @type {Record<string, string>}\n */\nexport const SHAPES = {\n square: '\u25A1',\n Square: '\u25A1',\n squ: '\u25A1',\n squf: '\u25AA',\n squarf: '\u25AA',\n blacksquar: '\u25AA',\n blacksquare: '\u25AA',\n FilledVerySmallSquare: '\u25AA',\n blk34: '\u2593',\n blk12: '\u2592',\n blk14: '\u2591',\n block: '\u2588',\n srect: '\u25AD',\n rect: '\u25AD',\n sdot: '\u22C5',\n sdotb: '\u22A1',\n dotsquare: '\u22A1',\n triangle: '\u25B5',\n tri: '\u25B5',\n trine: '\u25B5',\n utri: '\u25B5',\n triangledown: '\u25BF',\n dtri: '\u25BF',\n tridown: '\u25BF',\n triangleleft: '\u25C3',\n ltri: '\u25C3',\n triangleright: '\u25B9',\n rtri: '\u25B9',\n blacktriangle: '\u25B4',\n utrif: '\u25B4',\n blacktriangledown: '\u25BE',\n dtrif: '\u25BE',\n blacktriangleleft: '\u25C2',\n ltrif: '\u25C2',\n blacktriangleright: '\u25B8',\n rtrif: '\u25B8',\n loz: '\u25CA',\n lozenge: '\u25CA',\n blacklozenge: '\u29EB',\n lozf: '\u29EB',\n bigcirc: '\u25EF',\n xcirc: '\u25EF',\n circ: '\u02C6',\n Circle: '\u25CB',\n cir: '\u25CB',\n o: '\u25CB',\n bullet: '\u2022',\n bull: '\u2022',\n hellip: '\u2026',\n mldr: '\u2026',\n nldr: '\u2025',\n boxh: '\u2500',\n HorizontalLine: '\u2500',\n boxv: '\u2502',\n boxdr: '\u250C',\n boxdl: '\u2510',\n boxur: '\u2514',\n boxul: '\u2518',\n boxvr: '\u251C',\n boxvl: '\u2524',\n boxhd: '\u252C',\n boxhu: '\u2534',\n boxvh: '\u253C',\n boxH: '\u2550',\n boxV: '\u2551',\n boxdR: '\u2552',\n boxDr: '\u2553',\n boxDR: '\u2554',\n boxDl: '\u2555',\n boxdL: '\u2556',\n boxDL: '\u2557',\n boxuR: '\u2558',\n boxUr: '\u2559',\n boxUR: '\u255A',\n boxUl: '\u255C',\n boxuL: '\u255B',\n boxUL: '\u255D',\n boxvR: '\u255E',\n boxVr: '\u255F',\n boxVR: '\u2560',\n boxVl: '\u2562',\n boxvL: '\u2561',\n boxVL: '\u2563',\n boxHd: '\u2564',\n boxhD: '\u2565',\n boxHD: '\u2566',\n boxHu: '\u2567',\n boxhU: '\u2568',\n boxHU: '\u2569',\n boxvH: '\u256A',\n boxVh: '\u256B',\n boxVH: '\u256C',\n};\n\n/**\n * Punctuation & Diacritics\n * @type {Record<string, string>}\n */\nexport const PUNCTUATION = {\n excl: '!',\n iexcl: '\u00A1',\n brvbar: '\u00A6',\n sect: '\u00A7',\n uml: '\u00A8',\n copy: '\u00A9',\n ordf: '\u00AA',\n laquo: '\u00AB',\n not: '\u00AC',\n shy: '\\u00ad',\n reg: '\u00AE',\n macr: '\u00AF',\n deg: '\u00B0',\n plusmn: '\u00B1',\n sup2: '\u00B2',\n sup3: '\u00B3',\n acute: '\u00B4',\n micro: '\u00B5',\n para: '\u00B6',\n middot: '\u00B7',\n cedil: '\u00B8',\n sup1: '\u00B9',\n ordm: '\u00BA',\n raquo: '\u00BB',\n frac14: '\u00BC',\n frac12: '\u00BD',\n frac34: '\u00BE',\n iquest: '\u00BF',\n nbsp: '\\u00a0',\n comma: ',',\n period: '.',\n colon: ':',\n semi: ';',\n vert: '|',\n Verbar: '\u2016',\n verbar: '|',\n dblac: '\u02DD',\n circ: '\u02C6',\n caron: '\u02C7',\n breve: '\u02D8',\n dot: '\u02D9',\n ring: '\u02DA',\n ogon: '\u02DB',\n tilde: '\u02DC',\n DiacriticalGrave: '`',\n DiacriticalAcute: '\u00B4',\n DiacriticalTilde: '\u02DC',\n DiacriticalDot: '\u02D9',\n DiacriticalDoubleAcute: '\u02DD',\n grave: '`',\n};\n\n/**\n * Currency Symbols\n * @type {Record<string, string>}\n */\nexport const CURRENCY = {\n cent: '\u00A2',\n pound: '\u00A3',\n curren: '\u00A4',\n yen: '\u00A5',\n euro: '\u20AC',\n dollar: '$',\n fnof: '\u0192',\n inr: '\u20B9',\n af: '\u060B',\n birr: '\u1265\u122D',\n peso: '\u20B1',\n rub: '\u20BD',\n won: '\u20A9',\n yuan: '\u00A5',\n cedil: '\u00B8',\n};\n\n/**\n * Fractions\n * @type {Record<string, string>}\n */\nexport const FRACTIONS = {\n frac12: '\u00BD',\n half: '\u00BD',\n frac13: '\u2153',\n frac14: '\u00BC',\n frac15: '\u2155',\n frac16: '\u2159',\n frac18: '\u215B',\n frac23: '\u2154',\n frac25: '\u2156',\n frac34: '\u00BE',\n frac35: '\u2157',\n frac38: '\u215C',\n frac45: '\u2158',\n frac56: '\u215A',\n frac58: '\u215D',\n frac78: '\u215E',\n frasl: '\u2044',\n};\n\n/**\n * Miscellaneous Symbols\n * @type {Record<string, string>}\n */\nexport const MISC_SYMBOLS = {\n trade: '\u2122',\n TRADE: '\u2122',\n telrec: '\u2315',\n target: '\u2316',\n ulcorn: '\u231C',\n ulcorner: '\u231C',\n urcorn: '\u231D',\n urcorner: '\u231D',\n dlcorn: '\u231E',\n llcorner: '\u231E',\n drcorn: '\u231F',\n lrcorner: '\u231F',\n intercal: '\u22BA',\n intcal: '\u22BA',\n oplus: '\u2295',\n CirclePlus: '\u2295',\n ominus: '\u2296',\n CircleMinus: '\u2296',\n otimes: '\u2297',\n CircleTimes: '\u2297',\n osol: '\u2298',\n odot: '\u2299',\n CircleDot: '\u2299',\n oast: '\u229B',\n circledast: '\u229B',\n odash: '\u229D',\n circleddash: '\u229D',\n ocirc: '\u229A',\n circledcirc: '\u229A',\n boxplus: '\u229E',\n plusb: '\u229E',\n boxminus: '\u229F',\n minusb: '\u229F',\n boxtimes: '\u22A0',\n timesb: '\u22A0',\n boxdot: '\u22A1',\n sdotb: '\u22A1',\n veebar: '\u22BB',\n vee: '\u2228',\n barvee: '\u22BD',\n and: '\u2227',\n wedge: '\u2227',\n Cap: '\u22D2',\n Cup: '\u22D3',\n Fork: '\u22D4',\n pitchfork: '\u22D4',\n epar: '\u22D5',\n ltlarr: '\u2976',\n nvap: '\u224D\u20D2',\n nvsim: '\u223C\u20D2',\n nvge: '\u2265\u20D2',\n nvle: '\u2264\u20D2',\n nvlt: '<\u20D2',\n nvgt: '>\u20D2',\n nvltrie: '\u22B4\u20D2',\n nvrtrie: '\u22B5\u20D2',\n Vdash: '\u22A9',\n dashv: '\u22A3',\n vDash: '\u22A8',\n Vvdash: '\u22AA',\n nvdash: '\u22AC',\n nvDash: '\u22AD',\n nVdash: '\u22AE',\n nVDash: '\u22AF',\n};\n\nexport const XML = {\n amp: \"&\",\n apos: \"'\",\n gt: \">\",\n lt: \"<\",\n quot: \"\\\"\"\n}\nexport const COMMON_HTML = {\n nbsp: '\\u00a0',\n copy: '\\u00a9',\n reg: '\\u00ae',\n trade: '\\u2122',\n mdash: '\\u2014',\n ndash: '\\u2013',\n hellip: '\\u2026',\n laquo: '\\u00ab',\n raquo: '\\u00bb',\n lsquo: '\\u2018',\n rsquo: '\\u2019',\n ldquo: '\\u201c',\n rdquo: '\\u201d',\n bull: '\\u2022',\n para: '\\u00b6',\n sect: '\\u00a7',\n deg: '\\u00b0',\n frac12: '\\u00bd',\n frac14: '\\u00bc',\n frac34: '\\u00be',\n}\n// ---------------------------------------------------------------------------\n// Note: NUMERIC_ENTITIES (&#NNN; / &#xHH;) are handled by the scanner directly\n// via String.fromCodePoint() without any map lookup.\n// ---------------------------------------------------------------------------", "// ---------------------------------------------------------------------------\n// Built-in named entity map (name \u2192 replacement string)\n// No regex, no {regex,val} objects \u2014 just flat key/value pairs.\n// ---------------------------------------------------------------------------\n\nimport { XML as DEFAULT_XML_ENTITIES } from \"./entities.js\"\n\n// ---------------------------------------------------------------------------\n// Entity hook action constants\n// ---------------------------------------------------------------------------\n\n/**\n * Action constants for `onExternalEntity` and `onInputEntity` hooks.\n *\n * Use these instead of raw strings to avoid typos:\n *\n * @example\n * import EntityDecoder, { ENTITY_ACTION } from './EntityDecoder.js';\n * const dec = new EntityDecoder({\n * onInputEntity: (name, value) => ENTITY_ACTION.BLOCK,\n * });\n */\nexport const ENTITY_ACTION = Object.freeze({\n /** Resolve and expand the entity normally. */\n ALLOW: 'allow',\n /** Silently skip this entity \u2014 it will not be registered. */\n BLOCK: 'block',\n /** Throw an error, aborting entity registration entirely. */\n THROW: 'throw',\n});\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst SPECIAL_CHARS = new Set('!?\\\\\\\\/[]$%{}^&*()<>|+');\n\n/**\n * Validate that an entity name contains no dangerous characters.\n * @param {string} name\n * @returns {string} the name, unchanged\n * @throws {Error} on invalid characters\n */\nfunction validateEntityName(name) {\n if (name[0] === '#') {\n throw new Error(`[EntityReplacer] Invalid character '#' in entity name: \"${name}\"`);\n }\n for (const ch of name) {\n if (SPECIAL_CHARS.has(ch)) {\n throw new Error(`[EntityReplacer] Invalid character '${ch}' in entity name: \"${name}\"`);\n }\n }\n return name;\n}\n\n/**\n * Merge one or more entity maps into a flat name\u2192string map.\n * Accepts either:\n * - plain string values: { amp: '&' }\n * - legacy {regex,val} / {regx,val}: { lt: { regex: /.../, val: '<' } }\n *\n * Values containing '&' are skipped (recursive expansion risk).\n *\n * @param {...object} maps\n * @returns {Record<string, string>}\n */\nfunction mergeEntityMaps(...maps) {\n const out = Object.create(null);\n for (const map of maps) {\n if (!map) continue;\n for (const key of Object.keys(map)) {\n const raw = map[key];\n if (typeof raw === 'string') {\n out[key] = raw;\n } else if (raw && typeof raw === 'object' && raw.val !== undefined) {\n // Legacy {regex,val} or {regx,val} \u2014 extract the string val only\n const val = raw.val;\n if (typeof val === 'string') {\n out[key] = val;\n }\n // function vals are not supported in the scanner \u2014 skip\n }\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// applyLimitsTo helpers\n// ---------------------------------------------------------------------------\n\nconst LIMIT_TIER_EXTERNAL = 'external'; // input/runtime + persistent external maps\nconst LIMIT_TIER_BASE = 'base'; // DEFAULT_XML_ENTITIES + namedEntities (system) maps\nconst LIMIT_TIER_ALL = 'all'; // every entity regardless of tier\n\n/**\n * Resolve `applyLimitsTo` option into a normalised Set of tier strings.\n * Accepted values: 'external' | 'base' | 'all' | string[]\n * Default: 'external' (only untrusted injected entities are counted).\n * @param {string|string[]|undefined} raw\n * @returns {Set<string>}\n */\nfunction parseLimitTiers(raw) {\n if (!raw || raw === LIMIT_TIER_EXTERNAL) return new Set([LIMIT_TIER_EXTERNAL]);\n if (raw === LIMIT_TIER_ALL) return new Set([LIMIT_TIER_ALL]);\n if (raw === LIMIT_TIER_BASE) return new Set([LIMIT_TIER_BASE]);\n if (Array.isArray(raw)) return new Set(raw);\n return new Set([LIMIT_TIER_EXTERNAL]); // safe default for unrecognised values\n}\n\n// ---------------------------------------------------------------------------\n// NCR (Numeric Character Reference) classification\n// ---------------------------------------------------------------------------\n\n// Severity order \u2014 higher number = stricter action.\n// Used to enforce minimum action levels for specific codepoint ranges.\nconst NCR_LEVEL = Object.freeze({ allow: 0, leave: 1, remove: 2, throw: 3 });\n\n// XML 1.0 \u00A72.2: allowed chars are #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]\n// Restricted C0: U+0001\u2013U+001F excluding U+0009, U+000A, U+000D\nconst XML10_ALLOWED_C0 = new Set([0x09, 0x0A, 0x0D]);\n\n/**\n * Parse the `ncr` constructor option into flat, hot-path-friendly fields.\n * @param {object|undefined} ncr\n * @returns {{ xmlVersion: number, onLevel: number, nullLevel: number }}\n */\nfunction parseNCRConfig(ncr) {\n if (!ncr) {\n return { xmlVersion: 1.0, onLevel: NCR_LEVEL.allow, nullLevel: NCR_LEVEL.remove };\n }\n const xmlVersion = ncr.xmlVersion === 1.1 ? 1.1 : 1.0;\n const onLevel = NCR_LEVEL[ncr.onNCR] ?? NCR_LEVEL.allow;\n const nullLevel = NCR_LEVEL[ncr.nullNCR] ?? NCR_LEVEL.remove;\n // 'allow' is not meaningful for null \u2014 clamp to at least 'remove'\n const clampedNull = Math.max(nullLevel, NCR_LEVEL.remove);\n return { xmlVersion, onLevel, nullLevel: clampedNull };\n}\n\n// ---------------------------------------------------------------------------\n// EntityReplacer\n// ---------------------------------------------------------------------------\n\n/**\n * Single-pass, zero-regex entity replacer for XML/HTML content.\n *\n * Algorithm: scan the string once for '&', read to ';', resolve via map\n * or direct codepoint conversion, build output chunks, join once at the end.\n *\n * Entity lookup priority (highest \u2192 lowest):\n * 1. input / runtime (DOCTYPE entities for current document)\n * 2. persistent external (survive across documents)\n * 3. base named map (DEFAULT_XML_ENTITIES + user-supplied namedEntities)\n *\n * Both input and external resolve as the 'external' tier for limit purposes.\n * Base map entities resolve as the 'base' tier.\n *\n * Numeric / hex references (&#NNN; / &#xHH;) are resolved directly via\n * String.fromCodePoint() \u2014 no map needed. They count as 'base' tier.\n *\n * @example\n * const replacer = new EntityReplacer({ namedEntities: COMMON_HTML });\n * replacer.setExternalEntities({ brand: 'Acme' });\n *\n * const instance = replacer.reset();\n * instance.addInputEntities({ version: '1.0' });\n * instance.encode('&brand; v&version; &lt;'); // 'Acme v1.0 <'\n */\nexport default class EntityDecoder {\n /**\n * @param {object} [options]\n * @param {object|null} [options.namedEntities] \u2014 extra named entities merged into base map\n * @param {object} [options.limit] \u2014 security limits\n * @param {number} [options.limit.maxTotalExpansions=0] \u2014 0 = unlimited\n * @param {number} [options.limit.maxExpandedLength=0] \u2014 0 = unlimited\n * @param {'external'|'base'|'all'|string[]} [options.limit.applyLimitsTo='external']\n * Which entity tiers count against the security limits:\n * - 'external' (default) \u2014 only input/runtime + persistent external entities\n * - 'base' \u2014 only DEFAULT_XML_ENTITIES + namedEntities\n * - 'all' \u2014 every entity regardless of tier\n * - string[] \u2014 explicit combination, e.g. ['external', 'base']\n * @param {((resolved: string, original: string) => string)|null} [options.postCheck=null]\n * @param {string[]} [options.remove=[]] \u2014 entity names (e.g. ['nbsp', '#13']) to delete (replace with empty string)\n * @param {string[]} [options.leave=[]] \u2014 entity names to keep as literal (unchanged in output)\n * @param {object} [options.ncr] \u2014 Numeric Character Reference controls\n * @param {1.0|1.1} [options.ncr.xmlVersion=1.0]\n * XML version governing which codepoint ranges are restricted:\n * - 1.0 \u2014 C0 controls U+0001\u2013U+001F (except U+0009/000A/000D) are prohibited\n * - 1.1 \u2014 C0 controls are allowed when written as NCRs; C1 (U+007F\u2013U+009F) decoded as-is\n * @param {'allow'|'leave'|'remove'|'throw'} [options.ncr.onNCR='allow']\n * Base action for numeric references. Severity order: allow < leave < remove < throw.\n * For codepoint ranges that carry a minimum level (surrogates \u2192 remove, XML 1.0 C0 \u2192 remove),\n * the effective action is max(onNCR, rangeMinimum).\n * @param {'remove'|'throw'} [options.ncr.nullNCR='remove']\n * Action for U+0000 (null). 'allow' and 'leave' are clamped to 'remove' since null is never safe.\n * @param {((name: string, value: string) => 'allow'|'block'|'throw')|null} [options.onExternalEntity=null]\n * Hook called when an external entity is registered via `setExternalEntities()` or\n * `addExternalEntity()`. Return `ENTITY_ACTION.ALLOW` to accept the entity,\n * `ENTITY_ACTION.BLOCK` to silently skip it, or `ENTITY_ACTION.THROW` to abort with an error.\n * @param {((name: string, value: string) => 'allow'|'block'|'throw')|null} [options.onInputEntity=null]\n * Hook called when an input entity is registered via `addInputEntities()`. Return\n * `ENTITY_ACTION.ALLOW` to accept, `ENTITY_ACTION.BLOCK` to silently skip, or\n * `ENTITY_ACTION.THROW` to abort with an error.\n */\n constructor(options = {}) {\n this._limit = options.limit || {};\n this._maxTotalExpansions = this._limit.maxTotalExpansions || 0;\n this._maxExpandedLength = this._limit.maxExpandedLength || 0;\n this._postCheck = typeof options.postCheck === 'function' ? options.postCheck : r => r;\n this._limitTiers = parseLimitTiers(this._limit.applyLimitsTo ?? LIMIT_TIER_EXTERNAL);\n this._numericAllowed = options.numericAllowed ?? true;\n // Base map: DEFAULT_XML_ENTITIES + user-supplied extras. Immutable after construction.\n this._baseMap = mergeEntityMaps(DEFAULT_XML_ENTITIES, options.namedEntities || null);\n\n // Persistent external entities \u2014 survive across documents.\n // Stored as a separate map so reset() never touches them.\n /** @type {Record<string, string>} */\n this._externalMap = Object.create(null);\n\n // Input / runtime entities \u2014 current document only, wiped on reset().\n /** @type {Record<string, string>} */\n this._inputMap = Object.create(null);\n\n // Per-document counters\n this._totalExpansions = 0;\n this._expandedLength = 0;\n\n // --- New: remove / leave sets ---\n /** @type {Set<string>} */\n this._removeSet = new Set(options.remove && Array.isArray(options.remove) ? options.remove : []);\n /** @type {Set<string>} */\n this._leaveSet = new Set(options.leave && Array.isArray(options.leave) ? options.leave : []);\n\n // --- NCR config (parsed into flat fields for hot-path speed) ---\n const ncrCfg = parseNCRConfig(options.ncr);\n this._ncrXmlVersion = ncrCfg.xmlVersion;\n this._ncrOnLevel = ncrCfg.onLevel;\n this._ncrNullLevel = ncrCfg.nullLevel;\n\n // --- Registration hooks ---\n /** @type {((name: string, value: string) => 'allow'|'block'|'throw')|null} */\n this._onExternalEntity = typeof options.onExternalEntity === 'function'\n ? options.onExternalEntity\n : null;\n /** @type {((name: string, value: string) => 'allow'|'block'|'throw')|null} */\n this._onInputEntity = typeof options.onInputEntity === 'function'\n ? options.onInputEntity\n : null;\n }\n\n // -------------------------------------------------------------------------\n // Private: registration hook dispatch\n // -------------------------------------------------------------------------\n\n /**\n * Invoke a registration hook for a single entity name/value pair.\n * Returns true when the entity should be accepted, false when it should be\n * silently skipped (BLOCK), and throws when the hook returns THROW.\n *\n * @param {((name: string, value: string) => 'allow'|'block'|'throw')|null} hook\n * @param {string} name\n * @param {string} value\n * @param {string} context \u2014 used in error messages ('external' | 'input')\n * @returns {boolean} true = accept, false = skip\n */\n _applyRegistrationHook(hook, name, value, context) {\n if (!hook) return true; // no hook \u2192 always accept\n const action = hook(name, value);\n if (action === ENTITY_ACTION.BLOCK) return false;\n if (action === ENTITY_ACTION.THROW) {\n throw new Error(\n `[EntityDecoder] Registration of ${context} entity \"&${name};\" was rejected by hook`\n );\n }\n return true; // ALLOW or any unknown return value \u2192 accept\n }\n\n // -------------------------------------------------------------------------\n // Persistent external entity registration\n // -------------------------------------------------------------------------\n\n /**\n * Replace the full set of persistent external entities.\n * All keys are validated \u2014 throws on invalid characters.\n * If `onExternalEntity` is set, it is called once per entry; entries that\n * return `ENTITY_ACTION.BLOCK` are silently omitted, `ENTITY_ACTION.THROW`\n * aborts the whole call.\n * @param {Record<string, string | { regex?: RegExp, val: string }>} map\n */\n setExternalEntities(map) {\n if (map) {\n for (const key of Object.keys(map)) {\n validateEntityName(key);\n }\n }\n if (!this._onExternalEntity) {\n this._externalMap = mergeEntityMaps(map);\n return;\n }\n // Hook present \u2014 resolve values first, then filter\n const flat = mergeEntityMaps(map);\n const filtered = Object.create(null);\n for (const [name, value] of Object.entries(flat)) {\n if (this._applyRegistrationHook(this._onExternalEntity, name, value, 'external')) {\n filtered[name] = value;\n }\n }\n this._externalMap = filtered;\n }\n\n /**\n * Add a single persistent external entity.\n * If `onExternalEntity` is set it is called before the entity is stored;\n * `ENTITY_ACTION.BLOCK` silently skips storage, `ENTITY_ACTION.THROW` raises.\n * @param {string} key\n * @param {string} value\n */\n addExternalEntity(key, value) {\n validateEntityName(key);\n if (typeof value === 'string' && value.indexOf('&') === -1) {\n if (this._applyRegistrationHook(this._onExternalEntity, key, value, 'external')) {\n this._externalMap[key] = value;\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Input / runtime entity registration (per document)\n // -------------------------------------------------------------------------\n\n /**\n * Inject DOCTYPE entities for the current document.\n * Also resets per-document expansion counters.\n * If `onInputEntity` is set it is called once per entry; entries returning\n * `ENTITY_ACTION.BLOCK` are silently omitted, `ENTITY_ACTION.THROW` aborts.\n * @param {Record<string, string | { regx?: RegExp, regex?: RegExp, val: string }>} map\n */\n addInputEntities(map) {\n this._totalExpansions = 0;\n this._expandedLength = 0;\n if (!this._onInputEntity) {\n this._inputMap = mergeEntityMaps(map);\n return;\n }\n const flat = mergeEntityMaps(map);\n const filtered = Object.create(null);\n for (const [name, value] of Object.entries(flat)) {\n if (this._applyRegistrationHook(this._onInputEntity, name, value, 'input')) {\n filtered[name] = value;\n }\n }\n this._inputMap = filtered;\n }\n\n // -------------------------------------------------------------------------\n // Per-document reset\n // -------------------------------------------------------------------------\n\n /**\n * Wipe input/runtime entities and reset counters.\n * Call this before processing each new document.\n * @returns {this}\n */\n reset() {\n this._inputMap = Object.create(null);\n this._totalExpansions = 0;\n this._expandedLength = 0;\n return this;\n }\n\n // -------------------------------------------------------------------------\n // XML version (can be set after construction, e.g. once parser reads <?xml?>)\n // -------------------------------------------------------------------------\n\n /**\n * Update the XML version used for NCR classification.\n * Call this as soon as the document's `<?xml version=\"...\">` declaration is parsed.\n * @param {1.0|1.1|number} version\n */\n setXmlVersion(version) {\n this._ncrXmlVersion = version === 1.1 ? 1.1 : 1.0;\n }\n\n // -------------------------------------------------------------------------\n // Primary API\n // -------------------------------------------------------------------------\n\n /**\n * Replace all entity references in `str` in a single pass.\n *\n * @param {string} str\n * @returns {string}\n */\n decode(str) {\n if (typeof str !== 'string' || str.length === 0) return str;\n //TODO: check if needed\n if (str.indexOf('&') === -1) return str; // fast path \u2014 no entities at all\n\n const original = str;\n const chunks = [];\n const len = str.length;\n let last = 0; // start of next unprocessed literal chunk\n let i = 0;\n\n const limitExpansions = this._maxTotalExpansions > 0;\n const limitLength = this._maxExpandedLength > 0;\n const checkLimits = limitExpansions || limitLength;\n\n while (i < len) {\n // Scan forward to next '&'\n if (str.charCodeAt(i) !== 38 /* '&' */) { i++; continue; }\n\n // --- Found '&' at position i ---\n\n // Scan forward to ';'\n let j = i + 1;\n while (j < len && str.charCodeAt(j) !== 59 /* ';' */ && (j - i) <= 32) j++;\n\n if (j >= len || str.charCodeAt(j) !== 59) {\n // No closing ';' within window \u2014 treat '&' as literal\n i++;\n continue;\n }\n\n // Raw token between '&' and ';' (exclusive)\n const token = str.slice(i + 1, j);\n if (token.length === 0) { i++; continue; }\n\n let replacement;\n let tier; // which limit tier this entity belongs to\n\n if (this._removeSet.has(token)) {\n // Remove entity: replace with empty string\n replacement = '';\n // If entity was unknown (replacement undefined), we still need a tier for limits.\n // Treat as external tier because it's user-directed removal of an unknown reference.\n if (tier === undefined) {\n tier = LIMIT_TIER_EXTERNAL;\n }\n } else if (this._leaveSet.has(token)) {\n // Do not replace \u2014 keep original &token; as literal\n i++;\n continue;\n } else if (token.charCodeAt(0) === 35 /* '#' */) {\n // ---- Numeric / NCR reference ----\n // NCR classification always runs first \u2014 prohibited codepoints must be\n // caught regardless of numericAllowed.\n const ncrResult = this._resolveNCR(token);\n if (ncrResult === undefined) {\n // 'leave' action \u2014 keep original &token; as-is\n i++;\n continue;\n }\n replacement = ncrResult; // '' for remove, char string for allow\n tier = LIMIT_TIER_BASE;\n } else {\n // ---- Named reference ----\n const resolved = this._resolveName(token);\n replacement = resolved?.value;\n tier = resolved?.tier;\n }\n\n if (replacement === undefined) {\n // Unknown entity \u2014 leave as-is, advance past '&' only\n i++;\n continue;\n }\n\n // Flush literal chunk before this entity\n if (i > last) chunks.push(str.slice(last, i));\n chunks.push(replacement);\n last = j + 1; // skip past ';'\n i = last;\n\n // Apply expansion limits only if this tier is being tracked\n if (checkLimits && this._tierCounts(tier)) {\n if (limitExpansions) {\n this._totalExpansions++;\n if (this._totalExpansions > this._maxTotalExpansions) {\n throw new Error(\n `[EntityReplacer] Entity expansion count limit exceeded: ` +\n `${this._totalExpansions} > ${this._maxTotalExpansions}`\n );\n }\n }\n if (limitLength) {\n // delta: replacement.length minus the raw &token; length (token.length + 2 for '&' and ';')\n const delta = replacement.length - (token.length + 2);\n if (delta > 0) {\n this._expandedLength += delta;\n if (this._expandedLength > this._maxExpandedLength) {\n throw new Error(\n `[EntityReplacer] Expanded content length limit exceeded: ` +\n `${this._expandedLength} > ${this._maxExpandedLength}`\n );\n }\n }\n }\n }\n }\n\n // Flush trailing literal\n if (last < len) chunks.push(str.slice(last));\n\n // If nothing was replaced, chunks is empty \u2014 return original\n const result = chunks.length === 0 ? str : chunks.join('');\n\n return this._postCheck(result, original);\n }\n\n // -------------------------------------------------------------------------\n // Private: limit tier check\n // -------------------------------------------------------------------------\n\n /**\n * Returns true if a resolved entity of the given tier should count\n * against the expansion/length limits.\n * @param {string} tier \u2014 LIMIT_TIER_EXTERNAL | LIMIT_TIER_BASE\n * @returns {boolean}\n */\n _tierCounts(tier) {\n if (this._limitTiers.has(LIMIT_TIER_ALL)) return true;\n return this._limitTiers.has(tier);\n }\n\n // -------------------------------------------------------------------------\n // Private: entity resolution\n // -------------------------------------------------------------------------\n\n /**\n * Resolve a named entity token (without & and ;).\n * Priority: inputMap > externalMap > baseMap\n * Returns the resolved value tagged with its limit tier.\n *\n * @param {string} name\n * @returns {{ value: string, tier: string }|undefined}\n */\n _resolveName(name) {\n // input and external both count as 'external' tier for limit purposes \u2014\n // they are injected at runtime and are the untrusted surface.\n if (name in this._inputMap) return { value: this._inputMap[name], tier: LIMIT_TIER_EXTERNAL };\n if (name in this._externalMap) return { value: this._externalMap[name], tier: LIMIT_TIER_EXTERNAL };\n if (name in this._baseMap) return { value: this._baseMap[name], tier: LIMIT_TIER_BASE };\n return undefined;\n }\n\n /**\n * Classify a codepoint and return the minimum action level that must be applied.\n * Returns -1 when no minimum is imposed (normal allow path).\n *\n * Ranges checked (in priority order):\n * 1. U+0000 \u2014 null, governed by nullNCR (always \u2265 remove)\n * 2. U+D800\u2013U+DFFF \u2014 surrogates, always prohibited (min: remove)\n * 3. U+0001\u2013U+001F \\ {0x09,0x0A,0x0D} \u2014 XML 1.0 restricted C0 (min: remove)\n * (skipped in XML 1.1 \u2014 C0 controls are allowed when written as NCRs)\n *\n * @param {number} cp \u2014 codepoint\n * @returns {number} \u2014 minimum NCR_LEVEL value, or -1 for no restriction\n */\n _classifyNCR(cp) {\n // 1. Null\n if (cp === 0) return this._ncrNullLevel;\n\n // 2. Surrogates \u2014 always prohibited, minimum 'remove'\n if (cp >= 0xD800 && cp <= 0xDFFF) return NCR_LEVEL.remove;\n\n // 3. XML 1.0 restricted C0 controls\n if (this._ncrXmlVersion === 1.0) {\n if (cp >= 0x01 && cp <= 0x1F && !XML10_ALLOWED_C0.has(cp)) return NCR_LEVEL.remove;\n }\n\n return -1; // no restriction\n }\n\n /**\n * Execute a resolved NCR action.\n *\n * @param {number} action \u2014 NCR_LEVEL value\n * @param {string} token \u2014 raw token (e.g. '#38') for error messages\n * @param {number} cp \u2014 codepoint, used only for error messages\n * @returns {string|undefined}\n * - decoded character string \u2192 'allow'\n * - '' \u2192 'remove'\n * - undefined \u2192 'leave' (caller must skip past '&' only)\n * - throws Error \u2192 'throw'\n */\n _applyNCRAction(action, token, cp) {\n switch (action) {\n case NCR_LEVEL.allow: return String.fromCodePoint(cp);\n case NCR_LEVEL.remove: return '';\n case NCR_LEVEL.leave: return undefined; // signal: keep literal\n case NCR_LEVEL.throw:\n throw new Error(\n `[EntityDecoder] Prohibited numeric character reference ` +\n `&${token}; (U+${cp.toString(16).toUpperCase().padStart(4, '0')})`\n );\n default: return String.fromCodePoint(cp);\n }\n }\n\n /**\n * Full NCR resolution pipeline for a numeric token.\n *\n * Steps:\n * 1. Parse the codepoint (decimal or hex).\n * 2. Validate the raw codepoint range (NaN, <0, >0x10FFFF).\n * 3. If numericAllowed is false and no minimum restriction applies \u2192 leave as-is.\n * 4. Classify the codepoint to find the minimum required action level.\n * 5. Resolve effective action = max(onNCR, minimum).\n * 6. Apply and return.\n *\n * @param {string} token \u2014 e.g. '#38', '#x26', '#X26'\n * @returns {string|undefined}\n * - string (incl. '') \u2014 replacement ('' = remove)\n * - undefined \u2014 leave original &token; as-is\n */\n _resolveNCR(token) {\n // Step 1: parse codepoint\n const second = token.charCodeAt(1);\n let cp;\n if (second === 120 /* x */ || second === 88 /* X */) {\n cp = parseInt(token.slice(2), 16);\n } else {\n cp = parseInt(token.slice(1), 10);\n }\n\n // Step 2: out-of-range \u2192 leave as-is unconditionally\n if (Number.isNaN(cp) || cp < 0 || cp > 0x10FFFF) return undefined;\n\n // Step 3: classify to get minimum action level\n const minimum = this._classifyNCR(cp);\n\n // Step 4: if numericAllowed is false and no hard minimum \u2192 leave\n if (!this._numericAllowed && minimum < NCR_LEVEL.remove) return undefined;\n\n // Step 5: effective action = max(configured onNCR, range minimum)\n const effective = minimum === -1\n ? this._ncrOnLevel\n : Math.max(this._ncrOnLevel, minimum);\n\n // Step 6: apply\n return this._applyNCRAction(effective, token, cp);\n }\n}", "import { DANGEROUS_PROPERTY_NAMES, criticalProperties } from \"../util.js\";\nimport { COMMON_HTML, CURRENCY } from '@nodable/entities';\n\nconst defaultOnDangerousProperty = (name) => {\n if (DANGEROUS_PROPERTY_NAMES.includes(name)) {\n return \"__\" + name;\n }\n return name;\n};\n\n\nexport const defaultOptions = {\n preserveOrder: false,\n attributeNamePrefix: '@_',\n attributesGroupName: false,\n textNodeName: '#text',\n ignoreAttributes: true,\n removeNSPrefix: false, // remove NS from tag name or attribute name if true\n allowBooleanAttributes: false, //a tag can have attributes without any value\n //ignoreRootElement : false,\n parseTagValue: true,\n parseAttributeValue: false,\n trimValues: true, //Trim string values of tag and attributes\n cdataPropName: false,\n numberParseOptions: {\n hex: true,\n leadingZeros: true,\n eNotation: true,\n unicode: false\n },\n tagValueProcessor: function (tagName, val) {\n return val;\n },\n attributeValueProcessor: function (attrName, val) {\n return val;\n },\n stopNodes: [], //nested tags will not be parsed even for errors\n alwaysCreateTextNode: false,\n isArray: () => false,\n commentPropName: false,\n unpairedTags: [],\n processEntities: true,\n htmlEntities: false,\n entityDecoder: null,\n ignoreDeclaration: false,\n ignorePiTags: false,\n transformTagName: false,\n transformAttributeName: false,\n updateTag: function (tagName, jPath, attrs) {\n return tagName\n },\n // skipEmptyListItem: false\n captureMetaData: false,\n maxNestedTags: 100,\n strictReservedNames: true,\n jPath: true, // if true, pass jPath string to callbacks; if false, pass matcher instance\n onDangerousProperty: defaultOnDangerousProperty\n};\n\n\n/**\n * Validates that a property name is safe to use\n * @param {string} propertyName - The property name to validate\n * @param {string} optionName - The option field name (for error message)\n * @throws {Error} If property name is dangerous\n */\nfunction validatePropertyName(propertyName, optionName) {\n if (typeof propertyName !== 'string') {\n return; // Only validate string property names\n }\n\n const normalized = propertyName.toLowerCase();\n if (DANGEROUS_PROPERTY_NAMES.some(dangerous => normalized === dangerous.toLowerCase())) {\n throw new Error(\n `[SECURITY] Invalid ${optionName}: \"${propertyName}\" is a reserved JavaScript keyword that could cause prototype pollution`\n );\n }\n\n if (criticalProperties.some(dangerous => normalized === dangerous.toLowerCase())) {\n throw new Error(\n `[SECURITY] Invalid ${optionName}: \"${propertyName}\" is a reserved JavaScript keyword that could cause prototype pollution`\n );\n }\n}\n\n/**\n * Normalizes processEntities option for backward compatibility\n * @param {boolean|object} value \n * @returns {object} Always returns normalized object\n */\nfunction normalizeProcessEntities(value, htmlEntities) {\n // Boolean backward compatibility\n if (typeof value === 'boolean') {\n return {\n enabled: value, // true or false\n maxEntitySize: 10000,\n maxExpansionDepth: 10000,\n maxTotalExpansions: Infinity,\n maxExpandedLength: 100000,\n maxEntityCount: 1000,\n allowedTags: null,\n tagFilter: null,\n appliesTo: \"all\",\n };\n }\n\n // Object config - merge with defaults\n if (typeof value === 'object' && value !== null) {\n return {\n enabled: value.enabled !== false,\n maxEntitySize: Math.max(1, value.maxEntitySize ?? 10000),\n maxExpansionDepth: Math.max(1, value.maxExpansionDepth ?? 10000),\n maxTotalExpansions: Math.max(1, value.maxTotalExpansions ?? Infinity),\n maxExpandedLength: Math.max(1, value.maxExpandedLength ?? 100000),\n maxEntityCount: Math.max(1, value.maxEntityCount ?? 1000),\n allowedTags: value.allowedTags ?? null,\n tagFilter: value.tagFilter ?? null,\n appliesTo: value.appliesTo ?? \"all\",\n };\n }\n\n // Default to enabled with limits\n return normalizeProcessEntities(true);\n}\n\nexport const buildOptions = function (options) {\n const built = Object.assign({}, defaultOptions, options);\n\n // Validate property names to prevent prototype pollution\n const propertyNameOptions = [\n { value: built.attributeNamePrefix, name: 'attributeNamePrefix' },\n { value: built.attributesGroupName, name: 'attributesGroupName' },\n { value: built.textNodeName, name: 'textNodeName' },\n { value: built.cdataPropName, name: 'cdataPropName' },\n { value: built.commentPropName, name: 'commentPropName' }\n ];\n\n for (const { value, name } of propertyNameOptions) {\n if (value) {\n validatePropertyName(value, name);\n }\n }\n\n if (built.onDangerousProperty === null) {\n built.onDangerousProperty = defaultOnDangerousProperty;\n }\n\n // Always normalize processEntities for backward compatibility and validation\n built.processEntities = normalizeProcessEntities(built.processEntities, built.htmlEntities);\n built.unpairedTagsSet = new Set(built.unpairedTags);\n // Convert old-style stopNodes for backward compatibility\n if (built.stopNodes && Array.isArray(built.stopNodes)) {\n built.stopNodes = built.stopNodes.map(node => {\n if (typeof node === 'string' && node.startsWith('*.')) {\n // Old syntax: *.tagname meant \"tagname anywhere\"\n // Convert to new syntax: ..tagname\n return '..' + node.substring(2);\n }\n return node;\n });\n }\n //console.debug(built.processEntities)\n return built;\n};", "'use strict';\n\nlet METADATA_SYMBOL;\n\nif (typeof Symbol !== \"function\") {\n METADATA_SYMBOL = \"@@xmlMetadata\";\n} else {\n METADATA_SYMBOL = Symbol(\"XML Node Metadata\");\n}\n\nexport default class XmlNode {\n constructor(tagname) {\n this.tagname = tagname;\n this.child = []; //nested tags, text, cdata, comments in order\n this[\":@\"] = Object.create(null); //attributes map\n }\n add(key, val) {\n // this.child.push( {name : key, val: val, isCdata: isCdata });\n if (key === \"__proto__\") key = \"#__proto__\";\n this.child.push({ [key]: val });\n }\n addChild(node, startIndex) {\n if (node.tagname === \"__proto__\") node.tagname = \"#__proto__\";\n if (node[\":@\"] && Object.keys(node[\":@\"]).length > 0) {\n this.child.push({ [node.tagname]: node.child, [\":@\"]: node[\":@\"] });\n } else {\n this.child.push({ [node.tagname]: node.child });\n }\n // if requested, add the startIndex\n this.addStartIndex(startIndex);\n }\n\n addStartIndex(startIndex) {\n if (startIndex !== undefined) {\n // Note: for now we just overwrite the metadata. If we had more complex metadata,\n // we might need to do an object append here: metadata = { ...metadata, startIndex }\n this.child[this.child.length - 1][METADATA_SYMBOL] = { startIndex };\n }\n }\n\n addEndIndex(endIndex) {\n const lastChild = this.child[this.child.length - 1];\n // endIndex is write-once: when updateTag drops a node, the last child is a\n // previously completed sibling whose endIndex must not be overwritten\n if (lastChild !== undefined && lastChild[METADATA_SYMBOL] !== undefined\n && lastChild[METADATA_SYMBOL].endIndex === undefined) {\n lastChild[METADATA_SYMBOL].endIndex = endIndex;\n }\n }\n /** symbol used for metadata */\n static getMetaDataSymbol() {\n return METADATA_SYMBOL;\n }\n}\n", "/**\n * xml-naming\n * Validates XML Name productions as defined in the XML 1.0 and 1.1 specifications.\n * Covers: Name, NCName, QName, NMToken, NMTokens\n *\n * XML 1.0 spec: https://www.w3.org/TR/xml/#NT-Name\n * XML 1.1 spec: https://www.w3.org/TR/xml11/#NT-NameStartChar\n * XML NS spec: https://www.w3.org/TR/xml-names/#NT-NCName\n */\n\n// ---------------------------------------------------------------------------\n// Character class strings \u2014 XML 1.0\n//\n// NameStartChar ::= \":\" | [A-Z] | \"_\" | [a-z]\n// | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF]\n// | [#x370-#x37D] | [#x37F-#x1FFF] <- split to exclude #x0487\n// | [#x200C-#x200D]\n// | [#x2070-#x218F] | [#x2C00-#x2FEF]\n// | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD]\n//\n// NameChar ::= NameStartChar | \"-\" | \".\" | [0-9]\n// | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]\n//\n// Note: \\u0487 (Combining Cyrillic Millions Sign) was added in Unicode 4.0,\n// after XML 1.0 was defined against Unicode 2.0. It falls inside the range\n// \\u037F-\\u1FFF but must be excluded. We split that range into\n// \\u037F-\\u0486 and \\u0488-\\u1FFF to exclude it explicitly.\n// ---------------------------------------------------------------------------\n\nconst nameStartChar10 =\n ':A-Za-z_' +\n '\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF' +\n '\\u0370-\\u037D' +\n '\\u037F-\\u0486\\u0488-\\u1FFF' + // split to exclude \\u0487\n '\\u200C-\\u200D' +\n '\\u2070-\\u218F' +\n '\\u2C00-\\u2FEF' +\n '\\u3001-\\uD7FF' +\n '\\uF900-\\uFDCF' +\n '\\uFDF0-\\uFFFD';\n\nconst nameChar10 =\n nameStartChar10 +\n '\\\\-\\\\.\\\\d' +\n '\\u00B7' +\n '\\u0300-\\u036F' +\n '\\u203F-\\u2040';\n\n// ---------------------------------------------------------------------------\n// Character class strings \u2014 XML 1.1\n//\n// Differences from XML 1.0:\n//\n// NameStartChar:\n// 1.0 has split ranges: \\u00C0-\\u00D6, \\u00D8-\\u00F6, \\u00F8-\\u02FF\n// 1.1 merges them into: \\u00C0-\\u02FF\n// (\\u00D7 x and \\u00F7 / are division symbols, excluded in both versions)\n//\n// 1.0 tops out at \\uFFFD (BMP only)\n// 1.1 adds \\u{10000}-\\u{EFFFF} (supplementary planes)\n// These require the /u flag on the RegExp \u2014 see buildRegexes below.\n//\n// NameChar:\n// 1.1 adds \\u0487 (Combining Cyrillic Millions Sign, added in Unicode 4.0)\n// ---------------------------------------------------------------------------\n\nconst nameStartChar11 =\n ':A-Za-z_' +\n '\\u00C0-\\u02FF' + // merged \u2014 1.0 had three split ranges here\n '\\u0370-\\u037D' +\n '\\u037F-\\u0486\\u0488-\\u1FFF' + // split to exclude \\u0487 (combining mark, never a NameStartChar)\n '\\u200C-\\u200D' +\n '\\u2070-\\u218F' +\n '\\u2C00-\\u2FEF' +\n '\\u3001-\\uD7FF' +\n '\\uF900-\\uFDCF' +\n '\\uFDF0-\\uFFFD' +\n '\\u{10000}-\\u{EFFFF}'; // supplementary planes \u2014 REQUIRES /u flag on RegExp\n\nconst nameChar11 =\n nameStartChar11 +\n '\\\\-\\\\.\\\\d' +\n '\\u00B7' +\n '\\u0300-\\u036F' +\n '\\u0487' + // Combining Cyrillic Millions Sign \u2014 valid in 1.1, not 1.0\n '\\u203F-\\u2040';\n\n// ---------------------------------------------------------------------------\n// Regex builders\n//\n// XML 1.0 regexes: no flags \u2014 BMP only, standard JS regex behaviour.\n// XML 1.1 regexes: /u flag \u2014 required for \\u{10000}-\\u{EFFFF} to match actual\n// supplementary code points rather than lone surrogates (which are illegal XML).\n// ---------------------------------------------------------------------------\n\nconst buildRegexes = (startChar, char, flags = '') => {\n const ncStart = startChar.replace(':', '');\n const ncChar = char.replace(':', '');\n const ncNamePat = `[${ncStart}][${ncChar}]*`;\n\n return {\n name: new RegExp(`^[${startChar}][${char}]*$`, flags),\n ncName: new RegExp(`^${ncNamePat}$`, flags),\n qName: new RegExp(`^${ncNamePat}(?::${ncNamePat})?$`, flags),\n nmToken: new RegExp(`^[${char}]+$`, flags),\n nmTokens: new RegExp(`^[${char}]+(?:\\\\s+[${char}]+)*$`, flags),\n };\n};\n\nconst regexes10 = buildRegexes(nameStartChar10, nameChar10); // no /u \u2014 BMP only\nconst regexes11 = buildRegexes(nameStartChar11, nameChar11, 'u'); // /u \u2014 enables \\u{10000}-\\u{EFFFF}\n\n// ---------------------------------------------------------------------------\n// ASCII-only fast path (opt-in, off by default)\n//\n// The XML 1.0 vs 1.1 NameStartChar/NameChar productions differ *only* in\n// their non-ASCII ranges (merged vs split Latin-1 ranges, \\u0487, and\n// supplementary planes). Restricted to ASCII, both versions collapse to the\n// same character classes, so a single regex pair covers both xmlVersion\n// values \u2014 no /u flag needed.\n//\n// Rationale: unicode-aware regexes (the /u flag, required for XML 1.1's\n// supplementary-plane range) are measurably slower in V8 than plain\n// non-unicode regexes on the same input, even when the input is pure ASCII.\n// For the common case \u2014 HTML/SVG ids, XML tags \u2014 names are ASCII, so callers\n// who know this can opt in to skip the unicode-aware matching path entirely.\n// This is a real but *conditional* win: mainly for XML 1.1 input (avoids /u),\n// or at scale where the larger unicode character classes add engine\n// overhead. It also changes behaviour (rejects legitimate non-ASCII XML\n// 1.0/1.1 names), so it must never be silently enabled \u2014 hence off by\n// default.\n// ---------------------------------------------------------------------------\n\nconst nameStartCharAscii = ':A-Za-z_';\nconst nameCharAscii = nameStartCharAscii + '\\\\-\\\\.\\\\d';\n\nconst regexesAscii = buildRegexes(nameStartCharAscii, nameCharAscii); // no /u \u2014 ASCII only\n\nconst getRegexes = (xmlVersion = '1.0', asciiOnly = false) => {\n if (asciiOnly) return regexesAscii;\n return xmlVersion === '1.1' ? regexes11 : regexes10;\n};\n\n// ---------------------------------------------------------------------------\n// Boolean validators\n// ---------------------------------------------------------------------------\n\n/**\n * Returns true if the string is a valid XML Name.\n * Colons are allowed anywhere (Name production).\n * Used for: DOCTYPE entity names, notation names, DTD element declarations.\n *\n * @param {{ xmlVersion?: '1.0'|'1.1', asciiOnly?: boolean }} [opts]\n * asciiOnly: skip unicode-aware matching, ASCII names only (default false).\n */\nexport const name = (str, { xmlVersion = '1.0', asciiOnly = false } = {}) =>\n getRegexes(xmlVersion, asciiOnly).name.test(str);\n\n/**\n * Returns true if the string is a valid NCName (Non-Colonized Name).\n * Colons are not permitted.\n * Used for: namespace prefixes, local names, SVG id attributes.\n *\n * @param {{ xmlVersion?: '1.0'|'1.1', asciiOnly?: boolean }} [opts]\n * asciiOnly: skip unicode-aware matching, ASCII names only (default false).\n */\nexport const ncName = (str, { xmlVersion = '1.0', asciiOnly = false } = {}) =>\n getRegexes(xmlVersion, asciiOnly).ncName.test(str);\n\n/**\n * Returns true if the string is a valid QName (Qualified Name).\n * Allows exactly one colon as a prefix separator: prefix:localName.\n * Used for: element and attribute names in namespace-aware XML/SVG.\n *\n * @param {{ xmlVersion?: '1.0'|'1.1', asciiOnly?: boolean }} [opts]\n * asciiOnly: skip unicode-aware matching, ASCII names only (default false).\n */\nexport const qName = (str, { xmlVersion = '1.0', asciiOnly = false } = {}) =>\n getRegexes(xmlVersion, asciiOnly).qName.test(str);\n\n/**\n * Returns true if the string is a valid NMToken.\n * Like Name but no restriction on the first character.\n * Used for: DTD NMTOKEN attribute values.\n *\n * @param {{ xmlVersion?: '1.0'|'1.1', asciiOnly?: boolean }} [opts]\n * asciiOnly: skip unicode-aware matching, ASCII names only (default false).\n */\nexport const nmToken = (str, { xmlVersion = '1.0', asciiOnly = false } = {}) =>\n getRegexes(xmlVersion, asciiOnly).nmToken.test(str);\n\n/**\n * Returns true if the string is a valid NMTokens value.\n * A whitespace-separated list of NMToken values.\n * Used for: DTD NMTOKENS attribute values.\n *\n * @param {{ xmlVersion?: '1.0'|'1.1', asciiOnly?: boolean }} [opts]\n * asciiOnly: skip unicode-aware matching, ASCII names only (default false).\n */\nexport const nmTokens = (str, { xmlVersion = '1.0', asciiOnly = false } = {}) =>\n getRegexes(xmlVersion, asciiOnly).nmTokens.test(str);\n\n// ---------------------------------------------------------------------------\n// Memoized validator factory\n//\n// Real documents reuse a small vocabulary of tag/attribute names across many\n// siblings (e.g. `id`, `class`, `href` repeated across hundreds of elements).\n// The plain boolean validators above re-run the regex on every call\n// regardless of repeats. `createValidator` returns a closure with a private\n// string -> boolean cache, so repeated names after the first become O(1)\n// lookups instead of regex tests.\n//\n// - opts (xmlVersion, asciiOnly) are fixed at creation time, so the regex is\n// resolved once, not on every call.\n// - The cache is private to the returned closure \u2014 no shared/global state,\n// no cross-caller pollution.\n// - `maxCacheSize` bounds memory: once the cache reaches this many entries,\n// it stops accepting new ones (existing entries keep serving hits; new\n// misses just fall through to the regex, uncached). This avoids unbounded\n// growth against adversarial/high-cardinality input (e.g. validating\n// attacker-supplied names with no repeats) without the cost/complexity of\n// a full LRU, and without the perf cliff of reset-and-refill thrashing.\n// - Call `.reset()` on the returned function to clear the cache manually\n// (e.g. between unrelated parse calls).\n// ---------------------------------------------------------------------------\n\nconst PRODUCTIONS = ['name', 'ncName', 'qName', 'nmToken', 'nmTokens'];\n\n/**\n * Returns a memoized boolean validator function for a single production,\n * with opts fixed at creation time.\n *\n * @param {'name'|'ncName'|'qName'|'nmToken'|'nmTokens'} production\n * @param {{ xmlVersion?: '1.0'|'1.1', asciiOnly?: boolean, maxCacheSize?: number }} [opts]\n * maxCacheSize: max number of distinct strings to cache (default 2048).\n * Once reached, new strings are validated but not cached; existing cached\n * entries keep being served.\n * @returns {((str: string) => boolean) & { reset: () => void }}\n */\nexport const createValidator = (production, { xmlVersion = '1.0', asciiOnly = false, maxCacheSize = 2048 } = {}) => {\n if (!PRODUCTIONS.includes(production)) {\n throw new TypeError(\n `Unknown production \"${production}\". Must be one of: ${PRODUCTIONS.join(', ')}`\n );\n }\n\n const regex = getRegexes(xmlVersion, asciiOnly)[production];\n let cache = new Map();\n\n const validator = (str) => {\n const cached = cache.get(str);\n if (cached !== undefined) return cached;\n\n const result = regex.test(str);\n if (cache.size < maxCacheSize) cache.set(str, result);\n return result;\n };\n\n validator.reset = () => { cache = new Map(); };\n\n return validator;\n};\n\n// ---------------------------------------------------------------------------\n// Diagnostic validator\n// ---------------------------------------------------------------------------\n\n/**\n * Validates a string against a named production and returns a detailed result.\n *\n * @param {string} str\n * @param {'name'|'ncName'|'qName'|'nmToken'|'nmTokens'} production\n * @param {{ xmlVersion?: '1.0'|'1.1', asciiOnly?: boolean }} [opts]\n * @returns {{ valid: boolean, production: string, input: string, reason?: string, position?: number }}\n */\nexport const validate = (str, production, { xmlVersion = '1.0', asciiOnly = false } = {}) => {\n if (!PRODUCTIONS.includes(production)) {\n throw new TypeError(\n `Unknown production \"${production}\". Must be one of: ${PRODUCTIONS.join(', ')}`\n );\n }\n\n const validators = { name, ncName, qName, nmToken, nmTokens };\n const isValid = validators[production](str, { xmlVersion, asciiOnly });\n\n if (isValid) return { valid: true, production, input: str };\n\n let reason = 'Does not match the production rules';\n let position;\n\n // Diagnostic fallback char checks must mirror the same character set the\n // boolean validator above used, or the reported reason/position could\n // contradict the `valid: false` result (e.g. flagging a char as illegal\n // that the unicode-aware check would have accepted).\n const startCharPattern = asciiOnly ? /^[:A-Za-z_]/ : /^[:A-Za-z_\\u00C0-\\uFFFD]/;\n const namePattern = asciiOnly ? /[\\w\\-\\\\.:]/ : /[\\w\\-\\\\.:\\u00B7\\u00C0-\\uFFFD]/;\n\n if (str.length === 0) {\n reason = 'Input is empty';\n } else if (production === 'ncName' && str.includes(':')) {\n position = str.indexOf(':');\n reason = 'Colon is not allowed in NCName';\n } else if (production === 'qName' && str.startsWith(':')) {\n reason = 'QName cannot start with a colon';\n position = 0;\n } else if (production === 'qName' && str.endsWith(':')) {\n reason = 'QName cannot end with a colon';\n position = str.length - 1;\n } else if (production === 'qName' && (str.match(/:/g) || []).length > 1) {\n reason = 'QName can have at most one colon';\n position = str.lastIndexOf(':');\n } else if (\n ['name', 'ncName', 'qName'].includes(production) &&\n !startCharPattern.test(str[0])\n ) {\n reason = `First character \"${str[0]}\" is not a valid NameStartChar`;\n position = 0;\n } else {\n for (let i = 0; i < str.length; i++) {\n if (!namePattern.test(str[i])) {\n reason = `Character \"${str[i]}\" at position ${i} is not a valid NameChar`;\n position = i;\n break;\n }\n }\n }\n\n return { valid: false, production, input: str, reason, position };\n};\n\n// ---------------------------------------------------------------------------\n// Batch validator\n// ---------------------------------------------------------------------------\n\n/**\n * Validates an array of strings against a named production.\n *\n * @param {string[]} strings\n * @param {'name'|'ncName'|'qName'|'nmToken'|'nmTokens'} production\n * @param {{ xmlVersion?: '1.0'|'1.1', asciiOnly?: boolean }} [opts]\n * @returns {Array<{ valid: boolean, production: string, input: string, reason?: string, position?: number }>}\n */\nexport const validateAll = (strings, production, opts = {}) =>\n strings.map(str => validate(str, production, opts));\n\n// ---------------------------------------------------------------------------\n// Sanitizer\n// ---------------------------------------------------------------------------\n\n/**\n * Transforms an invalid string into the nearest valid XML name for the given production.\n *\n * @param {string} str\n * @param {'name'|'ncName'|'qName'|'nmToken'|'nmTokens'} production\n * @param {{ replacement?: string, asciiOnly?: boolean }} [opts]\n * asciiOnly: also replace any non-ASCII character, not just XML-illegal\n * ones (default false).\n * @returns {string}\n */\nexport const sanitize = (str, production = 'name', { replacement = '_', asciiOnly = false } = {}) => {\n if (!str) return replacement;\n\n let result = str;\n\n // Strip colons for NCName\n if (production === 'ncName') {\n result = result.replace(/:/g, '');\n }\n\n // Replace illegal characters\n const allowedCharPattern = asciiOnly ? /[^\\w\\-\\.:]/g : /[^\\w\\-\\.:\\u00B7\\u00C0-\\uFFFD]/g;\n result = result.replace(allowedCharPattern, replacement);\n\n // Fix invalid start character for Name / NCName / QName\n if (production !== 'nmToken' && production !== 'nmTokens') {\n if (/^[\\-\\.\\d]/.test(result)) {\n result = replacement + result;\n }\n }\n\n return result || replacement;\n};", "import { qName as isName } from 'xml-naming';\n\nexport default class DocTypeReader {\n constructor(options, xmlVersion) {\n this.suppressValidationErr = !options;\n this.options = options;\n this.xmlVersion = xmlVersion || 1.0;\n }\n\n setXmlVersion(xmlVersion = 1.0) {\n this.xmlVersion = xmlVersion;\n }\n readDocType(xmlData, i) {\n const entities = Object.create(null);\n let entityCount = 0;\n\n if (xmlData[i + 3] === 'O' &&\n xmlData[i + 4] === 'C' &&\n xmlData[i + 5] === 'T' &&\n xmlData[i + 6] === 'Y' &&\n xmlData[i + 7] === 'P' &&\n xmlData[i + 8] === 'E') {\n i = i + 9;\n let angleBracketsCount = 1;\n let hasBody = false, comment = false;\n let quoteChar = null; // tracks an open SYSTEM/PUBLIC literal before the '[' body\n let exp = \"\";\n for (; i < xmlData.length; i++) {\n // Inside a quoted external-identifier literal \u2014 XML allows '<'\n // and '>' as plain data here, so they must not be interpreted\n // as DOCTYPE structure until the matching quote closes.\n if (quoteChar !== null) {\n if (xmlData[i] === quoteChar) quoteChar = null;\n exp += xmlData[i];\n continue;\n }\n if (!hasBody && !comment && (xmlData[i] === '\"' || xmlData[i] === \"'\")) {\n quoteChar = xmlData[i];\n exp += xmlData[i];\n continue;\n }\n\n if (xmlData[i] === '<' && !comment) { //Determine the tag type\n if (hasBody && hasSeq(xmlData, \"!ENTITY\", i)) {\n i += 7;\n let entityName, val;\n [entityName, val, i] = this.readEntityExp(xmlData, i + 1, this.suppressValidationErr);\n if (val.indexOf(\"&\") === -1) { //Parameter entities are not supported\n if (this.options.enabled !== false &&\n this.options.maxEntityCount != null &&\n entityCount >= this.options.maxEntityCount) {\n throw new Error(\n `Entity count (${entityCount + 1}) exceeds maximum allowed (${this.options.maxEntityCount})`\n );\n }\n //const escaped = entityName.replace(/[.\\-+*:]/g, '\\\\.');\n //const escaped = entityName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n entities[entityName] = val;\n entityCount++;\n }\n }\n else if (hasBody && hasSeq(xmlData, \"!ELEMENT\", i)) {\n i += 8;//Not supported\n const { index } = this.readElementExp(xmlData, i + 1);\n i = index;\n } else if (hasBody && hasSeq(xmlData, \"!ATTLIST\", i)) {\n i += 8;//Not supported\n // const {index} = this.readAttlistExp(xmlData,i+1);\n // i = index;\n } else if (hasBody && hasSeq(xmlData, \"!NOTATION\", i)) {\n i += 9;//Not supported\n const { index } = this.readNotationExp(xmlData, i + 1, this.suppressValidationErr);\n i = index;\n } else if (hasSeq(xmlData, \"!--\", i)) comment = true;\n else throw new Error(`Invalid DOCTYPE`);\n\n angleBracketsCount++;\n exp = \"\";\n } else if (xmlData[i] === '>') { //Read tag content\n if (comment) {\n if (xmlData[i - 1] === \"-\" && xmlData[i - 2] === \"-\") {\n comment = false;\n angleBracketsCount--;\n }\n } else {\n angleBracketsCount--;\n }\n if (angleBracketsCount === 0) {\n break;\n }\n } else if (xmlData[i] === '[') {\n hasBody = true;\n } else {\n exp += xmlData[i];\n }\n }\n if (quoteChar !== null || angleBracketsCount !== 0) {\n throw new Error(`Unclosed DOCTYPE`);\n }\n } else {\n throw new Error(`Invalid Tag instead of DOCTYPE`);\n }\n return { entities, i };\n }\n readEntityExp(xmlData, i) {\n //External entities are not supported\n // <!ENTITY ext SYSTEM \"http://normal-website.com\" >\n\n //Parameter entities are not supported\n // <!ENTITY entityname \"&anotherElement;\">\n\n //Internal entities are supported\n // <!ENTITY entityname \"replacement text\">\n\n // Skip leading whitespace after <!ENTITY\n i = skipWhitespace(xmlData, i);\n\n // Read entity name\n const startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i]) && xmlData[i] !== '\"' && xmlData[i] !== \"'\") {\n i++;\n }\n let entityName = xmlData.substring(startIndex, i);\n\n validateEntityName(entityName, { xmlVersion: this.xmlVersion });\n\n // Skip whitespace after entity name\n i = skipWhitespace(xmlData, i);\n\n // Check for unsupported constructs (external entities or parameter entities)\n if (!this.suppressValidationErr) {\n if (xmlData.substring(i, i + 6).toUpperCase() === \"SYSTEM\") {\n throw new Error(\"External entities are not supported\");\n } else if (xmlData[i] === \"%\") {\n throw new Error(\"Parameter entities are not supported\");\n }\n }\n\n // Read entity value (internal entity)\n let entityValue = \"\";\n [i, entityValue] = this.readIdentifierVal(xmlData, i, \"entity\");\n\n // Validate entity size\n if (this.options.enabled !== false &&\n this.options.maxEntitySize != null &&\n entityValue.length > this.options.maxEntitySize) {\n throw new Error(\n `Entity \"${entityName}\" size (${entityValue.length}) exceeds maximum allowed size (${this.options.maxEntitySize})`\n );\n }\n\n i--;\n return [entityName, entityValue, i];\n }\n\n readNotationExp(xmlData, i) {\n // Skip leading whitespace after <!NOTATION\n i = skipWhitespace(xmlData, i);\n\n // Read notation name\n\n const startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n let notationName = xmlData.substring(startIndex, i);\n\n !this.suppressValidationErr && validateEntityName(notationName, { xmlVersion: this.xmlVersion });\n\n // Skip whitespace after notation name\n i = skipWhitespace(xmlData, i);\n\n // Check identifier type (SYSTEM or PUBLIC)\n const identifierType = xmlData.substring(i, i + 6).toUpperCase();\n if (!this.suppressValidationErr && identifierType !== \"SYSTEM\" && identifierType !== \"PUBLIC\") {\n throw new Error(`Expected SYSTEM or PUBLIC, found \"${identifierType}\"`);\n }\n i += identifierType.length;\n\n // Skip whitespace after identifier type\n i = skipWhitespace(xmlData, i);\n\n // Read public identifier (if PUBLIC)\n let publicIdentifier = null;\n let systemIdentifier = null;\n\n if (identifierType === \"PUBLIC\") {\n [i, publicIdentifier] = this.readIdentifierVal(xmlData, i, \"publicIdentifier\");\n\n // Skip whitespace after public identifier\n i = skipWhitespace(xmlData, i);\n\n // Optionally read system identifier\n if (xmlData[i] === '\"' || xmlData[i] === \"'\") {\n [i, systemIdentifier] = this.readIdentifierVal(xmlData, i, \"systemIdentifier\");\n }\n } else if (identifierType === \"SYSTEM\") {\n // Read system identifier (mandatory for SYSTEM)\n [i, systemIdentifier] = this.readIdentifierVal(xmlData, i, \"systemIdentifier\");\n\n if (!this.suppressValidationErr && !systemIdentifier) {\n throw new Error(\"Missing mandatory system identifier for SYSTEM notation\");\n }\n }\n\n return { notationName, publicIdentifier, systemIdentifier, index: --i };\n }\n\n readIdentifierVal(xmlData, i, type) {\n let identifierVal = \"\";\n const startChar = xmlData[i];\n if (startChar !== '\"' && startChar !== \"'\") {\n throw new Error(`Expected quoted string, found \"${startChar}\"`);\n }\n i++;\n\n const startIndex = i;\n while (i < xmlData.length && xmlData[i] !== startChar) {\n i++;\n }\n identifierVal = xmlData.substring(startIndex, i);\n\n if (xmlData[i] !== startChar) {\n throw new Error(`Unterminated ${type} value`);\n }\n i++;\n return [i, identifierVal];\n }\n\n readElementExp(xmlData, i) {\n // <!ELEMENT br EMPTY>\n // <!ELEMENT div ANY>\n // <!ELEMENT title (#PCDATA)>\n // <!ELEMENT book (title, author+)>\n // <!ELEMENT name (content-model)>\n\n // Skip leading whitespace after <!ELEMENT\n i = skipWhitespace(xmlData, i);\n\n // Read element name\n const startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n let elementName = xmlData.substring(startIndex, i);\n\n // Validate element name\n if (!this.suppressValidationErr && !isName(elementName, { xmlVersion: this.xmlVersion })) {\n throw new Error(`Invalid element name: \"${elementName}\"`);\n }\n\n // Skip whitespace after element name\n i = skipWhitespace(xmlData, i);\n let contentModel = \"\";\n // Expect '(' to start content model\n if (xmlData[i] === \"E\" && hasSeq(xmlData, \"MPTY\", i)) i += 4;\n else if (xmlData[i] === \"A\" && hasSeq(xmlData, \"NY\", i)) i += 2;\n else if (xmlData[i] === \"(\") {\n i++; // Move past '('\n\n // Read content model\n const startIndex = i;\n while (i < xmlData.length && xmlData[i] !== \")\") {\n i++;\n }\n contentModel = xmlData.substring(startIndex, i);\n\n if (xmlData[i] !== \")\") {\n throw new Error(\"Unterminated content model\");\n }\n\n } else if (!this.suppressValidationErr) {\n throw new Error(`Invalid Element Expression, found \"${xmlData[i]}\"`);\n }\n\n return {\n elementName,\n contentModel: contentModel.trim(),\n index: i\n };\n }\n\n readAttlistExp(xmlData, i) {\n // Skip leading whitespace after <!ATTLIST\n i = skipWhitespace(xmlData, i);\n\n // Read element name\n let startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n let elementName = xmlData.substring(startIndex, i);\n\n // Validate element name\n validateEntityName(elementName, { xmlVersion: this.xmlVersion })\n\n // Skip whitespace after element name\n i = skipWhitespace(xmlData, i);\n\n // Read attribute name\n startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n let attributeName = xmlData.substring(startIndex, i);\n\n // Validate attribute name\n if (!validateEntityName(attributeName, { xmlVersion: this.xmlVersion })) {\n throw new Error(`Invalid attribute name: \"${attributeName}\"`);\n }\n\n // Skip whitespace after attribute name\n i = skipWhitespace(xmlData, i);\n\n // Read attribute type\n let attributeType = \"\";\n if (xmlData.substring(i, i + 8).toUpperCase() === \"NOTATION\") {\n attributeType = \"NOTATION\";\n i += 8; // Move past \"NOTATION\"\n\n // Skip whitespace after \"NOTATION\"\n i = skipWhitespace(xmlData, i);\n\n // Expect '(' to start the list of notations\n if (xmlData[i] !== \"(\") {\n throw new Error(`Expected '(', found \"${xmlData[i]}\"`);\n }\n i++; // Move past '('\n\n // Read the list of allowed notations\n let allowedNotations = [];\n while (i < xmlData.length && xmlData[i] !== \")\") {\n\n\n const startIndex = i;\n while (i < xmlData.length && xmlData[i] !== \"|\" && xmlData[i] !== \")\") {\n i++;\n }\n let notation = xmlData.substring(startIndex, i);\n\n // Validate notation name\n notation = notation.trim();\n if (!validateEntityName(notation, { xmlVersion: this.xmlVersion })) {\n throw new Error(`Invalid notation name: \"${notation}\"`);\n }\n\n allowedNotations.push(notation);\n\n // Skip '|' separator or exit loop\n if (xmlData[i] === \"|\") {\n i++; // Move past '|'\n i = skipWhitespace(xmlData, i); // Skip optional whitespace after '|'\n }\n }\n\n if (xmlData[i] !== \")\") {\n throw new Error(\"Unterminated list of notations\");\n }\n i++; // Move past ')'\n\n // Store the allowed notations as part of the attribute type\n attributeType += \" (\" + allowedNotations.join(\"|\") + \")\";\n } else {\n // Handle simple types (e.g., CDATA, ID, IDREF, etc.)\n const startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n attributeType += xmlData.substring(startIndex, i);\n\n // Validate simple attribute type\n const validTypes = [\"CDATA\", \"ID\", \"IDREF\", \"IDREFS\", \"ENTITY\", \"ENTITIES\", \"NMTOKEN\", \"NMTOKENS\"];\n if (!this.suppressValidationErr && !validTypes.includes(attributeType.toUpperCase())) {\n throw new Error(`Invalid attribute type: \"${attributeType}\"`);\n }\n }\n\n // Skip whitespace after attribute type\n i = skipWhitespace(xmlData, i);\n\n // Read default value\n let defaultValue = \"\";\n if (xmlData.substring(i, i + 8).toUpperCase() === \"#REQUIRED\") {\n defaultValue = \"#REQUIRED\";\n i += 8;\n } else if (xmlData.substring(i, i + 7).toUpperCase() === \"#IMPLIED\") {\n defaultValue = \"#IMPLIED\";\n i += 7;\n } else {\n [i, defaultValue] = this.readIdentifierVal(xmlData, i, \"ATTLIST\");\n }\n\n return {\n elementName,\n attributeName,\n attributeType,\n defaultValue,\n index: i\n }\n }\n}\n\n\n\nconst skipWhitespace = (data, index) => {\n while (index < data.length && /\\s/.test(data[index])) {\n index++;\n }\n return index;\n};\n\n\n\nfunction hasSeq(data, seq, i) {\n for (let j = 0; j < seq.length; j++) {\n if (seq[j] !== data[i + j + 1]) return false;\n }\n return true;\n}\n\nfunction validateEntityName(name, xmlVersion) {\n if (isName(name, { xmlVersion: xmlVersion }))\n return name;\n else\n throw new Error(`Invalid entity name ${name}`);\n}", "/**\n * Flat lookup table: maps Unicode code point \u2192 ASCII digit (0-9).\n * Only decimal digit characters (Unicode category Nd) are included.\n *\n * Strategy: Int32Array of size (maxCodePoint - minCodePoint + 1).\n * Value 0xFF means \"not a digit\". Value 0-9 is the ASCII digit value.\n * This gives O(1) lookup with no branching, no bisect, no loop.\n *\n * Memory: range is 0x0660 to 0x1FBF0 \u2192 ~129,936 entries \u00D7 1 byte = ~127 KB.\n * Acceptable for a one-time init; lookup is a single array index.\n */\n\n// All known Unicode Nd (decimal digit) script zero code points.\n// Each script has exactly 10 consecutive digits: zero+0 .. zero+9.\nconst SCRIPT_ZEROS = [\n // Basic Latin (ASCII) \u2014 included for completeness / pass-through\n 0x0030, // 0-9\n\n // Arabic scripts\n 0x0660, // Arabic-Indic \u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669\n 0x06F0, // Extended Arabic-Indic (Urdu/Persian/Sindhi) \u06F0\u06F1\u06F2\u06F3\n\n // Indic scripts\n 0x0966, // Devanagari \u0966\u0967\u0968\u0969\u096A\u096B\u096C\u096D\u096E\u096F\n 0x09E6, // Bengali \u09E6\u09E7\u09E8\u09E9\u09EA\u09EB\u09EC\u09ED\u09EE\u09EF\n 0x0A66, // Gurmukhi \u0A66\u0A67\u0A68\u0A69\u0A6A\u0A6B\u0A6C\u0A6D\u0A6E\u0A6F\n 0x0AE6, // Gujarati \u0AE6\u0AE7\u0AE8\u0AE9\u0AEA\u0AEB\u0AEC\u0AED\u0AEE\u0AEF\n 0x0B66, // Odia \u0B66\u0B67\u0B68\u0B69\u0B6A\u0B6B\u0B6C\u0B6D\u0B6E\u0B6F\n 0x0BE6, // Tamil \u0BE6\u0BE7\u0BE8\u0BE9\u0BEA\u0BEB\u0BEC\u0BED\u0BEE\u0BEF\n 0x0C66, // Telugu \u0C66\u0C67\u0C68\u0C69\u0C6A\u0C6B\u0C6C\u0C6D\u0C6E\u0C6F\n 0x0CE6, // Kannada \u0CE6\u0CE7\u0CE8\u0CE9\u0CEA\u0CEB\u0CEC\u0CED\u0CEE\u0CEF\n 0x0D66, // Malayalam \u0D66\u0D67\u0D68\u0D69\u0D6A\u0D6B\u0D6C\u0D6D\u0D6E\u0D6F\n 0x0DE6, // Sinhala Archaic \u0DE6\u0DE7\u0DE8\u0DE9\u0DEA\u0DEB\u0DEC\u0DED\u0DEE\u0DEF\n\n // Southeast Asian scripts\n 0x0E50, // Thai \u0E50\u0E51\u0E52\u0E53\u0E54\u0E55\u0E56\u0E57\u0E58\u0E59\n 0x0ED0, // Lao \u0ED0\u0ED1\u0ED2\u0ED3\u0ED4\u0ED5\u0ED6\u0ED7\u0ED8\u0ED9\n 0x0F20, // Tibetan \u0F20\u0F21\u0F22\u0F23\u0F24\u0F25\u0F26\u0F27\u0F28\u0F29\n 0x1040, // Myanmar \u1040\u1041\u1042\u1043\u1044\u1045\u1046\u1047\u1048\u1049\n 0x1090, // Myanmar Shan \u1090\u1091\u1092\u1093\u1094\u1095\u1096\u1097\u1098\u1099\n 0x17E0, // Khmer \u17E0\u17E1\u17E2\u17E3\u17E4\u17E5\u17E6\u17E7\u17E8\u17E9\n 0x1810, // Mongolian \u1810\u1811\u1812\u1813\u1814\u1815\u1816\u1817\u1818\u1819\n 0x1946, // Limbu \u1946\u1947\u1948\u1949\u194A\u194B\u194C\u194D\u194E\u194F\n 0x19D0, // New Tai Lue \u19D0\u19D1\u19D2\u19D3\u19D4\u19D5\u19D6\u19D7\u19D8\u19D9\n 0x1A80, // Tai Tham Hora \u1A80\u1A81\u1A82\u1A83\u1A84\u1A85\u1A86\u1A87\u1A88\u1A89\n 0x1A90, // Tai Tham Tham \u1A90\u1A91\u1A92\u1A93\u1A94\u1A95\u1A96\u1A97\u1A98\u1A99\n 0x1B50, // Balinese \u1B50\u1B51\u1B52\u1B53\u1B54\u1B55\u1B56\u1B57\u1B58\u1B59\n 0x1BB0, // Sundanese \u1BB0\u1BB1\u1BB2\u1BB3\u1BB4\u1BB5\u1BB6\u1BB7\u1BB8\u1BB9\n 0x1C40, // Lepcha \u1C40\u1C41\u1C42\u1C43\u1C44\u1C45\u1C46\u1C47\u1C48\u1C49\n 0x1C50, // Ol Chiki \u1C50\u1C51\u1C52\u1C53\u1C54\u1C55\u1C56\u1C57\u1C58\u1C59\n\n // Fullwidth (CJK context)\n 0xFF10, // Fullwidth \uFF10\uFF11\uFF12\uFF13\uFF14\uFF15\uFF16\uFF17\uFF18\uFF19\n\n // Mathematical digit variants (Unicode math block)\n 0x1D7CE, // Mathematical Bold\n 0x1D7D8, // Mathematical Double-Struck\n 0x1D7E2, // Mathematical Sans-Serif\n 0x1D7EC, // Mathematical Sans-Serif Bold\n 0x1D7F6, // Mathematical Monospace\n\n // Other scripts\n 0x104A0, // Osmanya \uD801\uDCA0\uD801\uDCA1\uD801\uDCA2\uD801\uDCA3\uD801\uDCA4\uD801\uDCA5\uD801\uDCA6\uD801\uDCA7\uD801\uDCA8\uD801\uDCA9\n 0x10D30, // Hanifi Rohingya \uD803\uDD30\uD803\uDD31\uD803\uDD32\uD803\uDD33\uD803\uDD34\uD803\uDD35\uD803\uDD36\uD803\uDD37\uD803\uDD38\uD803\uDD39\n 0x11066, // Brahmi \uD804\uDC66\uD804\uDC67\uD804\uDC68\uD804\uDC69\uD804\uDC6A\uD804\uDC6B\uD804\uDC6C\uD804\uDC6D\uD804\uDC6E\uD804\uDC6F\n 0x110F0, // Sora Sompeng \uD804\uDCF0\uD804\uDCF1\uD804\uDCF2\uD804\uDCF3\uD804\uDCF4\uD804\uDCF5\uD804\uDCF6\uD804\uDCF7\uD804\uDCF8\uD804\uDCF9\n 0x11136, // Chakma \uD804\uDD36\uD804\uDD37\uD804\uDD38\uD804\uDD39\uD804\uDD3A\uD804\uDD3B\uD804\uDD3C\uD804\uDD3D\uD804\uDD3E\uD804\uDD3F\n 0x111D0, // Sharada \uD804\uDDD0\uD804\uDDD1\uD804\uDDD2\uD804\uDDD3\uD804\uDDD4\uD804\uDDD5\uD804\uDDD6\uD804\uDDD7\uD804\uDDD8\uD804\uDDD9\n 0x112F0, // Khudawadi \uD804\uDEF0\uD804\uDEF1\uD804\uDEF2\uD804\uDEF3\uD804\uDEF4\uD804\uDEF5\uD804\uDEF6\uD804\uDEF7\uD804\uDEF8\uD804\uDEF9\n 0x11450, // Newa \uD805\uDC50\uD805\uDC51\uD805\uDC52\uD805\uDC53\uD805\uDC54\uD805\uDC55\uD805\uDC56\uD805\uDC57\uD805\uDC58\uD805\uDC59\n 0x114D0, // Tirhuta \uD805\uDCD0\uD805\uDCD1\uD805\uDCD2\uD805\uDCD3\uD805\uDCD4\uD805\uDCD5\uD805\uDCD6\uD805\uDCD7\uD805\uDCD8\uD805\uDCD9\n 0x11650, // Modi \uD805\uDE50\uD805\uDE51\uD805\uDE52\uD805\uDE53\uD805\uDE54\uD805\uDE55\uD805\uDE56\uD805\uDE57\uD805\uDE58\uD805\uDE59\n 0x116C0, // Takri \uD805\uDEC0\uD805\uDEC1\uD805\uDEC2\uD805\uDEC3\uD805\uDEC4\uD805\uDEC5\uD805\uDEC6\uD805\uDEC7\uD805\uDEC8\uD805\uDEC9\n 0x11730, // Ahom \uD805\uDF30\uD805\uDF31\uD805\uDF32\uD805\uDF33\uD805\uDF34\uD805\uDF35\uD805\uDF36\uD805\uDF37\uD805\uDF38\uD805\uDF39\n 0x118E0, // Warang Citi \uD806\uDCE0\uD806\uDCE1\uD806\uDCE2\uD806\uDCE3\uD806\uDCE4\uD806\uDCE5\uD806\uDCE6\uD806\uDCE7\uD806\uDCE8\uD806\uDCE9\n 0x11950, // Dives Akuru \uD806\uDD50\uD806\uDD51\uD806\uDD52\uD806\uDD53\uD806\uDD54\uD806\uDD55\uD806\uDD56\uD806\uDD57\uD806\uDD58\uD806\uDD59\n 0x11BF0, // Khitan Small Script \uD806\uDFF0\uD806\uDFF1\uD806\uDFF2\uD806\uDFF3\uD806\uDFF4\uD806\uDFF5\uD806\uDFF6\uD806\uDFF7\uD806\uDFF8\uD806\uDFF9\n 0x11C50, // Bhaiksuki \uD807\uDC50\uD807\uDC51\uD807\uDC52\uD807\uDC53\uD807\uDC54\uD807\uDC55\uD807\uDC56\uD807\uDC57\uD807\uDC58\uD807\uDC59\n 0x11D50, // Masaram Gondi \uD807\uDD50\uD807\uDD51\uD807\uDD52\uD807\uDD53\uD807\uDD54\uD807\uDD55\uD807\uDD56\uD807\uDD57\uD807\uDD58\uD807\uDD59\n 0x11DA0, // Gunjala Gondi \uD807\uDDA0\uD807\uDDA1\uD807\uDDA2\uD807\uDDA3\uD807\uDDA4\uD807\uDDA5\uD807\uDDA6\uD807\uDDA7\uD807\uDDA8\uD807\uDDA9\n 0x11F50, // Kawi \uD807\uDF50\uD807\uDF51\uD807\uDF52\uD807\uDF53\uD807\uDF54\uD807\uDF55\uD807\uDF56\uD807\uDF57\uD807\uDF58\uD807\uDF59\n 0x16A60, // Mro \uD81A\uDE60\uD81A\uDE61\uD81A\uDE62\uD81A\uDE63\uD81A\uDE64\uD81A\uDE65\uD81A\uDE66\uD81A\uDE67\uD81A\uDE68\uD81A\uDE69\n 0x16AC0, // Tangsa \uD81A\uDEC0\uD81A\uDEC1\uD81A\uDEC2\uD81A\uDEC3\uD81A\uDEC4\uD81A\uDEC5\uD81A\uDEC6\uD81A\uDEC7\uD81A\uDEC8\uD81A\uDEC9\n 0x16B50, // Pahawh Hmong \uD81A\uDF50\uD81A\uDF51\uD81A\uDF52\uD81A\uDF53\uD81A\uDF54\uD81A\uDF55\uD81A\uDF56\uD81A\uDF57\uD81A\uDF58\uD81A\uDF59\n 0x1E140, // Nyiakeng Puachue Hmong \uD838\uDD40\uD838\uDD41\uD838\uDD42\uD838\uDD43\uD838\uDD44\uD838\uDD45\uD838\uDD46\uD838\uDD47\uD838\uDD48\uD838\uDD49\n 0x1E2F0, // Wancho \uD838\uDEF0\uD838\uDEF1\uD838\uDEF2\uD838\uDEF3\uD838\uDEF4\uD838\uDEF5\uD838\uDEF6\uD838\uDEF7\uD838\uDEF8\uD838\uDEF9\n 0x1E4F0, // Nag Mundari \uD839\uDCF0\uD839\uDCF1\uD839\uDCF2\uD839\uDCF3\uD839\uDCF4\uD839\uDCF5\uD839\uDCF6\uD839\uDCF7\uD839\uDCF8\uD839\uDCF9\n 0x1E950, // Adlam \uD83A\uDD50\uD83A\uDD51\uD83A\uDD52\uD83A\uDD53\uD83A\uDD54\uD83A\uDD55\uD83A\uDD56\uD83A\uDD57\uD83A\uDD58\uD83A\uDD59\n 0x1FBF0, // Segmented digit symbols \uD83E\uDFF0\uD83E\uDFF1\uD83E\uDFF2\uD83E\uDFF3\uD83E\uDFF4\uD83E\uDFF5\uD83E\uDFF6\uD83E\uDFF7\uD83E\uDFF8\uD83E\uDFF9\n];\n\n// Build a sparse Map for scripts above 0xFFFF (surrogate-pair range).\n// These can't go into a flat Uint8Array indexed by code point efficiently.\nconst NOT_DIGIT = 0xFF;\nconst HIGH_MAP = new Map(); // codePoint \u2192 digit value (0-9)\n\nconst LOW_MAX = 0xFFFF;\nconst LOW_MIN = 0x0660; // first non-ASCII digit script\n\n// Flat Uint8Array covering 0x0660 .. 0xFFFF\nconst TABLE_OFFSET = LOW_MIN;\nconst TABLE_SIZE = LOW_MAX - LOW_MIN + 1;\nconst TABLE = new Uint8Array(TABLE_SIZE).fill(NOT_DIGIT);\n\nfor (const zero of SCRIPT_ZEROS) {\n for (let d = 0; d < 10; d++) {\n const cp = zero + d;\n if (cp <= LOW_MAX) {\n TABLE[cp - TABLE_OFFSET] = d;\n } else {\n HIGH_MAP.set(cp, d);\n }\n }\n}\n\nexport { TABLE, TABLE_OFFSET, HIGH_MAP, NOT_DIGIT };\n", "'use strict';\n\nimport { TABLE, TABLE_OFFSET, HIGH_MAP, NOT_DIGIT } from './digitTable.js';\n\nconst CHAR_0 = 48; // '0'.charCodeAt(0)\nconst CHAR_9 = 57; // '9'.charCodeAt(0)\nconst CHAR_MINUS = 45; // '-'.charCodeAt(0)\n\n// Unicode minus/hyphen variants worth normalizing to ASCII '-' in numeric context:\n// U+2212 MINUS SIGN \u2212 (mathematically correct minus)\n// U+FF0D FULLWIDTH HYPHEN-MINUS \uFF0D (Japanese fullwidth context)\n// U+FE63 SMALL HYPHEN-MINUS \uFE63 (small form variant)\n//\n// NOT normalized (deliberate):\n// U+2013 EN DASH \u2013 (punctuation, not a numeric sign)\n// U+2014 EM DASH \u2014 (punctuation)\n// U+2010 HYPHEN \u2010 (typographic hyphen)\n//\n// Rationale: only characters a human or locale formatter would plausibly use\n// as a numeric minus sign are normalized. Dashes used for punctuation are left\n// alone to avoid mangling non-numeric strings.\nconst MINUS_SET = new Set([0x2212, 0xFF0D, 0xFE63]);\n\n/**\n * Normalize all Unicode decimal digit characters in a string to ASCII (0-9),\n * and normalize Unicode minus variants to ASCII '-' (U+002D).\n *\n * Non-digit, non-minus characters are passed through unchanged.\n *\n * Performance design:\n * - Fast path: if the string has no convertible characters, return it unchanged\n * (zero allocation).\n * - BMP digits (0x0660..0xFFFF excl. surrogates): flat Uint8Array lookup (O(1)).\n * - Supplementary plane digits (> 0xFFFF, encoded as surrogate pairs): Map lookup.\n * - Minus variants: checked inline with a small fixed Set.\n *\n * @param {string} str\n * @returns {string}\n */\nfunction anynum(str) {\n if (typeof str !== 'string') return str;\n\n const len = str.length;\n if (len === 0) return str;\n\n // Scan for first character needing conversion.\n // If none found, return original string (zero allocation).\n let firstHit = -1;\n\n for (let i = 0; i < len; i++) {\n const cc = str.charCodeAt(i);\n\n // ASCII digit or ASCII minus \u2014 already normalized, skip fast\n if ((cc >= CHAR_0 && cc <= CHAR_9) || cc === CHAR_MINUS) continue;\n\n // Below first unicode digit script \u2014 check minus variants only\n if (cc < TABLE_OFFSET) {\n if (MINUS_SET.has(cc)) { firstHit = i; break; }\n continue;\n }\n\n // Surrogate pairs live in BMP range 0xD800-0xDFFF \u2014 check before TABLE\n if (cc >= 0xD800 && cc <= 0xDBFF) {\n if (i + 1 < len) {\n const low = str.charCodeAt(i + 1);\n if (low >= 0xDC00 && low <= 0xDFFF) {\n const cp = 0x10000 + ((cc - 0xD800) << 10) + (low - 0xDC00);\n if (HIGH_MAP.has(cp)) { firstHit = i; break; }\n }\n }\n continue;\n }\n\n // BMP non-surrogate: flat table lookup; also check minus variants in this range\n if (TABLE[cc - TABLE_OFFSET] !== NOT_DIGIT || MINUS_SET.has(cc)) {\n firstHit = i;\n break;\n }\n }\n\n // Nothing to replace \u2014 return original, zero allocation\n if (firstHit === -1) return str;\n\n // Build result: copy unchanged prefix, then convert from firstHit onward\n const chars = [];\n\n if (firstHit > 0) chars.push(str.slice(0, firstHit));\n\n for (let i = firstHit; i < len; i++) {\n const cc = str.charCodeAt(i);\n\n // ASCII digit or ASCII minus \u2014 pass through\n if ((cc >= CHAR_0 && cc <= CHAR_9) || cc === CHAR_MINUS) {\n chars.push(str[i]);\n continue;\n }\n\n // Below TABLE_OFFSET \u2014 check minus variants, else pass through\n if (cc < TABLE_OFFSET) {\n chars.push(MINUS_SET.has(cc) ? '-' : str[i]);\n continue;\n }\n\n // Surrogate pairs\n if (cc >= 0xD800 && cc <= 0xDBFF) {\n if (i + 1 < len) {\n const low = str.charCodeAt(i + 1);\n if (low >= 0xDC00 && low <= 0xDFFF) {\n const cp = 0x10000 + ((cc - 0xD800) << 10) + (low - 0xDC00);\n const d = HIGH_MAP.get(cp);\n if (d !== undefined) {\n chars.push(String.fromCharCode(d + 48));\n i++; // consume low surrogate\n continue;\n }\n }\n }\n chars.push(str[i]);\n continue;\n }\n\n // BMP non-surrogate: flat table lookup + minus variants\n if (MINUS_SET.has(cc)) {\n chars.push('-');\n continue;\n }\n const d = TABLE[cc - TABLE_OFFSET];\n chars.push(d !== NOT_DIGIT ? String.fromCharCode(d + 48) : str[i]);\n }\n\n return chars.join('');\n}\n\nexport { anynum };\nexport default anynum;", "const hexRegex = /^[-+]?0x[a-fA-F0-9]+$/;\nconst binRegex = /^0b[01]+$/;\nconst octRegex = /^0o[0-7]+$/;\nconst numRegex = /^([\\-\\+])?(0*)([0-9]*(\\.[0-9]*)?)$/;\n\nimport anynum from \"anynum\";\n\nconst consider = {\n hex: true,\n binary: false,\n octal: false,\n leadingZeros: true,\n decimalPoint: \"\\.\",\n eNotation: true,\n //skipLike: /regex/,\n infinity: \"original\", // \"null\", \"infinity\" (Infinity type), \"string\" (\"Infinity\" (the string literal))\n unicode: false,\n};\n\nexport default function toNumber(str, options = {}) {\n options = Object.assign({}, consider, options);\n if (!str || typeof str !== \"string\") return str;\n\n let trimmedStr = str.trim();\n\n if (trimmedStr.length === 0) return str;\n else if (options.skipLike !== undefined && options.skipLike.test(trimmedStr)) return str;\n else if (trimmedStr === \"0\") return 0;\n\n if (options.unicode) {\n trimmedStr = anynum(trimmedStr);\n if (trimmedStr === \"0\") return 0; // re-check after normalization\n }\n if (options.hex && hexRegex.test(trimmedStr)) {\n return parse_int(trimmedStr, 16);\n } else if (options.binary && binRegex.test(trimmedStr)) {\n return parse_int(trimmedStr, 2);\n } else if (options.octal && octRegex.test(trimmedStr)) {\n return parse_int(trimmedStr, 8);\n } else if (!isFinite(trimmedStr)) { //Infinity\n return handleInfinity(str, Number(trimmedStr), options);\n } else if (trimmedStr.includes('e') || trimmedStr.includes('E')) { //eNotation\n return resolveEnotation(str, trimmedStr, options);\n } else {\n //separate negative sign, leading zeros, and rest number\n const match = numRegex.exec(trimmedStr);\n // +00.123 => [ , '+', '00', '.123', ..\n if (match) {\n const sign = match[1] || \"\";\n const leadingZeros = match[2];\n let numTrimmedByZeros = trimZeros(match[3]); //complete num without leading zeros\n const decimalAdjacentToLeadingZeros = sign ? // 0., -00., 000.\n str[leadingZeros.length + 1] === \".\"\n : str[leadingZeros.length] === \".\";\n\n //trim ending zeros for floating number\n if (!options.leadingZeros //leading zeros are not allowed\n && (leadingZeros.length > 1\n || (leadingZeros.length === 1 && !decimalAdjacentToLeadingZeros))) {\n // 00, 00.3, +03.24, 03, 03.24\n return str;\n }\n else {//no leading zeros or leading zeros are allowed\n const num = Number(trimmedStr);\n const parsedStr = String(num);\n\n if (num === 0) return num;\n if (parsedStr.search(/[eE]/) !== -1) { //given number is long and parsed to eNotation\n if (options.eNotation) return num;\n else return str;\n } else if (trimmedStr.indexOf(\".\") !== -1) { //floating number\n if (parsedStr === \"0\") return num; //0.0\n else if (parsedStr === numTrimmedByZeros) return num; //0.456. 0.79000\n else if (parsedStr === `${sign}${numTrimmedByZeros}`) return num;\n else return str;\n }\n\n let n = leadingZeros ? numTrimmedByZeros : trimmedStr;\n if (leadingZeros) {\n // -009 => -9\n return (n === parsedStr) || (sign + n === parsedStr) ? num : str\n } else {\n // +9\n return (n === parsedStr) || (n === sign + parsedStr) ? num : str\n }\n }\n } else { //non-numeric string\n return str;\n }\n }\n}\n\nconst eNotationRegx = /^([-+])?(0*)(\\d*(\\.\\d*)?[eE][-\\+]?\\d+)$/;\nfunction resolveEnotation(str, trimmedStr, options) {\n if (!options.eNotation) return str;\n const notation = trimmedStr.match(eNotationRegx);\n if (notation) {\n let sign = notation[1] || \"\";\n const eChar = notation[3].indexOf(\"e\") === -1 ? \"E\" : \"e\";\n const leadingZeros = notation[2];\n const eAdjacentToLeadingZeros = sign ? // 0E.\n str[leadingZeros.length + 1] === eChar\n : str[leadingZeros.length] === eChar;\n\n if (leadingZeros.length > 1 && eAdjacentToLeadingZeros) return str;\n else if (leadingZeros.length === 1\n && (notation[3].startsWith(`.${eChar}`) || notation[3][0] === eChar)) {\n return Number(trimmedStr);\n } else if (leadingZeros.length > 0) {\n // Has leading zeros \u2014 only accept if leadingZeros option allows it\n if (options.leadingZeros && !eAdjacentToLeadingZeros) {\n trimmedStr = (notation[1] || \"\") + notation[3];\n return Number(trimmedStr);\n } else return str;\n } else {\n // No leading zeros \u2014 always valid e-notation, parse it\n return Number(trimmedStr);\n }\n } else {\n return str;\n }\n}\n\n/**\n * \n * @param {string} numStr without leading zeros\n * @returns \n */\nfunction trimZeros(numStr) {\n if (numStr && numStr.indexOf(\".\") !== -1) {//float\n //remove ending zeros without the O(n^2) backtracking that /0+$/ hits\n //when the string doesn't end in 0 but has a long internal zero-run\n let end = numStr.length;\n while (end > 0 && numStr.charCodeAt(end - 1) === 48 /* '0' */) end--;\n numStr = numStr.slice(0, end);\n if (numStr === \".\") numStr = \"0\";\n else if (numStr[0] === \".\") numStr = \"0\" + numStr;\n else if (numStr[numStr.length - 1] === \".\") numStr = numStr.substring(0, numStr.length - 1);\n return numStr;\n }\n return numStr;\n}\n\nfunction parse_int(numStr, base) {\n const str = numStr.trim();\n if (base === 2 || base === 8) numStr = str.substring(2);\n\n if (parseInt) return parseInt(numStr, base);\n else if (Number.parseInt) return Number.parseInt(numStr, base);\n else if (window && window.parseInt) return window.parseInt(numStr, base);\n else throw new Error(\"parseInt, Number.parseInt, window.parseInt are not supported\");\n}\n\n/**\n * Handle infinite values based on user option\n * @param {string} str - original input string\n * @param {number} num - parsed number (Infinity or -Infinity)\n * @param {object} options - user options\n * @returns {string|number|null} based on infinity option\n */\nfunction handleInfinity(str, num, options) {\n const isPositive = num === Infinity;\n\n switch (options.infinity.toLowerCase()) {\n case \"null\":\n return null;\n case \"infinity\":\n return num; // Return Infinity or -Infinity\n case \"string\":\n return isPositive ? \"Infinity\" : \"-Infinity\";\n case \"original\":\n default:\n return str; // Return original string like \"1e1000\"\n }\n}", "export default function getIgnoreAttributesFn(ignoreAttributes) {\n if (typeof ignoreAttributes === 'function') {\n return ignoreAttributes\n }\n if (Array.isArray(ignoreAttributes)) {\n return (attrName) => {\n for (const pattern of ignoreAttributes) {\n if (typeof pattern === 'string' && attrName === pattern) {\n return true\n }\n if (pattern instanceof RegExp && pattern.test(attrName)) {\n return true\n }\n }\n }\n }\n return () => false\n}", "/**\n * Expression - Parses and stores a tag pattern expression\n * \n * Patterns are parsed once and stored in an optimized structure for fast matching.\n * \n * @example\n * const expr = new Expression(\"root.users.user\");\n * const expr2 = new Expression(\"..user[id]:first\");\n * const expr3 = new Expression(\"root/users/user\", { separator: '/' });\n */\nexport default class Expression {\n /**\n * Create a new Expression\n * @param {string} pattern - Pattern string (e.g., \"root.users.user\", \"..user[id]\")\n * @param {Object} options - Configuration options\n * @param {string} options.separator - Path separator (default: '.')\n */\n constructor(pattern, options = {}, data) {\n this.pattern = pattern;\n this.separator = options.separator || '.';\n this.segments = this._parse(pattern);\n this.data = data;\n // Cache expensive checks for performance (O(1) instead of O(n))\n this._hasDeepWildcard = this.segments.some(seg => seg.type === 'deep-wildcard');\n this._hasAttributeCondition = this.segments.some(seg => seg.attrName !== undefined);\n this._hasPositionSelector = this.segments.some(seg => seg.position !== undefined);\n }\n\n /**\n * Parse pattern string into segments\n * @private\n * @param {string} pattern - Pattern to parse\n * @returns {Array} Array of segment objects\n */\n _parse(pattern) {\n const segments = [];\n\n // Split by separator but handle \"..\" specially\n let i = 0;\n let currentPart = '';\n\n while (i < pattern.length) {\n if (pattern[i] === this.separator) {\n // Check if next char is also separator (deep wildcard)\n if (i + 1 < pattern.length && pattern[i + 1] === this.separator) {\n // Flush current part if any\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n currentPart = '';\n }\n // Add deep wildcard\n segments.push({ type: 'deep-wildcard' });\n i += 2; // Skip both separators\n } else {\n // Regular separator\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n }\n currentPart = '';\n i++;\n }\n } else {\n currentPart += pattern[i];\n i++;\n }\n }\n\n // Flush remaining part\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n }\n\n return segments;\n }\n\n /**\n * Parse a single segment\n * @private\n * @param {string} part - Segment string (e.g., \"user\", \"ns::user\", \"user[id]\", \"ns::user:first\")\n * @returns {Object} Segment object\n */\n _parseSegment(part) {\n const segment = { type: 'tag' };\n\n // NEW NAMESPACE SYNTAX (v2.0):\n // ============================\n // Namespace uses DOUBLE colon (::)\n // Position uses SINGLE colon (:)\n // \n // Examples:\n // \"user\" \u2192 tag\n // \"user:first\" \u2192 tag + position\n // \"user[id]\" \u2192 tag + attribute\n // \"user[id]:first\" \u2192 tag + attribute + position\n // \"ns::user\" \u2192 namespace + tag\n // \"ns::user:first\" \u2192 namespace + tag + position\n // \"ns::user[id]\" \u2192 namespace + tag + attribute\n // \"ns::user[id]:first\" \u2192 namespace + tag + attribute + position\n // \"ns::first\" \u2192 namespace + tag named \"first\" (NO ambiguity!)\n //\n // This eliminates all ambiguity:\n // :: = namespace separator\n // : = position selector\n // [] = attributes\n\n // Step 1: Extract brackets [attr] or [attr=value]\n let bracketContent = null;\n let withoutBrackets = part;\n\n const bracketMatch = part.match(/^([^\\[]+)(\\[[^\\]]*\\])(.*)$/);\n if (bracketMatch) {\n withoutBrackets = bracketMatch[1] + bracketMatch[3];\n if (bracketMatch[2]) {\n const content = bracketMatch[2].slice(1, -1);\n if (content) {\n bracketContent = content;\n }\n }\n }\n\n // Step 2: Check for namespace (double colon ::)\n let namespace = undefined;\n let tagAndPosition = withoutBrackets;\n\n if (withoutBrackets.includes('::')) {\n const nsIndex = withoutBrackets.indexOf('::');\n namespace = withoutBrackets.substring(0, nsIndex).trim();\n tagAndPosition = withoutBrackets.substring(nsIndex + 2).trim(); // Skip ::\n\n if (!namespace) {\n throw new Error(`Invalid namespace in pattern: ${part}`);\n }\n }\n\n // Step 3: Parse tag and position (single colon :)\n let tag = undefined;\n let positionMatch = null;\n\n if (tagAndPosition.includes(':')) {\n const colonIndex = tagAndPosition.lastIndexOf(':'); // Use last colon for position\n const tagPart = tagAndPosition.substring(0, colonIndex).trim();\n const posPart = tagAndPosition.substring(colonIndex + 1).trim();\n\n // Verify position is a valid keyword\n const isPositionKeyword = ['first', 'last', 'odd', 'even'].includes(posPart) ||\n /^nth\\(\\d+\\)$/.test(posPart);\n\n if (isPositionKeyword) {\n tag = tagPart;\n positionMatch = posPart;\n } else {\n // Not a valid position keyword, treat whole thing as tag\n tag = tagAndPosition;\n }\n } else {\n tag = tagAndPosition;\n }\n\n if (!tag) {\n throw new Error(`Invalid segment pattern: ${part}`);\n }\n\n segment.tag = tag;\n if (namespace) {\n segment.namespace = namespace;\n }\n\n // Step 4: Parse attributes\n if (bracketContent) {\n if (bracketContent.includes('=')) {\n const eqIndex = bracketContent.indexOf('=');\n segment.attrName = bracketContent.substring(0, eqIndex).trim();\n segment.attrValue = bracketContent.substring(eqIndex + 1).trim();\n } else {\n segment.attrName = bracketContent.trim();\n }\n }\n\n // Step 5: Parse position selector\n if (positionMatch) {\n const nthMatch = positionMatch.match(/^nth\\((\\d+)\\)$/);\n if (nthMatch) {\n segment.position = 'nth';\n segment.positionValue = parseInt(nthMatch[1], 10);\n } else {\n segment.position = positionMatch;\n }\n }\n\n return segment;\n }\n\n /**\n * Get the number of segments\n * @returns {number}\n */\n get length() {\n return this.segments.length;\n }\n\n /**\n * Check if expression contains deep wildcard\n * @returns {boolean}\n */\n hasDeepWildcard() {\n return this._hasDeepWildcard;\n }\n\n /**\n * Check if expression has attribute conditions\n * @returns {boolean}\n */\n hasAttributeCondition() {\n return this._hasAttributeCondition;\n }\n\n /**\n * Check if expression has position selectors\n * @returns {boolean}\n */\n hasPositionSelector() {\n return this._hasPositionSelector;\n }\n\n /**\n * Get string representation\n * @returns {string}\n */\n toString() {\n return this.pattern;\n }\n}", "/**\n * ExpressionSet - An indexed collection of Expressions for efficient bulk matching\n *\n * Instead of iterating all expressions on every tag, ExpressionSet pre-indexes\n * them at insertion time by depth and terminal tag name. At match time, only\n * the relevant bucket is evaluated \u2014 typically reducing checks from O(E) to O(1)\n * lookup plus O(small bucket) matches.\n *\n * Three buckets are maintained:\n * - `_byDepthAndTag` \u2014 exact depth + exact tag name (tightest, used first)\n * - `_wildcardByDepth` \u2014 exact depth + wildcard tag `*` (depth-matched only)\n * - `_deepWildcards` \u2014 expressions containing `..` (cannot be depth-indexed)\n *\n * @example\n * import { Expression, ExpressionSet } from 'fast-xml-tagger';\n *\n * // Build once at config time\n * const stopNodes = new ExpressionSet();\n * stopNodes.add(new Expression('root.users.user'));\n * stopNodes.add(new Expression('root.config.setting'));\n * stopNodes.add(new Expression('..script'));\n *\n * // Query on every tag \u2014 hot path\n * if (stopNodes.matchesAny(matcher)) { ... }\n */\nexport default class ExpressionSet {\n constructor() {\n /** @type {Map<string, import('./Expression.js').default[]>} depth:tag \u2192 expressions */\n this._byDepthAndTag = new Map();\n\n /** @type {Map<number, import('./Expression.js').default[]>} depth \u2192 wildcard-tag expressions */\n this._wildcardByDepth = new Map();\n\n /** @type {import('./Expression.js').default[]} expressions containing deep wildcard (..) */\n this._deepWildcards = [];\n\n /** @type {Map<string, import('./Expression.js').default[]>} terminalTag \u2192 deep wildcard expressions */\n this._deepByTerminalTag = new Map();\n\n /** @type {Set<string>} pattern strings already added \u2014 used for deduplication */\n this._patterns = new Set();\n\n /** @type {boolean} whether the set is sealed against further additions */\n this._sealed = false;\n }\n\n /**\n * Add an Expression to the set.\n * Duplicate patterns (same pattern string) are silently ignored.\n *\n * @param {import('./Expression.js').default} expression - A pre-constructed Expression instance\n * @returns {this} for chaining\n * @throws {TypeError} if called after seal()\n *\n * @example\n * set.add(new Expression('root.users.user'));\n * set.add(new Expression('..script'));\n */\n add(expression) {\n if (this._sealed) {\n throw new TypeError(\n 'ExpressionSet is sealed. Create a new ExpressionSet to add more expressions.'\n );\n }\n\n // Deduplicate by pattern string\n if (this._patterns.has(expression.pattern)) return this;\n this._patterns.add(expression.pattern);\n\n if (expression.hasDeepWildcard()) {\n const lastSeg = expression.segments[expression.segments.length - 1];\n if (lastSeg && lastSeg.type !== 'deep-wildcard' && lastSeg.tag !== '*') {\n const tag = lastSeg.tag;\n if (!this._deepByTerminalTag.has(tag)) this._deepByTerminalTag.set(tag, []);\n this._deepByTerminalTag.get(tag).push(expression);\n } else {\n this._deepWildcards.push(expression);\n }\n return this;\n }\n\n const depth = expression.length;\n const lastSeg = expression.segments[expression.segments.length - 1];\n const tag = lastSeg?.tag;\n\n if (!tag || tag === '*') {\n // Can index by depth but not by tag\n if (!this._wildcardByDepth.has(depth)) this._wildcardByDepth.set(depth, []);\n this._wildcardByDepth.get(depth).push(expression);\n } else {\n // Tightest bucket: depth + tag\n const key = `${depth}:${tag}`;\n if (!this._byDepthAndTag.has(key)) this._byDepthAndTag.set(key, []);\n this._byDepthAndTag.get(key).push(expression);\n }\n\n return this;\n }\n\n /**\n * Add multiple expressions at once.\n *\n * @param {import('./Expression.js').default[]} expressions - Array of Expression instances\n * @returns {this} for chaining\n *\n * @example\n * set.addAll([\n * new Expression('root.users.user'),\n * new Expression('root.config.setting'),\n * ]);\n */\n addAll(expressions) {\n for (const expr of expressions) this.add(expr);\n return this;\n }\n\n /**\n * Check whether a pattern string is already present in the set.\n *\n * @param {import('./Expression.js').default} expression\n * @returns {boolean}\n */\n has(expression) {\n return this._patterns.has(expression.pattern);\n }\n\n /**\n * Number of expressions in the set.\n * @type {number}\n */\n get size() {\n return this._patterns.size;\n }\n\n /**\n * Seal the set against further modifications.\n * Useful to prevent accidental mutations after config is built.\n * Calling add() or addAll() on a sealed set throws a TypeError.\n *\n * @returns {this}\n */\n seal() {\n this._sealed = true;\n return this;\n }\n\n /**\n * Whether the set has been sealed.\n * @type {boolean}\n */\n get isSealed() {\n return this._sealed;\n }\n\n /**\n * Test whether the matcher's current path matches any expression in the set.\n *\n * Evaluation order (cheapest \u2192 most expensive):\n * 1. Exact depth + tag bucket \u2014 O(1) lookup, typically 0\u20132 expressions\n * 2. Depth-only wildcard bucket \u2014 O(1) lookup, rare\n * 3. Deep-wildcard list \u2014 always checked, but usually small\n *\n * @param {import('./Matcher.js').default} matcher - Matcher instance (or readOnly view)\n * @returns {boolean} true if any expression matches the current path\n *\n * @example\n * if (stopNodes.matchesAny(matcher)) {\n * // handle stop node\n * }\n */\n matchesAny(matcher) {\n return this.findMatch(matcher) !== null;\n }\n /**\n * Find and return the first Expression that matches the matcher's current path.\n *\n * Uses the same evaluation order as matchesAny (cheapest \u2192 most expensive):\n * 1. Exact depth + tag bucket\n * 2. Depth-only wildcard bucket\n * 3. Deep-wildcard list\n *\n * @param {import('./Matcher.js').default} matcher - Matcher instance (or readOnly view)\n * @returns {import('./Expression.js').default | null} the first matching Expression, or null\n *\n * @example\n * const expr = stopNodes.findMatch(matcher);\n * if (expr) {\n * // access expr.config, expr.pattern, etc.\n * }\n */\n findMatch(matcher) {\n const depth = matcher.getDepth();\n const tag = matcher.getCurrentTag();\n\n // 1. Tightest bucket \u2014 most expressions live here\n const exactKey = `${depth}:${tag}`;\n const exactBucket = this._byDepthAndTag.get(exactKey);\n if (exactBucket) {\n for (let i = 0; i < exactBucket.length; i++) {\n if (matcher.matches(exactBucket[i])) return exactBucket[i];\n }\n }\n\n // 2. Depth-matched wildcard-tag expressions\n const wildcardBucket = this._wildcardByDepth.get(depth);\n if (wildcardBucket) {\n for (let i = 0; i < wildcardBucket.length; i++) {\n if (matcher.matches(wildcardBucket[i])) return wildcardBucket[i];\n }\n }\n\n // 3. Deep wildcards \u2014 indexed by terminal tag, then unindexed fallback\n const deepBucket = this._deepByTerminalTag.get(tag);\n if (deepBucket) {\n for (let i = 0; i < deepBucket.length; i++) {\n if (matcher.matches(deepBucket[i])) return deepBucket[i];\n }\n }\n for (let i = 0; i < this._deepWildcards.length; i++) {\n if (matcher.matches(this._deepWildcards[i])) return this._deepWildcards[i];\n }\n\n return null;\n }\n}\n", "import ExpressionSet from \"./ExpressionSet.js\";\n\n/**\n * MatcherView - A lightweight read-only view over a Matcher's internal state.\n *\n * Created once by Matcher and reused across all callbacks. Holds a direct\n * reference to the parent Matcher so it always reflects current parser state\n * with zero copying or freezing overhead.\n *\n * Users receive this via {@link Matcher#readOnly} or directly from parser\n * callbacks. It exposes all query and matching methods but has no mutation\n * methods \u2014 misuse is caught at the TypeScript level rather than at runtime.\n *\n * @example\n * const matcher = new Matcher();\n * const view = matcher.readOnly();\n *\n * matcher.push(\"root\", {});\n * view.getCurrentTag(); // \"root\"\n * view.getDepth(); // 1\n */\nexport class MatcherView {\n /**\n * @param {Matcher} matcher - The parent Matcher instance to read from.\n */\n constructor(matcher) {\n this._matcher = matcher;\n }\n\n /**\n * Get the path separator used by the parent matcher.\n * @returns {string}\n */\n get separator() {\n return this._matcher.separator;\n }\n\n /**\n * Get current tag name.\n * @returns {string|undefined}\n */\n getCurrentTag() {\n const path = this._matcher.path;\n return path.length > 0 ? path[path.length - 1].tag : undefined;\n }\n\n /**\n * Get current namespace.\n * @returns {string|undefined}\n */\n getCurrentNamespace() {\n const path = this._matcher.path;\n return path.length > 0 ? path[path.length - 1].namespace : undefined;\n }\n\n /**\n * Get current node's attribute value.\n * @param {string} attrName\n * @returns {*}\n */\n getAttrValue(attrName) {\n const path = this._matcher.path;\n if (path.length === 0) return undefined;\n return path[path.length - 1].values?.[attrName];\n }\n\n /**\n * Check if current node has an attribute.\n * @param {string} attrName\n * @returns {boolean}\n */\n hasAttr(attrName) {\n const path = this._matcher.path;\n if (path.length === 0) return false;\n const current = path[path.length - 1];\n return current.values !== undefined && attrName in current.values;\n }\n\n /**\n * Get the value of a \"kept\" attribute from the nearest ancestor (or\n * current node) that declared it via `push(tag, attrs, ns, { keep: [...] })`.\n * @param {string} attrName\n * @returns {*}\n */\n getAnyParentAttr(attrName) {\n return this._matcher.getAnyParentAttr(attrName);\n }\n\n /**\n * Check whether any ancestor (or the current node) kept the given\n * attribute via `push(tag, attrs, ns, { keep: [...] })`.\n * @param {string} attrName\n * @returns {boolean}\n */\n hasAnyParentAttr(attrName) {\n return this._matcher.hasAnyParentAttr(attrName);\n }\n\n /**\n * Get current node's sibling position (child index in parent).\n * @returns {number}\n */\n getPosition() {\n const path = this._matcher.path;\n if (path.length === 0) return -1;\n return path[path.length - 1].position ?? 0;\n }\n\n /**\n * Get current node's repeat counter (occurrence count of this tag name).\n * @returns {number}\n */\n getCounter() {\n const path = this._matcher.path;\n if (path.length === 0) return -1;\n return path[path.length - 1].counter ?? 0;\n }\n\n /**\n * Get current node's sibling index (alias for getPosition).\n * @returns {number}\n * @deprecated Use getPosition() or getCounter() instead\n */\n getIndex() {\n return this.getPosition();\n }\n\n /**\n * Get current path depth.\n * @returns {number}\n */\n getDepth() {\n return this._matcher.path.length;\n }\n\n /**\n * Get path as string.\n * @param {string} [separator] - Optional separator (uses default if not provided)\n * @param {boolean} [includeNamespace=true]\n * @returns {string}\n */\n toString(separator, includeNamespace = true) {\n return this._matcher.toString(separator, includeNamespace);\n }\n\n /**\n * Get path as array of tag names.\n * @returns {string[]}\n */\n toArray() {\n return this._matcher.path.map(n => n.tag);\n }\n\n /**\n * Match current path against an Expression.\n * @param {Expression} expression\n * @returns {boolean}\n */\n matches(expression) {\n return this._matcher.matches(expression);\n }\n\n /**\n * Match any expression in the given set against the current path.\n * @param {ExpressionSet} exprSet\n * @returns {boolean}\n */\n matchesAny(exprSet) {\n return exprSet.matchesAny(this._matcher);\n }\n}\n\n/**\n * Matcher - Tracks current path in XML/JSON tree and matches against Expressions.\n *\n * The matcher maintains a stack of nodes representing the current path from root to\n * current tag. It only stores attribute values for the current (top) node to minimize\n * memory usage. Sibling tracking is used to auto-calculate position and counter.\n *\n * Use {@link Matcher#readOnly} to obtain a {@link MatcherView} safe to pass to\n * user callbacks \u2014 it always reflects current state with no Proxy overhead.\n *\n * @example\n * const matcher = new Matcher();\n * matcher.push(\"root\", {});\n * matcher.push(\"users\", {});\n * matcher.push(\"user\", { id: \"123\", type: \"admin\" });\n *\n * const expr = new Expression(\"root.users.user\");\n * matcher.matches(expr); // true\n */\nexport default class Matcher {\n /**\n * Create a new Matcher.\n * @param {Object} [options={}]\n * @param {string} [options.separator='.'] - Default path separator\n */\n constructor(options = {}) {\n this.separator = options.separator || '.';\n this.path = [];\n this.siblingStacks = [];\n // Each path node: { tag, values, position, counter, namespace? }\n // values only present for current (last) node\n // Each siblingStacks entry: Map<tagName, count> tracking occurrences at each level\n this._pathStringCache = null;\n this._view = new MatcherView(this);\n\n // Kept-attribute stack: only populated when push() is called with options.keep.\n this._keptAttrs = [];\n }\n\n /**\n * Push a new tag onto the path.\n * @param {string} tagName\n * @param {Object|null} [attrValues=null]\n * @param {string|null} [namespace=null]\n * @param {Object|null} [options=null]\n * @param {string[]} [options.keep] - Names of attributes (from attrValues)\n */\n push(tagName, attrValues = null, namespace = null, options = null) {\n this._pathStringCache = null;\n\n // Remove values from previous current node (now becoming ancestor)\n if (this.path.length > 0) {\n this.path[this.path.length - 1].values = undefined;\n }\n\n // Get or create sibling tracking for current level\n const currentLevel = this.path.length;\n let level = this.siblingStacks[currentLevel];\n if (!level) {\n // `counts` tells same-name siblings apart (the \"counter\" \u2014 nth <item>\n // among other <item>s). `total` is every child seen at this level so\n // far, kept as a running number instead of re-added from `counts` on\n // every push \u2014 a parent with many differently-named children would\n // otherwise cost more per child the more distinct names it has.\n level = { counts: new Map(), total: 0 };\n this.siblingStacks[currentLevel] = level;\n }\n\n // Create a unique key for sibling tracking that includes namespace\n const siblingKey = namespace ? `${namespace}:${tagName}` : tagName;\n\n // Calculate counter (how many times this tag appeared at this level)\n const counter = level.counts.get(siblingKey) || 0;\n\n // Position = total children at this level seen before this one.\n const position = level.total;\n\n // Update sibling count for this tag, and the level's running total.\n level.counts.set(siblingKey, counter + 1);\n level.total++;\n\n // Create new node\n const node = {\n tag: tagName,\n position: position,\n counter: counter\n };\n\n if (namespace !== null && namespace !== undefined) {\n node.namespace = namespace;\n }\n\n if (attrValues !== null && attrValues !== undefined) {\n node.values = attrValues;\n }\n\n this.path.push(node);\n\n // Depth of the node we just pushed (1-based, matches this.path.length)\n const depth = this.path.length;\n\n // Copy only the requested attributes into the kept-attrs stack. This is\n // the one part of push() whose cost scales with input (O(keep.length))\n // rather than being O(1) \u2014 by design, since the caller is explicitly\n // opting in for specific attribute names. No options/keep => zero added\n // cost beyond the two property reads below.\n const keep = options !== null ? options.keep : null;\n if (keep !== null && keep !== undefined && keep.length > 0 && attrValues) {\n for (let i = 0; i < keep.length; i++) {\n const name = keep[i];\n if (attrValues[name] !== undefined) {\n this._keptAttrs.push({ depth, name, value: attrValues[name] });\n }\n }\n }\n }\n\n /**\n * Pop the last tag from the path.\n * @returns {Object|undefined} The popped node\n */\n pop() {\n if (this.path.length === 0) return undefined;\n this._pathStringCache = null;\n\n const node = this.path.pop();\n\n if (this.siblingStacks.length > this.path.length + 1) {\n this.siblingStacks.length = this.path.length + 1;\n }\n\n // Drop any kept attributes that belonged to the popped node (or deeper).\n // _keptAttrs is depth-ordered (push only ever appends increasing depths),\n // so this is a backward scan that stops at the first surviving entry \u2014\n // typically O(1) since kept attrs are rare by design.\n const poppedDepth = this.path.length + 1;\n while (\n this._keptAttrs.length > 0 &&\n this._keptAttrs[this._keptAttrs.length - 1].depth >= poppedDepth\n ) {\n this._keptAttrs.pop();\n }\n\n return node;\n }\n\n /**\n * Update current node's attribute values.\n * Useful when attributes are parsed after push.\n * @param {Object} attrValues\n */\n updateCurrent(attrValues) {\n if (this.path.length > 0) {\n const current = this.path[this.path.length - 1];\n if (attrValues !== null && attrValues !== undefined) {\n current.values = attrValues;\n }\n }\n }\n\n /**\n * Get current tag name.\n * @returns {string|undefined}\n */\n getCurrentTag() {\n return this.path.length > 0 ? this.path[this.path.length - 1].tag : undefined;\n }\n\n /**\n * Get current namespace.\n * @returns {string|undefined}\n */\n getCurrentNamespace() {\n return this.path.length > 0 ? this.path[this.path.length - 1].namespace : undefined;\n }\n\n /**\n * Get current node's attribute value.\n * @param {string} attrName\n * @returns {*}\n */\n getAttrValue(attrName) {\n if (this.path.length === 0) return undefined;\n return this.path[this.path.length - 1].values?.[attrName];\n }\n\n /**\n * Check if current node has an attribute.\n * @param {string} attrName\n * @returns {boolean}\n */\n hasAttr(attrName) {\n if (this.path.length === 0) return false;\n const current = this.path[this.path.length - 1];\n return current.values !== undefined && attrName in current.values;\n }\n\n /**\n * Get the value of a \"kept\" attribute from the nearest ancestor (or\n * current node) that declared it via `push(tag, attrs, ns, { keep: [...] })`.\n * Unlike getAttrValue(), this works regardless of how deep the path has\n * gone since the attribute was pushed \u2014 but only for attribute names that\n * were explicitly marked with `keep` at push time. Cost is proportional to\n * the number of currently-kept attributes (typically 0-3), not path depth.\n * @param {string} attrName\n * @returns {*} the value, or undefined if no ancestor kept this attribute\n */\n getAnyParentAttr(attrName) {\n const kept = this._keptAttrs;\n for (let i = kept.length - 1; i >= 0; i--) {\n if (kept[i].name === attrName) return kept[i].value;\n }\n return undefined;\n }\n\n /**\n * Check whether any ancestor (or the current node) kept the given\n * attribute via `push(tag, attrs, ns, { keep: [...] })`.\n * @param {string} attrName\n * @returns {boolean}\n */\n hasAnyParentAttr(attrName) {\n const kept = this._keptAttrs;\n for (let i = kept.length - 1; i >= 0; i--) {\n if (kept[i].name === attrName) return true;\n }\n return false;\n }\n\n /**\n * Get current node's sibling position (child index in parent).\n * @returns {number}\n */\n getPosition() {\n if (this.path.length === 0) return -1;\n return this.path[this.path.length - 1].position ?? 0;\n }\n\n /**\n * Get current node's repeat counter (occurrence count of this tag name).\n * @returns {number}\n */\n getCounter() {\n if (this.path.length === 0) return -1;\n return this.path[this.path.length - 1].counter ?? 0;\n }\n\n /**\n * Get current node's sibling index (alias for getPosition).\n * @returns {number}\n * @deprecated Use getPosition() or getCounter() instead\n */\n getIndex() {\n return this.getPosition();\n }\n\n /**\n * Get current path depth.\n * @returns {number}\n */\n getDepth() {\n return this.path.length;\n }\n\n /**\n * Get path as string.\n * @param {string} [separator] - Optional separator (uses default if not provided)\n * @param {boolean} [includeNamespace=true]\n * @returns {string}\n */\n toString(separator, includeNamespace = true) {\n const sep = separator || this.separator;\n const isDefault = (sep === this.separator && includeNamespace === true);\n\n if (isDefault) {\n if (this._pathStringCache !== null) {\n return this._pathStringCache;\n }\n const result = this.path.map(n =>\n (n.namespace) ? `${n.namespace}:${n.tag}` : n.tag\n ).join(sep);\n this._pathStringCache = result;\n return result;\n }\n\n return this.path.map(n =>\n (includeNamespace && n.namespace) ? `${n.namespace}:${n.tag}` : n.tag\n ).join(sep);\n }\n\n /**\n * Get path as array of tag names.\n * @returns {string[]}\n */\n toArray() {\n return this.path.map(n => n.tag);\n }\n\n /**\n * Reset the path to empty.\n */\n reset() {\n this._pathStringCache = null;\n this.path = [];\n this.siblingStacks = [];\n this._keptAttrs = [];\n }\n\n /**\n * Match current path against an Expression.\n * @param {Expression} expression\n * @returns {boolean}\n */\n matches(expression) {\n const segments = expression.segments;\n\n if (segments.length === 0) {\n return false;\n }\n\n if (expression.hasDeepWildcard()) {\n return this._matchWithDeepWildcard(segments);\n }\n\n return this._matchSimple(segments);\n }\n\n /**\n * @private\n */\n _matchSimple(segments) {\n if (this.path.length !== segments.length) {\n return false;\n }\n\n for (let i = 0; i < segments.length; i++) {\n if (!this._matchSegment(segments[i], this.path[i], i === this.path.length - 1)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * @private\n */\n _matchWithDeepWildcard(segments) {\n let pathIdx = this.path.length - 1;\n let segIdx = segments.length - 1;\n\n while (segIdx >= 0 && pathIdx >= 0) {\n const segment = segments[segIdx];\n\n if (segment.type === 'deep-wildcard') {\n segIdx--;\n\n if (segIdx < 0) {\n return true;\n }\n\n const nextSeg = segments[segIdx];\n let found = false;\n\n for (let i = pathIdx; i >= 0; i--) {\n if (this._matchSegment(nextSeg, this.path[i], i === this.path.length - 1)) {\n pathIdx = i - 1;\n segIdx--;\n found = true;\n break;\n }\n }\n\n if (!found) {\n return false;\n }\n } else {\n if (!this._matchSegment(segment, this.path[pathIdx], pathIdx === this.path.length - 1)) {\n return false;\n }\n pathIdx--;\n segIdx--;\n }\n }\n\n return segIdx < 0;\n }\n\n /**\n * @private\n */\n _matchSegment(segment, node, isCurrentNode) {\n if (segment.tag !== '*' && segment.tag !== node.tag) {\n return false;\n }\n\n if (segment.namespace !== undefined) {\n if (segment.namespace !== '*' && segment.namespace !== node.namespace) {\n return false;\n }\n }\n\n if (segment.attrName !== undefined) {\n if (!isCurrentNode) {\n return false;\n }\n\n if (!node.values || !(segment.attrName in node.values)) {\n return false;\n }\n\n if (segment.attrValue !== undefined) {\n if (String(node.values[segment.attrName]) !== String(segment.attrValue)) {\n return false;\n }\n }\n }\n\n if (segment.position !== undefined) {\n if (!isCurrentNode) {\n return false;\n }\n\n const counter = node.counter ?? 0;\n\n if (segment.position === 'first' && counter !== 0) {\n return false;\n } else if (segment.position === 'odd' && counter % 2 !== 1) {\n return false;\n } else if (segment.position === 'even' && counter % 2 !== 0) {\n return false;\n } else if (segment.position === 'nth' && counter !== segment.positionValue) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Match any expression in the given set against the current path.\n * @param {ExpressionSet} exprSet\n * @returns {boolean}\n */\n matchesAny(exprSet) {\n return exprSet.matchesAny(this);\n }\n\n /**\n * Create a snapshot of current state.\n * @returns {Object}\n */\n snapshot() {\n return {\n path: this.path.map(node => ({ ...node })),\n siblingStacks: this.siblingStacks.map(level => level ? { counts: new Map(level.counts), total: level.total } : level),\n keptAttrs: this._keptAttrs.map(entry => ({ ...entry }))\n };\n }\n\n /**\n * Restore state from snapshot.\n * @param {Object} snapshot\n */\n restore(snapshot) {\n this._pathStringCache = null;\n this.path = snapshot.path.map(node => ({ ...node }));\n this.siblingStacks = snapshot.siblingStacks.map(level => level ? { counts: new Map(level.counts), total: level.total } : level);\n this._keptAttrs = (snapshot.keptAttrs || []).map(entry => ({ ...entry }));\n }\n\n /**\n * Return the read-only {@link MatcherView} for this matcher.\n *\n * The same instance is returned on every call \u2014 no allocation occurs.\n * It always reflects the current parser state and is safe to pass to\n * user callbacks without risk of accidental mutation.\n *\n * @returns {MatcherView}\n *\n * @example\n * const view = matcher.readOnly();\n * // pass view to callbacks \u2014 it stays in sync automatically\n * view.matches(expr); // \u2713\n * view.getCurrentTag(); // \u2713\n * // view.push(...) // \u2717 method does not exist \u2014 caught by TypeScript\n */\n readOnly() {\n return this._view;\n }\n}\n", "/**\n * HTML context patterns.\n *\n * Detects XSS vectors that are dangerous when a string ends up rendered as HTML.\n * All patterns use bounded quantifiers to ensure linear-time matching (ReDoS-safe).\n *\n * Each entry is { pattern: RegExp, id: string, description: string }\n * so callers can inspect which rule fired if they need to.\n */\n\nconst HTML_PATTERNS = [\n {\n id: 'html-script-open',\n description: '<script opening tag',\n pattern: /<script[\\s>/]/i,\n },\n {\n id: 'html-script-close',\n description: '</script closing tag',\n pattern: /<\\/script[\\s>]/i,\n },\n {\n id: 'html-javascript-protocol',\n description: 'javascript: URI scheme (with optional whitespace/encoding)',\n // Handles j&#x61;vascript:, j\\u0061vascript:, and whitespace variants\n pattern: /j[\\t\\n\\r ]*a[\\t\\n\\r ]*v[\\t\\n\\r ]*a[\\t\\n\\r ]*s[\\t\\n\\r ]*c[\\t\\n\\r ]*r[\\t\\n\\r ]*i[\\t\\n\\r ]*p[\\t\\n\\r ]*t[\\t\\n\\r ]*:/i,\n },\n {\n id: 'html-vbscript-protocol',\n description: 'vbscript: URI scheme',\n pattern: /vbscript[\\t\\n\\r ]*:/i,\n },\n {\n id: 'html-data-html',\n description: 'data:text/html URI \u2014 can execute scripts in browsers',\n pattern: /data[\\t\\n\\r ]*:[\\t\\n\\r ]*text\\/html/i,\n },\n {\n id: 'html-data-xhtml',\n description: 'data:application/xhtml+xml URI',\n pattern: /data[\\t\\n\\r ]*:[\\t\\n\\r ]*application\\/xhtml/i,\n },\n {\n id: 'html-data-svg',\n description: 'data:image/svg+xml URI \u2014 can execute scripts',\n pattern: /data[\\t\\n\\r ]*:[\\t\\n\\r ]*image\\/svg\\+xml/i,\n },\n {\n id: 'html-inline-event-handler',\n description: 'Inline event handler attributes: onclick=, onerror=, onload=, etc.',\n // \\bon ensures we match a word boundary so \"phonetic=\" is not caught\n pattern: /\\bon\\w{1,30}\\s*=/i,\n },\n {\n id: 'html-entity-obfuscated-script',\n description: 'HTML-entity-encoded <script (e.g. &#x3C;script or &lt;script)',\n // Entities include optional trailing semicolon: &#x3C; or &#x3C (both valid in HTML5)\n pattern: /(?:&#x0*3[Cc];?|&#0*60;?|&lt;)\\s*script/i,\n },\n {\n id: 'html-entity-obfuscated-javascript',\n description: 'HTML-entity-encoded javascript: (partial \u2014 catches common &#106; or &#x6a; for \"j\")',\n pattern: /(?:&#x0*6[Aa];?|&#0*106;?)\\s*(?:&#x0*61;?|a)[\\s\\S]{0,80}script\\s*:/i,\n },\n {\n id: 'html-style-expression',\n description: 'CSS expression() \u2014 IE-era code execution in style attributes',\n pattern: /style[\\s\\S]{0,20}expression\\s*\\(/i,\n },\n {\n id: 'html-object-embed',\n description: '<object or <embed tags that can load active content',\n pattern: /<(?:object|embed)[\\s>/]/i,\n },\n {\n id: 'html-base-tag',\n description: '<base href= \u2014 can hijack all relative URLs on a page',\n pattern: /<base[\\s>]/i,\n },\n {\n id: 'html-meta-refresh',\n description: '<meta http-equiv=\"refresh\" \u2014 can redirect users',\n pattern: /<meta[\\s\\S]{0,40}http-equiv[\\s\\S]{0,20}refresh/i,\n },\n {\n id: 'html-srcdoc',\n description: 'srcdoc= attribute on iframes \u2014 embeds HTML that can run scripts',\n pattern: /srcdoc\\s*=/i,\n },\n {\n id: 'html-iframe',\n description: '<iframe tag',\n pattern: /<iframe[\\s>/]/i,\n },\n {\n id: 'html-form',\n description: '<form tag \u2014 can be used for phishing / credential harvesting injection',\n pattern: /<form[\\s>/]/i,\n },\n];\n\nexport default HTML_PATTERNS;\n", "/**\n * XML context patterns.\n *\n * Detects injection vectors that are specifically dangerous when a string\n * is inserted into an XML document (not HTML rendering context).\n *\n * Key distinction from HTML: these patterns target parser-level attacks \u2014\n * things that can confuse or subvert an XML parser, trigger external entity\n * resolution, or inject DTD content. HTML rendering concerns (XSS) belong\n * in the HTML context.\n */\n\nconst XML_PATTERNS = [\n {\n id: 'xml-cdata-injection',\n description: 'CDATA section injection: <![CDATA[ breaks out of text node context',\n pattern: /<!\\[CDATA\\[/i,\n },\n {\n id: 'xml-cdata-close',\n description: 'CDATA close sequence: ]]> can terminate an enclosing CDATA section',\n pattern: /\\]\\]>/,\n },\n {\n id: 'xml-processing-instruction',\n description: 'XML processing instruction: <?xml-stylesheet or <?php etc.',\n pattern: /<\\?(?:xml[\\- ]|php|asp)/i,\n },\n {\n id: 'xml-doctype-injection',\n description: 'DOCTYPE declaration embedded in content \u2014 can define entities',\n // Match <!DOCTYPE followed by end-of-string, whitespace, or [ (internal subset)\n pattern: /<!DOCTYPE(?:[\\s[]|$)/i,\n },\n {\n id: 'xml-entity-system',\n description: 'SYSTEM keyword \u2014 used in external entity declarations (XXE)',\n pattern: /\\bSYSTEM\\s+[\"']/i,\n },\n {\n id: 'xml-entity-public',\n description: 'PUBLIC keyword \u2014 used in external entity declarations (XXE)',\n pattern: /\\bPUBLIC\\s+[\"']/i,\n },\n {\n id: 'xml-entity-declaration',\n description: '<!ENTITY declaration \u2014 defines entities, potential XXE or entity expansion',\n pattern: /<!ENTITY[\\s%]/i,\n },\n {\n id: 'xml-billion-laughs',\n description: 'Entity reference chaining / billion laughs: repeated &eX; style references',\n // Heuristic: 3+ consecutive entity refs suggests expansion attack\n pattern: /(?:&\\w{1,20};){3,}/,\n },\n {\n id: 'xml-namespace-confusion',\n description: 'xmlns: attribute injection \u2014 can redefine namespaces to confuse parsers',\n // pattern: /\\bxmlns\\s*(?::\\w{1,40})?\\s*=/i,\n pattern: /\\bxmlns(?::\\w{1,40})?\\s*=/i,\n },\n {\n id: 'xml-comment-injection',\n description: '<!-- comment injection \u2014 can hide content from some parsers',\n pattern: /<!--/,\n },\n {\n id: 'xml-comment-close',\n description: '--> closes an enclosing XML comment',\n pattern: /-->/,\n },\n {\n id: 'xml-pi-close',\n description: '?> closes an enclosing processing instruction',\n pattern: /\\?>/,\n },\n];\n\nexport default XML_PATTERNS;\n", "/**\n * SVG context patterns.\n *\n * SVG is XML-based but renders in browsers, giving it a unique attack surface\n * that combines XML parser behaviour with browser rendering and JavaScript execution.\n *\n * Many of these vectors bypass HTML sanitizers that don't understand SVG semantics\n * (DOMPurify has documented bypass vulnerabilities specifically in SVG/XML context).\n */\n\nconst SVG_PATTERNS = [\n {\n id: 'svg-script-element',\n description: '<script element inside SVG executes JavaScript',\n pattern: /<script[\\s>/]/i,\n },\n {\n id: 'svg-xlink-href-javascript',\n description: 'xlink:href with javascript: \u2014 classic SVG XSS via <a> or <use>',\n pattern: /xlink\\s*:\\s*href\\s*=\\s*[\"']?\\s*javascript\\s*:/i,\n },\n {\n id: 'svg-href-javascript',\n description: 'href= with javascript: in SVG context (<a>, <animate>, etc.)',\n pattern: /href\\s*=\\s*[\"']?\\s*javascript\\s*:/i,\n },\n {\n id: 'svg-foreignobject',\n description: '<foreignObject embeds HTML inside SVG \u2014 can execute scripts',\n pattern: /<foreignObject[\\s>/]/i,\n },\n {\n id: 'svg-use-external',\n description: '<use xlink:href or href pointing to external resource (non-fragment URL)',\n // Match <use with href= where the value starts with a non-# character (external URL)\n // [\\\"'][^#] catches quoted values not starting with #; [^\\\"'#\\s>] catches unquoted\n pattern: /<use[\\s\\S]{0,60}(?:xlink\\s*:\\s*)?href\\s*=\\s*(?:[\"'][^#]|[^\"'#\\s>])/i,\n },\n {\n id: 'svg-animate-href',\n description: '<animate attributeName=\"href\" \u2014 can dynamically change href to javascript:',\n pattern: /<animate[\\s\\S]{0,80}attributeName\\s*=\\s*[\"'][\\s]*href[\"']/i,\n },\n {\n id: 'svg-animate-xlinkhref',\n description: '<animate attributeName=\"xlink:href\"',\n pattern: /<animate[\\s\\S]{0,80}attributeName\\s*=\\s*[\"'][\\s]*xlink\\s*:\\s*href[\"']/i,\n },\n {\n id: 'svg-set-javascript',\n description: '<set to=\"javascript:...\" \u2014 sets an attribute to a javascript: URI',\n pattern: /<set[\\s\\S]{0,80}to\\s*=\\s*[\"']?\\s*javascript\\s*:/i,\n },\n {\n id: 'svg-event-handler',\n description: 'SVG-specific event handler attributes: onload=, onerror=, onactivate=, etc.',\n pattern: /\\bon(?:load|error|activate|begin|end|repeat|focus|blur|click|mouse\\w{1,20}|key\\w{1,20})\\s*=/i,\n },\n {\n id: 'svg-handler-generic',\n description: 'Generic on* handler catch-all for SVG attributes',\n pattern: /\\bon\\w{1,30}\\s*=/i,\n },\n {\n id: 'svg-filter-feimage',\n description: '<feImage href= \u2014 filter primitive that can load external resources',\n pattern: /<feImage[\\s\\S]{0,80}(?:xlink\\s*:\\s*)?href\\s*=/i,\n },\n {\n id: 'svg-image-external',\n description: '<image xlink:href with http/https or javascript protocol',\n pattern: /<image[\\s\\S]{0,80}(?:xlink\\s*:\\s*)?href\\s*=\\s*[\"']?\\s*(?:https?|javascript)\\s*:/i,\n },\n {\n id: 'svg-style-javascript',\n description: 'style= attribute containing javascript: (e.g. background:url(javascript:...))',\n pattern: /style\\s*=[\\s\\S]{0,60}javascript\\s*:/i,\n },\n];\n\nexport default SVG_PATTERNS;\n", "/**\n * SQL context patterns \u2014 high-precision rules only.\n *\n * These rules have very low false-positive risk and are safe to apply to\n * general user text (names, descriptions, search queries, etc.).\n * All patterns are ReDoS-safe \u2014 unlike the `sql-injection` npm package\n * which has an active CVE on its own detection regexes.\n *\n * For exhaustive coverage including noisier heuristics (comment sequences,\n * hex literals, stacked queries with semicolons), use 'SQL-STRICT' instead.\n * Apply 'SQL-STRICT' only to strings that are specifically SQL fragments,\n * not to general free-text fields.\n */\n\nconst SQL_PATTERNS = [\n {\n id: 'sql-block-comment-open',\n description: 'SQL block comment open: /* ... */ \u2014 unusual in legitimate user text',\n pattern: /\\/\\*/,\n },\n {\n id: 'sql-union-select',\n description: 'UNION SELECT \u2014 most common SQL injection aggregation attack',\n pattern: /\\bUNION\\s{1,20}(?:ALL\\s{1,20})?SELECT\\b/i,\n },\n {\n id: 'sql-drop-table',\n description: 'DROP TABLE \u2014 destructive DDL injection',\n pattern: /\\bDROP\\s{1,20}TABLE\\b/i,\n },\n {\n id: 'sql-drop-database',\n description: 'DROP DATABASE \u2014 destructive DDL injection',\n pattern: /\\bDROP\\s{1,20}DATABASE\\b/i,\n },\n {\n id: 'sql-insert-into',\n description: 'INSERT INTO \u2014 data injection',\n pattern: /\\bINSERT\\s{1,20}INTO\\b/i,\n },\n {\n id: 'sql-delete-from',\n description: 'DELETE FROM \u2014 data deletion injection',\n pattern: /\\bDELETE\\s{1,20}FROM\\b/i,\n },\n {\n id: 'sql-update-set',\n description: 'UPDATE ... SET \u2014 data modification injection',\n // Allows arbitrary content between UPDATE and SET (table name, alias, etc.)\n pattern: /\\bUPDATE\\b[\\s\\S]{1,60}\\bSET\\b/i,\n },\n {\n id: 'sql-exec-xp',\n description: 'EXEC xp_ \u2014 MSSQL extended stored procedure execution',\n pattern: /\\bEXEC(?:UTE)?\\s{1,20}xp_/i,\n },\n {\n id: 'sql-tautology-string',\n description: \"Classic string tautology: ' OR '1'='1 or \\\" OR \\\"1\\\"=\\\"1\\\"\",\n // Last quote is optional \u2014 injection may truncate it: ' OR '1'='1--\n pattern: /'\\s{0,10}OR\\s{0,10}'[^']{0,20}'\\s*=\\s*'[^']{0,20}/i,\n },\n {\n id: 'sql-tautology-numeric',\n description: 'Numeric tautology: OR 1=1',\n pattern: /\\bOR\\s{1,10}1\\s*=\\s*1\\b/i,\n },\n {\n id: 'sql-always-true-zero',\n description: 'Numeric tautology: OR 0=0',\n pattern: /\\bOR\\s{1,10}0\\s*=\\s*0\\b/i,\n },\n {\n id: 'sql-sleep-benchmark',\n description: 'Time-based blind injection: SLEEP() or BENCHMARK()',\n pattern: /\\b(?:SLEEP|BENCHMARK)\\s*\\(/i,\n },\n {\n id: 'sql-waitfor-delay',\n description: 'MSSQL time-based blind injection: WAITFOR DELAY',\n pattern: /\\bWAITFOR\\s{1,20}DELAY\\b/i,\n },\n {\n id: 'sql-char-function',\n description: 'CHAR() function \u2014 used to obfuscate injected strings',\n pattern: /\\bCHAR\\s*\\(\\s*\\d{1,3}/i,\n },\n {\n id: 'sql-information-schema',\n description: 'INFORMATION_SCHEMA \u2014 reconnaissance query for table/column enumeration',\n pattern: /\\bINFORMATION_SCHEMA\\b/i,\n },\n];\n\nexport default SQL_PATTERNS;\n", "/**\n * SHELL context patterns.\n *\n * Detects shell injection vectors and path traversal patterns.\n * Designed for use when a string will be passed to a shell command,\n * used as a file path, or interpolated into OS-level operations.\n */\n\nconst SHELL_PATTERNS = [\n {\n id: 'shell-path-traversal-unix',\n description: 'Unix path traversal: ../ \u2014 climbing the directory tree',\n pattern: /\\.\\.\\//,\n },\n {\n id: 'shell-path-traversal-windows',\n description: 'Windows path traversal: ..\\\\ \u2014 climbing the directory tree',\n pattern: /\\.\\.\\\\/,\n },\n {\n id: 'shell-path-traversal-encoded',\n description: 'URL-encoded path traversal: %2e%2e or %2f variants',\n pattern: /%2e%2e|%2f\\.\\.|\\.\\.%2f/i,\n },\n {\n id: 'shell-null-byte',\n description: 'Null byte injection: \\\\x00 or %00 \u2014 truncates strings in C-backed functions',\n pattern: /\\x00|%00/,\n },\n {\n id: 'shell-semicolon',\n description: 'Semicolon command separator: cmd1; cmd2',\n pattern: /;/,\n },\n {\n id: 'shell-pipe',\n description: 'Pipe operator: cmd1 | cmd2',\n pattern: /\\|/,\n },\n {\n id: 'shell-and-operator',\n description: 'AND operator: cmd1 && cmd2',\n pattern: /&&/,\n },\n {\n id: 'shell-or-operator',\n description: 'OR operator: cmd1 || cmd2',\n pattern: /\\|\\|/,\n },\n {\n id: 'shell-backtick',\n description: 'Backtick command substitution: `cmd`',\n pattern: /`/,\n },\n {\n id: 'shell-dollar-paren',\n description: 'Dollar-paren command substitution: $(cmd)',\n pattern: /\\$\\(/,\n },\n {\n id: 'shell-dollar-brace',\n description: 'Dollar-brace variable expansion: ${var} \u2014 can be abused for injection',\n pattern: /\\$\\{/,\n },\n {\n id: 'shell-redirect-out',\n description: 'Output redirection: cmd > file or cmd >> file',\n pattern: />{1,2}/,\n },\n {\n id: 'shell-redirect-in',\n description: 'Input redirection: cmd < file',\n pattern: /</,\n },\n {\n id: 'shell-newline-injection',\n description: 'Newline injection: \\\\n or \\\\r \u2014 can inject new shell commands',\n pattern: /[\\n\\r]/,\n },\n {\n id: 'shell-glob-star',\n description: 'Glob expansion: * or ? \u2014 can expand to unintended files',\n // Only flag when combined with path separators to reduce false positives\n pattern: /[/\\\\][*?]/,\n },\n {\n id: 'shell-absolute-root',\n description: 'Absolute root path injection: string starting with / or \\\\ (Windows UNC)',\n pattern: /^(?:\\/|\\\\\\\\)/,\n },\n {\n id: 'shell-windows-drive',\n description: 'Windows drive letter path injection: C:\\\\ or D:/',\n pattern: /^[a-zA-Z]:[/\\\\]/,\n },\n {\n id: 'shell-curl-wget',\n description: 'curl/wget with URL or flags \u2014 can exfiltrate data or download payloads',\n // Require a URL scheme (http/https/ftp) or a flag (-) to reduce false positives\n // \"curl is a tool\" won't match; \"curl http://...\" or \"curl -s ...\" will\n pattern: /\\b(?:curl|wget)\\s+(?:https?:\\/\\/|ftp:\\/\\/|-)/i,\n },\n];\n\nexport default SHELL_PATTERNS;\n", "/**\n * REDOS context patterns.\n *\n * Detects strings that, if used as regular expressions, could cause\n * catastrophic backtracking (ReDoS \u2014 Regular Expression Denial of Service).\n *\n * These patterns detect the structural forms that lead to exponential or\n * polynomial backtracking in NFA-based regex engines (V8, PCRE, Java, etc.).\n *\n * Use this context when user-supplied strings will be compiled into RegExp objects.\n */\n\nconst REDOS_PATTERNS = [\n {\n id: 'redos-nested-quantifier-plus',\n description: 'Nested + quantifier inside a group with outer quantifier: (a+)+, (.+b)*, etc.',\n // Matches any group containing a + quantifier, with an outer * or + \u2014 catches (a+)+, (.+b)*, etc.\n pattern: /\\([^)]*\\+[^)]*\\)[+*]/,\n },\n {\n id: 'redos-nested-quantifier-star',\n description: 'Nested * quantifier: (a*)* or (a*)+ \u2014 catastrophic backtracking',\n pattern: /\\([^)]*\\*[^)]*\\)[*+]/,\n },\n {\n id: 'redos-nested-groups',\n description: 'Doubly nested quantified groups: ((a+)+) \u2014 guaranteed catastrophic',\n pattern: /\\(\\([^)]{0,40}\\)[+*]\\)[+*]/,\n },\n {\n id: 'redos-alternation-overlap',\n description: 'Overlapping alternation under quantifier: (a|a)+ \u2014 ambiguous NFA paths',\n // Detect repeated identical alternatives under a quantifier\n pattern: /\\(([^|()]{1,20})\\|(?:\\1)(?:\\|[^|()]{1,20}){0,5}\\)[+*?]{1,2}/,\n },\n {\n id: 'redos-star-plus-concat',\n description: '(x*x)+ pattern \u2014 triggers super-linear backtracking',\n pattern: /\\([^)]{0,10}\\*[^)]{0,10}\\)[+*]/,\n },\n {\n id: 'redos-dot-star-greedy',\n description: '(.*){n,} or (.+){n,} \u2014 repeated greedy dot quantifiers',\n pattern: /\\(\\.[*+]\\)\\{?\\d/,\n },\n {\n id: 'redos-large-repetition',\n description: 'Very large fixed or range repetition count {1000,} or {1000,n} \u2014 denial of service via backtracking',\n // Matches { followed by 4+ digits (\u22651000), then optional ,digits }\n pattern: /\\{\\d{4,}(?:,\\d*)?\\}/,\n },\n {\n id: 'redos-catastrophic-alternation',\n description: 'Long alternation with many similar branches \u2014 polynomial backtracking risk',\n // Heuristic: 10+ pipe-separated alternatives in a single group\n pattern: /\\([^)]{0,200}(?:\\|[^|)]{0,50}){9,}\\)/,\n },\n];\n\nexport default REDOS_PATTERNS;\n", "/**\n * NOSQL context patterns.\n *\n * Detects injection vectors specific to NoSQL databases (primarily MongoDB)\n * and JavaScript-evaluated queries.\n *\n * Attack categories:\n * 1. MongoDB query operator injection: $where, $ne, $gt, $regex, $or, $and, etc.\n * These operators, when injected into a JSON query object, can bypass\n * authentication or exfiltrate data without knowing passwords.\n *\n * 2. JavaScript execution: $where clauses execute arbitrary JS server-side.\n *\n * 3. Prototype pollution: __proto__, constructor.prototype \u2014 can corrupt\n * the prototype chain of all objects in the Node.js process.\n *\n * Pattern note: MongoDB operators appear as JSON keys. In JSON, keys are\n * quoted: {\"$where\": ...} so the pattern must allow an optional closing\n * quote between the operator name and the colon: /\\$where[\"'\\s]*:/\n */\n\n// Shared suffix: optional closing quote/whitespace before the colon\n// Handles: $op: (bare), \"$op\": (JSON), '$op': (single-quoted)\nconst SEP = /[\"'\\s]*:/;\nconst sep = '[\"\\'\\\\s]*:';\n\nconst NOSQL_PATTERNS = [\n // \u2500\u2500\u2500 MongoDB $ operator injection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n {\n id: 'nosql-where-operator',\n description: '$where \u2014 executes arbitrary JavaScript server-side in MongoDB',\n pattern: new RegExp(`\\\\$where${sep}`, 'i'),\n },\n {\n id: 'nosql-ne-operator',\n description: '$ne \u2014 \"not equal\" operator used to bypass equality checks',\n pattern: new RegExp(`\\\\$ne${sep}`, 'i'),\n },\n {\n id: 'nosql-gt-operator',\n description: '$gt \u2014 \"greater than\" used to bypass password/value checks',\n pattern: new RegExp(`\\\\$gte?${sep}`, 'i'),\n },\n {\n id: 'nosql-lt-operator',\n description: '$lt / $lte \u2014 \"less than\" bypass variants',\n pattern: new RegExp(`\\\\$lte?${sep}`, 'i'),\n },\n {\n id: 'nosql-regex-operator',\n description: '$regex \u2014 can be used to extract data character by character (blind injection)',\n pattern: new RegExp(`\\\\$regex${sep}`, 'i'),\n },\n {\n id: 'nosql-or-operator',\n description: '$or \u2014 logical OR; used to create always-true conditions',\n pattern: new RegExp(`\\\\$or${sep}\\\\s*\\\\[`, 'i'),\n },\n {\n id: 'nosql-and-operator',\n description: '$and \u2014 logical AND operator injection',\n pattern: new RegExp(`\\\\$and${sep}\\\\s*\\\\[`, 'i'),\n },\n {\n id: 'nosql-nor-operator',\n description: '$nor \u2014 logical NOR operator injection',\n pattern: new RegExp(`\\\\$nor${sep}\\\\s*\\\\[`, 'i'),\n },\n {\n id: 'nosql-exists-operator',\n description: '$exists \u2014 can enumerate fields to determine schema',\n pattern: new RegExp(`\\\\$exists${sep}`, 'i'),\n },\n {\n id: 'nosql-in-operator',\n description: '$in \u2014 matches any value in a list; can enumerate values',\n pattern: new RegExp(`\\\\$in${sep}\\\\s*\\\\[`, 'i'),\n },\n {\n id: 'nosql-expr-operator',\n description: '$expr \u2014 allows aggregation expressions in queries (MongoDB 3.6+)',\n pattern: new RegExp(`\\\\$expr${sep}`, 'i'),\n },\n {\n id: 'nosql-function-operator',\n description: '$function \u2014 executes arbitrary JavaScript in MongoDB 4.4+',\n pattern: new RegExp(`\\\\$function${sep}`, 'i'),\n },\n {\n id: 'nosql-accumulator-operator',\n description: '$accumulator \u2014 custom aggregation with arbitrary JS execution',\n pattern: new RegExp(`\\\\$accumulator${sep}`, 'i'),\n },\n // \u2500\u2500\u2500 Prototype pollution \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n {\n id: 'nosql-proto-pollution',\n description: '__proto__ \u2014 prototype pollution via object key injection',\n pattern: /__proto__/,\n },\n {\n id: 'nosql-constructor-prototype',\n description: 'constructor.prototype \u2014 alternative prototype pollution vector (dot notation or JSON key)',\n // Matches dot-notation (obj.constructor.prototype) and JSON key adjacency\n // (\"constructor\": {\"prototype\": ...})\n pattern: /constructor[\\s\"':.,{\\[]*prototype/i,\n },\n {\n id: 'nosql-proto-bracket',\n description: '[\"__proto__\"] \u2014 bracket-notation prototype pollution',\n pattern: /\\[[\"']__proto__[\"']\\]/,\n },\n];\n\nexport default NOSQL_PATTERNS;\n", "/**\n * LOG context patterns.\n *\n * Detects injection vectors that are dangerous when a string is written\n * to a log file, passed to a logging framework, or interpolated into\n * a log message that will be parsed or displayed.\n *\n * Attack categories:\n * 1. CRLF injection \u2014 injects fake log lines by embedding newlines\n * 2. Log4Shell (CVE-2021-44228) \u2014 ${jndi:...} triggers JNDI lookup in Log4j\n * 3. SSTI in log templates \u2014 {{...}}, #{...} trigger template evaluation\n * if the log message is passed through a template engine\n * 4. Null byte injection \u2014 truncates log entries in some implementations\n * 5. ANSI escape injection \u2014 manipulates terminal output when logs are\n * tailed in a terminal (colour codes, cursor movement, etc.)\n *\n * Note: Newline characters (\\n, \\r) will produce false positives for\n * multi-line legitimate values. Use this context only for single-line\n * log field values (usernames, IDs, request parameters, etc.).\n */\n\nconst LOG_PATTERNS = [\n // \u2500\u2500\u2500 CRLF / newline injection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n {\n id: 'log-crlf-injection',\n description: 'CRLF injection: literal \\\\r or \\\\n embeds fake log lines',\n pattern: /[\\r\\n]/,\n },\n {\n id: 'log-url-encoded-crlf',\n description: 'URL-encoded CRLF: %0d, %0a, %0D, %0A \u2014 decoded by some log parsers',\n pattern: /%0[dDaA]/,\n },\n {\n id: 'log-unicode-newline',\n description: 'Unicode newline variants: U+2028 (line separator), U+2029 (paragraph separator)',\n pattern: /[\\u2028\\u2029]/,\n },\n\n // \u2500\u2500\u2500 Log4Shell / JNDI injection (CVE-2021-44228) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n {\n id: 'log-log4shell-jndi',\n description: 'Log4Shell: ${jndi:...} triggers remote code execution in Apache Log4j',\n pattern: /\\$\\{jndi\\s*:/i,\n },\n {\n id: 'log-log4shell-obfuscated',\n description: 'Obfuscated Log4Shell: ${::-j}... lookup-bypass prefix used to evade WAF detection',\n // ${::- is the Log4j lookup-bypass escape sequence; presence alone is suspicious\n pattern: /\\$\\{::-/,\n },\n {\n id: 'log-log4j-lookup',\n description: 'Log4j lookup syntax: ${env:...}, ${sys:...}, ${ctx:...} \u2014 data exfiltration',\n pattern: /\\$\\{(?:env|sys|ctx|main|map|sd|web|docker|k8s|spring)\\s*:/i,\n },\n\n // \u2500\u2500\u2500 Server-Side Template Injection (SSTI) in log messages \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n {\n id: 'log-ssti-double-brace',\n description: 'SSTI double-brace: {{expression}} \u2014 Jinja2, Twig, Handlebars, etc.',\n pattern: /\\{\\{[\\s\\S]{0,80}\\}\\}/,\n },\n {\n id: 'log-ssti-hash-brace',\n description: 'SSTI hash-brace: #{expression} \u2014 Thymeleaf, Velocity, Ruby ERB',\n pattern: /#\\{[\\s\\S]{0,80}\\}/,\n },\n {\n id: 'log-ssti-dollar-brace',\n description: 'SSTI/EL injection: ${expression with operators or method calls} \u2014 JSP EL, Freemarker, SpEL',\n // Require that the ${...} content looks like an expression, not a plain variable name.\n // Flags if the content contains: . ( * + operators, or known SSTI keywords.\n // This avoids flagging ${PATH}, ${HOME} etc. (plain shell variables).\n pattern: /\\$\\{[^}]*(?:\\.|\\(|\\*|\\+|\\bclass\\b|\\bruntime\\b|\\bprocess\\b|\\bexec\\b)[^}]{0,80}\\}/i,\n },\n {\n id: 'log-ssti-percent-tag',\n description: 'SSTI ERB/ASP tag: <%= expression %> \u2014 Ruby ERB, ASP',\n pattern: /<%=[\\s\\S]{0,80}%>/,\n },\n\n // \u2500\u2500\u2500 Null byte \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n {\n id: 'log-null-byte',\n description: 'Null byte: \\\\x00 or %00 \u2014 can truncate log entries in C-backed loggers',\n pattern: /\\x00|%00/,\n },\n\n // \u2500\u2500\u2500 ANSI escape injection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n {\n id: 'log-ansi-escape',\n description: 'ANSI escape sequence: ESC[ \u2014 can manipulate terminal output when logs are tailed',\n pattern: /\\x1b\\[/,\n },\n];\n\nexport default LOG_PATTERNS;\n", "/**\n * SQL-STRICT context patterns.\n *\n * Extends the base 'SQL' context with three additional rules that are\n * effective at detecting real injections but carry a higher false-positive\n * risk on general free-text input.\n *\n * Use 'SQL-STRICT' when:\n * - The string is specifically a SQL fragment or database identifier\n * - You control the input domain (e.g. a dedicated SQL search field)\n * - You can tolerate occasional false positives in exchange for broader coverage\n *\n * Use 'SQL' (not STRICT) when:\n * - The field is general user text (names, descriptions, comments)\n * - False positives would block legitimate content (e.g. \"see note -- above\")\n *\n * Rules moved here from 'SQL' due to false-positive risk:\n *\n * sql-line-comment \u2014 \"--\" fires on \"see note -- above\", \"value--\", CSS var(--primary)\n * sql-stacked-query \u2014 \"; SELECT\" fires on legitimate prose with semicolons + SQL words\n * sql-hex-encoding \u2014 \"0xDEAD\" fires on hex values in technical docs and log output\n */\n\nimport SQL_PATTERNS from './sql.js';\n\nconst SQL_STRICT_EXTRA = [\n {\n id: 'sql-line-comment',\n description: 'SQL line comment: -- followed by whitespace or end of string',\n pattern: /--(?:\\s|$)/,\n },\n {\n id: 'sql-stacked-query',\n description: 'Stacked queries: semicolon immediately followed by a SQL keyword',\n pattern: /;\\s{0,10}(?:SELECT|INSERT|UPDATE|DELETE|DROP|CREATE|ALTER|EXEC)\\b/i,\n },\n {\n id: 'sql-hex-encoding',\n description: 'Hex-encoded string injection: 0x41414141 style (MySQL)',\n pattern: /\\b0x[0-9a-f]{4,}/i,\n },\n];\n\n// SQL-STRICT = all base SQL rules + the three noisy extras\nconst SQL_STRICT_PATTERNS = [...SQL_PATTERNS, ...SQL_STRICT_EXTRA];\n\nexport default SQL_STRICT_PATTERNS;\n", "/**\n * is-unsafe v2\n *\n * Zero-dependency, DOM-free, pure predicate for detecting unsafe strings\n * across HTML, XML, SVG, SQL, SQL-STRICT, SHELL, REDOS, NOSQL, and LOG contexts.\n *\n * v2 change: contexts are imported as named pattern arrays rather than resolved\n * via a string-keyed registry. This makes each context independently\n * tree-shakeable \u2014 bundlers can drop any context you never import.\n *\n * @module is-unsafe\n */\n\n// \u2500\u2500\u2500 Context pattern arrays (named exports) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Import only the ones you need. Each is independently tree-shakeable.\n\nexport { default as HTML } from './contexts/html.js';\nexport { default as XML } from './contexts/xml.js';\nexport { default as SVG } from './contexts/svg.js';\nexport { default as SQL } from './contexts/sql.js';\nexport { default as SHELL } from './contexts/shell.js';\nexport { default as REDOS } from './contexts/redos.js';\nexport { default as NOSQL } from './contexts/nosql.js';\nexport { default as LOG } from './contexts/log.js';\n\n// SQL-STRICT needs a quoted identifier because of the hyphen\nimport SQL_STRICT from './contexts/sql-strict.js';\nexport { SQL_STRICT };\n\n// \u2500\u2500\u2500 VALID_CONTEXTS convenience re-export \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Importing this pulls in ALL contexts. Use it only when you need all of them\n// (e.g. for validation UI, tooling, or exhaustive audits).\n// If you only need a subset, import the named contexts directly instead.\n\nimport HTML from './contexts/html.js';\nimport XML from './contexts/xml.js';\nimport SVG from './contexts/svg.js';\nimport SQL from './contexts/sql.js';\nimport SHELL from './contexts/shell.js';\nimport REDOS from './contexts/redos.js';\nimport NOSQL from './contexts/nosql.js';\nimport LOG from './contexts/log.js';\n\n// \u2500\u2500\u2500 Attach labels to named contexts \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Each built-in PatternList carries its canonical name so matchList can read\n// list.label directly \u2014 no registry lookup needed at match time.\n// Custom PatternLists default to 'CUSTOM' unless the caller sets list.label.\n\nHTML.label = 'HTML';\nXML.label = 'XML';\nSVG.label = 'SVG';\nSQL.label = 'SQL';\nSQL_STRICT.label = 'SQL-STRICT';\nSHELL.label = 'SHELL';\nREDOS.label = 'REDOS';\nNOSQL.label = 'NOSQL';\nLOG.label = 'LOG';\n\nexport const VALID_CONTEXTS = Object.freeze({\n HTML,\n XML,\n SVG,\n SQL,\n 'SQL-STRICT': SQL_STRICT,\n SHELL,\n REDOS,\n NOSQL,\n LOG,\n});\n\n// \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * @typedef {{ id: string, description: string, pattern: RegExp }} Rule\n */\n\n/**\n * @typedef {Rule[]} PatternList\n */\n\n/**\n * @typedef {Object} MatchResult\n * @property {string} context - Label identifying which context matched ('HTML', 'CUSTOM', etc.)\n * @property {string} id - Rule identifier\n * @property {string} description - Human-readable description of what was matched\n * @property {RegExp} pattern - The pattern that matched\n */\n\n// \u2500\u2500\u2500 Internal helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * @param {unknown} value\n */\nfunction assertString(value) {\n if (typeof value !== 'string') {\n throw new TypeError(\n `is-unsafe: first argument must be a string, got ${typeof value}`\n );\n }\n}\n\n/**\n * @param {unknown} context\n */\nfunction assertContext(context) {\n if (context instanceof RegExp) return;\n\n if (Array.isArray(context)) {\n if (context.length === 0) {\n throw new TypeError('is-unsafe: context must not be an empty array');\n }\n // Detect array-of-arrays vs flat pattern list\n if (Array.isArray(context[0])) {\n // Array of PatternLists\n for (const list of context) {\n if (!Array.isArray(list) || list.length === 0) {\n throw new TypeError(\n 'is-unsafe: each context in the array must be a non-empty pattern array (PatternList)'\n );\n }\n }\n }\n // else: flat PatternList \u2014 trust it, no deep validation needed\n return;\n }\n\n throw new TypeError(\n `is-unsafe: second argument must be a PatternList (e.g. HTML), ` +\n `an array of PatternLists (e.g. [HTML, XML]), or a RegExp. Got: ${typeof context}`\n );\n}\n\n/**\n * Normalise any valid context arg into an array of PatternLists.\n *\n * @param {Rule[]|Rule[][]|RegExp} context\n * @returns {{ lists: Rule[][]|null, regex: RegExp|null }}\n */\nfunction normalise(context) {\n if (context instanceof RegExp) return { lists: null, regex: context };\n // Distinguish PatternList (array of rule objects) from array of PatternLists\n if (Array.isArray(context[0])) return { lists: context, regex: null };\n return { lists: [context], regex: null };\n}\n\n/**\n * Test value against a single PatternList. Returns the first MatchResult or null.\n *\n * @param {string} value\n * @param {Rule[]} list\n * @returns {MatchResult|null}\n */\nfunction matchList(value, list) {\n const label = list.label ?? 'CUSTOM';\n for (const rule of list) {\n if (rule.pattern.test(value)) {\n return { context: label, id: rule.id, description: rule.description, pattern: rule.pattern };\n }\n }\n return null;\n}\n\n// \u2500\u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Returns `true` if `value` is unsafe in the given context(s), `false` otherwise.\n *\n * @param {string} value - The string to test\n * @param {PatternList | PatternList[] | RegExp} context\n * - A PatternList imported from is-unsafe (e.g. `HTML`, `XML`)\n * - An array of PatternLists \u2014 returns true if unsafe in **any** of them\n * - A custom RegExp \u2014 returns true if the pattern matches\n * @returns {boolean}\n *\n * @example\n * import { isUnsafe, HTML, SQL } from 'is-unsafe';\n *\n * isUnsafe('<script>alert(1)</script>', HTML) // true\n * isUnsafe('hello world', HTML) // false\n * isUnsafe('value', [HTML, SQL]) // false\n * isUnsafe('value', /my-pattern/i) // false\n */\nfunction isUnsafe(value, context) {\n assertString(value);\n assertContext(context);\n\n const { lists, regex } = normalise(context);\n\n if (regex) return regex.test(value);\n\n for (const list of lists) {\n if (matchList(value, list) !== null) return true;\n }\n return false;\n}\n\n/**\n * Like `isUnsafe`, but returns the first `MatchResult` describing **why**\n * the value was flagged, or `null` if it is safe.\n *\n * @param {string} value\n * @param {PatternList | PatternList[] | RegExp} context\n * @returns {MatchResult|null}\n *\n * @example\n * import { whyUnsafe, HTML } from 'is-unsafe';\n *\n * whyUnsafe('<script>alert(1)</script>', HTML)\n * // { context: 'HTML', id: 'html-script-open', description: '...', pattern: /.../ }\n */\nfunction whyUnsafe(value, context) {\n assertString(value);\n assertContext(context);\n\n const { lists, regex } = normalise(context);\n\n if (regex) {\n return regex.test(value)\n ? { context: 'CUSTOM', id: 'custom-regex', description: 'Matched caller-supplied pattern', pattern: regex }\n : null;\n }\n\n for (const list of lists) {\n const result = matchList(value, list);\n if (result !== null) return result;\n }\n return null;\n}\n\n/**\n * Returns **all** matching rules across the given context(s), or an empty\n * array if the value is safe. Useful for comprehensive auditing.\n *\n * @param {string} value\n * @param {PatternList | PatternList[] | RegExp} context\n * @returns {MatchResult[]}\n */\nfunction allUnsafe(value, context) {\n assertString(value);\n assertContext(context);\n\n const { lists, regex } = normalise(context);\n const results = [];\n\n if (regex) {\n if (regex.test(value)) {\n results.push({ context: 'CUSTOM', id: 'custom-regex', description: 'Matched caller-supplied pattern', pattern: regex });\n }\n return results;\n }\n\n for (const list of lists) {\n const label = list.label ?? 'CUSTOM';\n for (const rule of list) {\n if (rule.pattern.test(value)) {\n results.push({ context: label, id: rule.id, description: rule.description, pattern: rule.pattern });\n }\n }\n }\n\n return results;\n}\n\nexport { isUnsafe, whyUnsafe, allUnsafe };\nexport default isUnsafe;\n", "'use strict';\n///@ts-check\n\nimport { getAllMatches, isExist, DANGEROUS_PROPERTY_NAMES, criticalProperties } from '../util.js';\nimport xmlNode from './xmlNode.js';\nimport DocTypeReader from './DocTypeReader.js';\nimport toNumber from \"strnum\";\nimport getIgnoreAttributesFn from \"../ignoreAttributes.js\";\nimport { Expression, Matcher } from 'path-expression-matcher';\nimport { ExpressionSet } from 'path-expression-matcher';\nimport { EntityDecoder, XML, CURRENCY, COMMON_HTML, ENTITY_ACTION } from '@nodable/entities';\nimport { isUnsafe, HTML as HTML_CONTEXT, XML as XML_CONTEXT } from \"is-unsafe\"\n\n\n// const regx =\n// '<((!\\\\[CDATA\\\\[([\\\\s\\\\S]*?)(]]>))|((NAME:)?(NAME))([^>]*)>|((\\\\/)(NAME)\\\\s*>))([^<]*)'\n// .replace(/NAME/g, util.nameRegexp);\n\n//const tagsRegx = new RegExp(\"<(\\\\/?[\\\\w:\\\\-\\._]+)([^>]*)>(\\\\s*\"+cdataRegx+\")*([^<]+)?\",\"g\");\n//const tagsRegx = new RegExp(\"<(\\\\/?)((\\\\w*:)?([\\\\w:\\\\-\\._]+))([^>]*)>([^<]*)(\"+cdataRegx+\"([^<]*))*([^<]+)?\",\"g\");\n\n// Helper functions for attribute and namespace handling\n\n/**\n * Extract raw attributes (without prefix) from prefixed attribute map\n * @param {object} prefixedAttrs - Attributes with prefix from buildAttributesMap\n * @param {object} options - Parser options containing attributeNamePrefix\n * @returns {object} Raw attributes for matcher\n */\nfunction extractRawAttributes(prefixedAttrs, options) {\n if (!prefixedAttrs) return {};\n\n // Handle attributesGroupName option\n const attrs = options.attributesGroupName\n ? prefixedAttrs[options.attributesGroupName]\n : prefixedAttrs;\n\n if (!attrs) return {};\n\n const rawAttrs = {};\n for (const key in attrs) {\n // Remove the attribute prefix to get raw name\n if (key.startsWith(options.attributeNamePrefix)) {\n const rawName = key.substring(options.attributeNamePrefix.length);\n rawAttrs[rawName] = attrs[key];\n } else {\n // Attribute without prefix (shouldn't normally happen, but be safe)\n rawAttrs[key] = attrs[key];\n }\n }\n return rawAttrs;\n}\n\n/**\n * Extract namespace from raw tag name\n * @param {string} rawTagName - Tag name possibly with namespace (e.g., \"soap:Envelope\")\n * @returns {string|undefined} Namespace or undefined\n */\nfunction extractNamespace(rawTagName) {\n if (!rawTagName || typeof rawTagName !== 'string') return undefined;\n\n const colonIndex = rawTagName.indexOf(':');\n if (colonIndex !== -1 && colonIndex > 0) {\n const ns = rawTagName.substring(0, colonIndex);\n // Don't treat xmlns as a namespace\n if (ns !== 'xmlns') {\n return ns;\n }\n }\n return undefined;\n}\n\nexport default class OrderedObjParser {\n constructor(options, externalEntities) {\n this.options = options;\n this.currentNode = null;\n this.tagsNodeStack = [];\n this.parseXml = parseXml;\n this.parseTextData = parseTextData;\n this.resolveNameSpace = resolveNameSpace;\n this.buildAttributesMap = buildAttributesMap;\n this.isItStopNode = isItStopNode;\n this.replaceEntitiesValue = replaceEntitiesValue;\n this.readStopNodeData = readStopNodeData;\n this.saveTextToParentTag = saveTextToParentTag;\n this.addChild = addChild;\n this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes)\n this.entityExpansionCount = 0;\n this.currentExpandedLength = 0;\n this.doctypefound = false;\n let namedEntities = { ...XML };\n if (this.options.entityDecoder) {\n this.entityDecoder = this.options.entityDecoder\n } else {\n if (typeof this.options.htmlEntities === \"object\") namedEntities = this.options.htmlEntities;\n else if (this.options.htmlEntities === true) namedEntities = { ...COMMON_HTML, ...CURRENCY };\n this.entityDecoder = new EntityDecoder({\n namedEntities: { ...namedEntities, ...externalEntities },\n numericAllowed: this.options.htmlEntities,\n limit: {\n maxTotalExpansions: this.options.processEntities.maxTotalExpansions,\n maxExpandedLength: this.options.processEntities.maxExpandedLength,\n applyLimitsTo: this.options.processEntities.appliesTo,\n },\n // onExternalEntity: (name, value) => isUnsafe(value) ? 'block' : 'allow',\n onInputEntity: (name, value) =>\n //TODO: VALID_CONTEXTS.HTML should be set only if this.options.htmlEntities\n isUnsafe(value, [HTML_CONTEXT, XML_CONTEXT]) ? ENTITY_ACTION.BLOCK : ENTITY_ACTION.ALLOW,\n\n //postCheck: resolved => resolved\n });\n }\n\n // Initialize path matcher for path-expression-matcher\n this.matcher = new Matcher();\n this.readonlyMatcher = this.matcher.readOnly();\n\n // Flag to track if current node is a stop node (optimization)\n this.isCurrentNodeStopNode = false;\n\n // Pre-compile stopNodes expressions\n this.stopNodeExpressionsSet = new ExpressionSet();\n const stopNodesOpts = this.options.stopNodes;\n if (stopNodesOpts && stopNodesOpts.length > 0) {\n for (let i = 0; i < stopNodesOpts.length; i++) {\n const stopNodeExp = stopNodesOpts[i];\n if (typeof stopNodeExp === 'string') {\n // Convert string to Expression object\n this.stopNodeExpressionsSet.add(new Expression(stopNodeExp));\n } else if (stopNodeExp instanceof Expression) {\n // Already an Expression object\n this.stopNodeExpressionsSet.add(stopNodeExp);\n }\n }\n this.stopNodeExpressionsSet.seal();\n }\n }\n\n}\n\n\n/**\n * @param {string} val\n * @param {string} tagName\n * @param {string|Matcher} jPath - jPath string or Matcher instance based on options.jPath\n * @param {boolean} dontTrim\n * @param {boolean} hasAttributes\n * @param {boolean} isLeafNode\n * @param {boolean} escapeEntities\n */\nfunction parseTextData(val, tagName, jPath, dontTrim, hasAttributes, isLeafNode, escapeEntities) {\n const options = this.options;\n if (val !== undefined) {\n if (options.trimValues && !dontTrim) {\n val = val.trim();\n }\n if (val.length > 0) {\n if (!escapeEntities) val = this.replaceEntitiesValue(val, tagName, jPath);\n\n // Pass jPath string or matcher based on options.jPath setting\n const jPathOrMatcher = options.jPath ? jPath.toString() : jPath;\n const newval = options.tagValueProcessor(tagName, val, jPathOrMatcher, hasAttributes, isLeafNode);\n if (newval === null || newval === undefined) {\n //don't parse\n return val;\n } else if (typeof newval !== typeof val || newval !== val) {\n //overwrite\n return newval;\n } else if (options.trimValues) {\n return parseValue(val, options.parseTagValue, options.numberParseOptions);\n } else {\n const trimmedVal = val.trim();\n if (trimmedVal === val) {\n return parseValue(val, options.parseTagValue, options.numberParseOptions);\n } else {\n return val;\n }\n }\n }\n }\n}\n\nfunction resolveNameSpace(tagname) {\n if (this.options.removeNSPrefix) {\n const tags = tagname.split(':');\n const prefix = tagname.charAt(0) === '/' ? '/' : '';\n if (tags[0] === 'xmlns') {\n return '';\n }\n if (tags.length === 2) {\n tagname = prefix + tags[1];\n }\n }\n return tagname;\n}\n\n//TODO: change regex to capture NS\n//const attrsRegx = new RegExp(\"([\\\\w\\\\-\\\\.\\\\:]+)\\\\s*=\\\\s*(['\\\"])((.|\\n)*?)\\\\2\",\"gm\");\nconst attrsRegx = new RegExp('([^\\\\s=]+)\\\\s*(=\\\\s*([\\'\"])([\\\\s\\\\S]*?)\\\\3)?', 'gm');\n\nfunction buildAttributesMap(attrStr, jPath, tagName, force = false) {\n const options = this.options;\n if (force === true || (options.ignoreAttributes !== true && typeof attrStr === 'string')) {\n // attrStr = attrStr.replace(/\\r?\\n/g, ' ');\n //attrStr = attrStr || attrStr.trim();\n\n const matches = getAllMatches(attrStr, attrsRegx);\n const len = matches.length; //don't make it inline\n const attrs = {};\n\n // Pre-process values once: trim + entity replacement\n // Reused in both matcher update and second pass\n const processedVals = new Array(len);\n let hasRawAttrs = false;\n const rawAttrsForMatcher = {};\n\n for (let i = 0; i < len; i++) {\n const attrName = this.resolveNameSpace(matches[i][1]);\n const oldVal = matches[i][4];\n\n if (attrName.length && oldVal !== undefined) {\n let val = oldVal;\n if (options.trimValues) val = val.trim();\n val = this.replaceEntitiesValue(val, tagName, this.readonlyMatcher);\n processedVals[i] = val;\n\n rawAttrsForMatcher[attrName] = val;\n hasRawAttrs = true;\n }\n }\n\n // Update matcher ONCE before second pass, if applicable\n if (hasRawAttrs && typeof jPath === 'object' && jPath.updateCurrent) {\n jPath.updateCurrent(rawAttrsForMatcher);\n }\n\n // Hoist toString() once \u2014 path doesn't change during attribute processing\n const jPathStr = options.jPath ? jPath.toString() : this.readonlyMatcher;\n\n // Second pass: apply processors, build final attrs\n let hasAttrs = false;\n for (let i = 0; i < len; i++) {\n const attrName = this.resolveNameSpace(matches[i][1]);\n\n if (this.ignoreAttributesFn(attrName, jPathStr)) continue;\n\n let aName = options.attributeNamePrefix + attrName;\n\n if (attrName.length) {\n if (options.transformAttributeName) {\n aName = options.transformAttributeName(aName);\n }\n aName = sanitizeName(aName, options);\n\n if (matches[i][4] !== undefined) {\n // Reuse already-processed value \u2014 no double entity replacement\n const oldVal = processedVals[i];\n\n const newVal = options.attributeValueProcessor(attrName, oldVal, jPathStr);\n if (newVal === null || newVal === undefined) {\n attrs[aName] = oldVal;\n } else if (typeof newVal !== typeof oldVal || newVal !== oldVal) {\n attrs[aName] = newVal;\n } else {\n attrs[aName] = parseValue(oldVal, options.parseAttributeValue, options.numberParseOptions);\n }\n hasAttrs = true;\n } else if (options.allowBooleanAttributes) {\n attrs[aName] = true;\n hasAttrs = true;\n }\n }\n }\n\n if (!hasAttrs) return;\n\n if (options.attributesGroupName && !options.preserveOrder) {\n const attrCollection = {};\n attrCollection[options.attributesGroupName] = attrs;\n return attrCollection;\n }\n return attrs;\n }\n}\nconst parseXml = function (xmlData) {\n xmlData = xmlData.replace(/\\r\\n?/g, \"\\n\"); //TODO: remove this line\n const xmlObj = new xmlNode('!xml');\n let currentNode = xmlObj;\n let textData = \"\";\n\n // Reset matcher for new document\n this.matcher.reset();\n this.entityDecoder.reset();\n\n // Reset entity expansion counters for this document\n this.entityExpansionCount = 0;\n this.currentExpandedLength = 0;\n this.doctypefound = false;\n const options = this.options;\n const docTypeReader = new DocTypeReader(options.processEntities);\n const xmlLen = xmlData.length;\n for (let i = 0; i < xmlLen; i++) {//for each char in XML data\n const ch = xmlData[i];\n if (ch === '<') {\n // const nextIndex = i+1;\n // const _2ndChar = xmlData[nextIndex];\n const c1 = xmlData.charCodeAt(i + 1);\n if (c1 === 47) {//Closing Tag '/'\n const closeIndex = findClosingIndex(xmlData, \">\", i, \"Closing Tag is not closed.\")\n let tagName = xmlData.substring(i + 2, closeIndex).trim();\n\n if (options.removeNSPrefix) {\n const colonIndex = tagName.indexOf(\":\");\n if (colonIndex !== -1) {\n tagName = tagName.substr(colonIndex + 1);\n }\n }\n\n tagName = transformTagName(options.transformTagName, tagName, \"\", options).tagName;\n\n if (currentNode) {\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);\n }\n\n //check if last tag of nested tag was unpaired tag\n const lastTagName = this.matcher.getCurrentTag();\n if (tagName && options.unpairedTagsSet.has(tagName)) {\n throw new Error(`Unpaired tag can not be used as closing tag: </${tagName}>`);\n }\n if (lastTagName && options.unpairedTagsSet.has(lastTagName)) {\n // Pop the unpaired tag\n this.matcher.pop();\n this.tagsNodeStack.pop();\n }\n // Pop the closing tag\n this.matcher.pop();\n this.isCurrentNodeStopNode = false; // Reset flag when closing tag\n\n //a closing tag with no matching opening tag leaves the stack empty\n currentNode = this.tagsNodeStack.pop() || xmlObj;//avoid recursion, set the parent tag scope\n\n if (options.captureMetaData && currentNode) {\n currentNode.addEndIndex(closeIndex + 1);\n }\n textData = \"\";\n i = closeIndex;\n } else if (c1 === 63) { //'?'\n\n let tagData = readTagExp(xmlData, i, false, \"?>\");\n if (!tagData) throw new Error(\"Pi Tag is not closed.\");\n\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);\n const attsMap = this.buildAttributesMap(tagData.tagExp, this.matcher, tagData.tagName, true);\n if (attsMap) {\n const ver = attsMap[this.options.attributeNamePrefix + \"version\"];\n this.entityDecoder.setXmlVersion(Number(ver) || 1.0);\n docTypeReader.setXmlVersion(Number(ver) || 1.0);\n }\n if ((options.ignoreDeclaration && tagData.tagName === \"?xml\") || options.ignorePiTags) {\n //do nothing\n } else {\n\n const childNode = new xmlNode(tagData.tagName);\n childNode.add(options.textNodeName, \"\");\n\n if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent && options.ignoreAttributes !== true) {\n childNode[\":@\"] = attsMap\n }\n this.addChild(currentNode, childNode, this.readonlyMatcher, i);\n\n if (options.captureMetaData) {\n // closeIndex points at '?' of the closing '?>'\n currentNode.addEndIndex(tagData.closeIndex + 2);\n }\n }\n\n\n i = tagData.closeIndex + 1;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 45\n && xmlData.charCodeAt(i + 3) === 45) { //'!--'\n const endIndex = findClosingIndex(xmlData, \"-->\", i + 4, \"Comment is not closed.\")\n if (options.commentPropName) {\n const comment = xmlData.substring(i + 4, endIndex - 2);\n\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);\n\n currentNode.add(options.commentPropName, [{ [options.textNodeName]: comment }]);\n }\n i = endIndex;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 68) { //'!D'\n if (this.doctypefound) throw new Error(\"Multiple DOCTYPE declarations found.\");\n this.doctypefound = true;\n const result = docTypeReader.readDocType(xmlData, i);\n this.entityDecoder.addInputEntities(result.entities);\n i = result.i;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 91) { // '!['\n const closeIndex = findClosingIndex(xmlData, \"]]>\", i, \"CDATA is not closed.\") - 2;\n const tagExp = xmlData.substring(i + 9, closeIndex);\n\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);\n\n let val = this.parseTextData(tagExp, currentNode.tagname, this.readonlyMatcher, true, false, true, true);\n if (val == undefined) val = \"\";\n\n //cdata should be set even if it is 0 length string\n if (options.cdataPropName) {\n currentNode.add(options.cdataPropName, [{ [options.textNodeName]: tagExp }]);\n } else {\n currentNode.add(options.textNodeName, val);\n }\n\n i = closeIndex + 2;\n } else {//Opening tag\n let result = readTagExp(xmlData, i, options.removeNSPrefix);\n\n // Safety check: readTagExp can return undefined\n if (!result) {\n // Log context for debugging\n const context = xmlData.substring(Math.max(0, i - 50), Math.min(xmlLen, i + 50));\n throw new Error(`readTagExp returned undefined at position ${i}. Context: \"${context}\"`);\n }\n\n let tagName = result.tagName;\n const rawTagName = result.rawTagName;\n let tagExp = result.tagExp;\n let attrExpPresent = result.attrExpPresent;\n let closeIndex = result.closeIndex;\n\n ({ tagName, tagExp } = transformTagName(options.transformTagName, tagName, tagExp, options));\n\n if (options.strictReservedNames &&\n (tagName === options.commentPropName\n || tagName === options.cdataPropName\n || tagName === options.textNodeName\n || tagName === options.attributesGroupName\n )) {\n throw new Error(`Invalid tag name: ${tagName}`);\n }\n\n //save text as child node\n if (currentNode && textData) {\n if (currentNode.tagname !== '!xml') {\n //when nested tag is found\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher, false);\n }\n }\n\n //check if last tag was unpaired tag\n const lastTag = currentNode;\n if (lastTag && options.unpairedTagsSet.has(lastTag.tagname)) {\n currentNode = this.tagsNodeStack.pop();\n this.matcher.pop();\n }\n\n // Clean up self-closing syntax BEFORE processing attributes\n // This is where tagExp gets the trailing / removed\n let isSelfClosing = false;\n if (tagExp.length > 0 && tagExp.lastIndexOf(\"/\") === tagExp.length - 1) {\n isSelfClosing = true;\n if (tagName[tagName.length - 1] === \"/\") {\n tagName = tagName.substr(0, tagName.length - 1);\n tagExp = tagName;\n } else {\n tagExp = tagExp.substr(0, tagExp.length - 1);\n }\n\n // Re-check attrExpPresent after cleaning\n attrExpPresent = (tagName !== tagExp);\n }\n\n // Now process attributes with CLEAN tagExp (no trailing /)\n let prefixedAttrs = null;\n let rawAttrs = {};\n let namespace = undefined;\n\n // Extract namespace from rawTagName\n namespace = extractNamespace(rawTagName);\n\n // Push tag to matcher FIRST (with empty attrs for now) so callbacks see correct path\n if (tagName !== xmlObj.tagname) {\n this.matcher.push(tagName, {}, namespace);\n }\n\n // Now build attributes - callbacks will see correct matcher state\n if (tagName !== tagExp && attrExpPresent) {\n // Build attributes (returns prefixed attributes for the tree)\n // Note: buildAttributesMap now internally updates the matcher with raw attributes\n prefixedAttrs = this.buildAttributesMap(tagExp, this.matcher, tagName);\n\n if (prefixedAttrs) {\n // Extract raw attributes (without prefix) for our use\n //TODO: seems a performance overhead\n rawAttrs = extractRawAttributes(prefixedAttrs, options);\n }\n }\n\n // Now check if this is a stop node (after attributes are set)\n if (tagName !== xmlObj.tagname) {\n this.isCurrentNodeStopNode = this.isItStopNode();\n }\n\n const startIndex = i;\n if (this.isCurrentNodeStopNode) {\n let tagContent = \"\";\n\n // For self-closing tags, content is empty\n if (isSelfClosing) {\n i = result.closeIndex;\n }\n //unpaired tag\n else if (options.unpairedTagsSet.has(tagName)) {\n i = result.closeIndex;\n }\n //normal tag\n else {\n //read until closing tag is found\n const result = this.readStopNodeData(xmlData, rawTagName, closeIndex + 1);\n if (!result) throw new Error(`Unexpected end of ${rawTagName}`);\n i = result.i;\n tagContent = result.tagContent;\n }\n\n const childNode = new xmlNode(tagName);\n\n if (prefixedAttrs) {\n childNode[\":@\"] = prefixedAttrs;\n }\n\n // For stop nodes, store raw content as-is without any processing\n childNode.add(options.textNodeName, tagContent);\n\n this.matcher.pop(); // Pop the stop node tag\n this.isCurrentNodeStopNode = false; // Reset flag\n\n this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);\n\n if (options.captureMetaData) {\n currentNode.addEndIndex(i + 1);\n }\n } else {\n //selfClosing tag\n if (isSelfClosing) {\n ({ tagName, tagExp } = transformTagName(options.transformTagName, tagName, tagExp, options));\n\n const childNode = new xmlNode(tagName);\n if (prefixedAttrs) {\n childNode[\":@\"] = prefixedAttrs;\n }\n this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);\n\n if (options.captureMetaData) {\n currentNode.addEndIndex(closeIndex + 1);\n }\n this.matcher.pop(); // Pop self-closing tag\n this.isCurrentNodeStopNode = false; // Reset flag\n }\n else if (options.unpairedTagsSet.has(tagName)) {//unpaired tag\n const childNode = new xmlNode(tagName);\n if (prefixedAttrs) {\n childNode[\":@\"] = prefixedAttrs;\n }\n this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);\n\n if (options.captureMetaData) {\n currentNode.addEndIndex(result.closeIndex + 1);\n }\n this.matcher.pop(); // Pop unpaired tag\n this.isCurrentNodeStopNode = false; // Reset flag\n i = result.closeIndex;\n // Continue to next iteration without changing currentNode\n continue;\n }\n //opening tag\n else {\n const childNode = new xmlNode(tagName);\n if (this.tagsNodeStack.length > options.maxNestedTags) {\n throw new Error(\"Maximum nested tags exceeded\");\n }\n this.tagsNodeStack.push(currentNode);\n\n if (prefixedAttrs) {\n childNode[\":@\"] = prefixedAttrs;\n }\n this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);\n currentNode = childNode;\n }\n textData = \"\";\n i = closeIndex;\n }\n }\n } else {\n textData += xmlData[i];\n }\n }\n return xmlObj.child;\n}\n\nfunction addChild(currentNode, childNode, matcher, startIndex) {\n // unset startIndex if not requested\n if (!this.options.captureMetaData) startIndex = undefined;\n\n // Pass jPath string or matcher based on options.jPath setting\n const jPathOrMatcher = this.options.jPath ? matcher.toString() : matcher;\n const result = this.options.updateTag(childNode.tagname, jPathOrMatcher, childNode[\":@\"])\n if (result === false) {\n //do nothing\n } else if (typeof result === \"string\") {\n childNode.tagname = result\n currentNode.addChild(childNode, startIndex);\n } else {\n currentNode.addChild(childNode, startIndex);\n }\n}\n\n/**\n * @param {object} val - Entity object with regex and val properties\n * @param {string} tagName - Tag name\n * @param {string|Matcher} jPath - jPath string or Matcher instance based on options.jPath\n */\nfunction replaceEntitiesValue(val, tagName, jPath) {\n const entityConfig = this.options.processEntities;\n\n if (!entityConfig || !entityConfig.enabled) {\n return val;\n }\n\n // Check if tag is allowed to contain entities\n if (entityConfig.allowedTags) {\n const jPathOrMatcher = this.options.jPath ? jPath.toString() : jPath;\n const allowed = Array.isArray(entityConfig.allowedTags)\n ? entityConfig.allowedTags.includes(tagName)\n : entityConfig.allowedTags(tagName, jPathOrMatcher);\n\n if (!allowed) {\n return val;\n }\n }\n\n // Apply custom tag filter if provided\n if (entityConfig.tagFilter) {\n const jPathOrMatcher = this.options.jPath ? jPath.toString() : jPath;\n if (!entityConfig.tagFilter(tagName, jPathOrMatcher)) {\n return val; // Skip based on custom filter\n }\n }\n\n return this.entityDecoder.decode(val);\n}\n\n\nfunction saveTextToParentTag(textData, parentNode, matcher, isLeafNode) {\n if (textData) { //store previously collected data as textNode\n if (isLeafNode === undefined) isLeafNode = parentNode.child.length === 0\n\n textData = this.parseTextData(textData,\n parentNode.tagname,\n matcher,\n false,\n parentNode[\":@\"] ? Object.keys(parentNode[\":@\"]).length !== 0 : false,\n isLeafNode);\n\n if (textData !== undefined && textData !== \"\")\n parentNode.add(this.options.textNodeName, textData);\n textData = \"\";\n }\n return textData;\n}\n\n/**\n * @param {Array<Expression>} stopNodeExpressions - Array of compiled Expression objects\n * @param {Matcher} matcher - Current path matcher\n */\nfunction isItStopNode() {\n if (this.stopNodeExpressionsSet.size === 0) return false;\n\n return this.matcher.matchesAny(this.stopNodeExpressionsSet);\n}\n\n/**\n * Returns the tag Expression and where it is ending handling single-double quotes situation\n * @param {string} xmlData \n * @param {number} i starting index\n * @returns \n */\nfunction tagExpWithClosingIndex(xmlData, i, closingChar = \">\") {\n //TODO: ignore boolean attributes in tag expression\n //TODO: if ignore attributes, dont read full attribute expression but the end. But read for xml declaration\n let attrBoundary = 0;\n const len = xmlData.length;\n const closeCode0 = closingChar.charCodeAt(0);\n const closeCode1 = closingChar.length > 1 ? closingChar.charCodeAt(1) : -1;\n\n let result = '';\n let segmentStart = i;\n\n for (let index = i; index < len; index++) {\n const code = xmlData.charCodeAt(index);\n\n if (attrBoundary) {\n if (code === attrBoundary) attrBoundary = 0;\n } else if (code === 34 || code === 39) { // \" or '\n attrBoundary = code;\n } else if (code === closeCode0) {\n if (closeCode1 !== -1) {\n if (xmlData.charCodeAt(index + 1) === closeCode1) {\n result += xmlData.substring(segmentStart, index);\n return { data: result, index };\n }\n } else {\n result += xmlData.substring(segmentStart, index);\n return { data: result, index };\n }\n } else if (code === 9 && !attrBoundary) { // \\t - only replace with space outside attribute values\n // Flush accumulated segment, add space, start new segment\n result += xmlData.substring(segmentStart, index) + ' ';\n segmentStart = index + 1;\n }\n }\n}\n\nfunction findClosingIndex(xmlData, str, i, errMsg) {\n const closingIndex = xmlData.indexOf(str, i);\n if (closingIndex === -1) {\n throw new Error(errMsg)\n } else {\n return closingIndex + str.length - 1;\n }\n}\n\nfunction findClosingChar(xmlData, char, i, errMsg) {\n const closingIndex = xmlData.indexOf(char, i);\n if (closingIndex === -1) throw new Error(errMsg);\n return closingIndex; // no offset needed\n}\n\nfunction readTagExp(xmlData, i, removeNSPrefix, closingChar = \">\") {\n const result = tagExpWithClosingIndex(xmlData, i + 1, closingChar);\n if (!result) return;\n let tagExp = result.data;\n const closeIndex = result.index;\n const separatorIndex = tagExp.search(/\\s/);\n let tagName = tagExp;\n let attrExpPresent = true;\n if (separatorIndex !== -1) {//separate tag name and attributes expression\n tagName = tagExp.substring(0, separatorIndex);\n tagExp = tagExp.substring(separatorIndex + 1).trimStart();\n }\n\n const rawTagName = tagName;\n if (removeNSPrefix) {\n const colonIndex = tagName.indexOf(\":\");\n if (colonIndex !== -1) {\n tagName = tagName.substr(colonIndex + 1);\n attrExpPresent = tagName !== result.data.substr(colonIndex + 1);\n }\n }\n\n return {\n tagName: tagName,\n tagExp: tagExp,\n closeIndex: closeIndex,\n attrExpPresent: attrExpPresent,\n rawTagName: rawTagName,\n }\n}\n/**\n * find paired tag for a stop node\n * @param {string} xmlData \n * @param {string} tagName \n * @param {number} i \n */\nfunction readStopNodeData(xmlData, tagName, i) {\n const startIndex = i;\n // Starting at 1 since we already have an open tag\n let openTagCount = 1;\n\n const xmllen = xmlData.length;\n for (; i < xmllen; i++) {\n if (xmlData[i] === \"<\") {\n const c1 = xmlData.charCodeAt(i + 1);\n if (c1 === 47) {//close tag '/'\n const closeIndex = findClosingChar(xmlData, \">\", i, `${tagName} is not closed`);\n let closeTagName = xmlData.substring(i + 2, closeIndex).trim();\n if (closeTagName === tagName) {\n openTagCount--;\n if (openTagCount === 0) {\n return {\n tagContent: xmlData.substring(startIndex, i),\n i: closeIndex\n }\n }\n }\n i = closeIndex;\n } else if (c1 === 63) { //?\n const closeIndex = findClosingIndex(xmlData, \"?>\", i + 1, \"StopNode is not closed.\")\n i = closeIndex;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 45\n && xmlData.charCodeAt(i + 3) === 45) { // '!--'\n const closeIndex = findClosingIndex(xmlData, \"-->\", i + 3, \"StopNode is not closed.\")\n i = closeIndex;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 91) { // '!['\n const closeIndex = findClosingIndex(xmlData, \"]]>\", i, \"StopNode is not closed.\") - 2;\n i = closeIndex;\n } else {\n const tagData = readTagExp(xmlData, i, false)\n\n if (tagData) {\n const openTagName = tagData && tagData.tagName;\n if (openTagName === tagName && tagData.tagExp[tagData.tagExp.length - 1] !== \"/\") {\n openTagCount++;\n }\n i = tagData.closeIndex;\n }\n }\n }\n }//end for loop\n}\n\nfunction parseValue(val, shouldParse, options) {\n if (shouldParse && typeof val === 'string') {\n //console.log(options)\n const newval = val.trim();\n if (newval === 'true') return true;\n else if (newval === 'false') return false;\n else return toNumber(val, options);\n } else {\n if (isExist(val)) {\n return val;\n } else {\n return '';\n }\n }\n}\n\nfunction fromCodePoint(str, base, prefix) {\n const codePoint = Number.parseInt(str, base);\n\n if (codePoint >= 0 && codePoint <= 0x10FFFF) {\n return String.fromCodePoint(codePoint);\n } else {\n return prefix + str + \";\";\n }\n}\n\nfunction transformTagName(fn, tagName, tagExp, options) {\n if (fn) {\n const newTagName = fn(tagName);\n if (tagExp === tagName) {\n tagExp = newTagName\n }\n tagName = newTagName;\n }\n tagName = sanitizeName(tagName, options);\n return { tagName, tagExp };\n}\n\n\n\nfunction sanitizeName(name, options) {\n if (criticalProperties.includes(name)) {\n throw new Error(`[SECURITY] Invalid name: \"${name}\" is a reserved JavaScript keyword that could cause prototype pollution`);\n } else if (DANGEROUS_PROPERTY_NAMES.includes(name)) {\n return options.onDangerousProperty(name);\n }\n return name;\n}", "'use strict';\n\nimport XmlNode from './xmlNode.js';\nimport { Matcher } from 'path-expression-matcher';\n\nconst METADATA_SYMBOL = XmlNode.getMetaDataSymbol();\n\n/**\n * Helper function to strip attribute prefix from attribute map\n * @param {object} attrs - Attributes with prefix (e.g., {\"@_class\": \"code\"})\n * @param {string} prefix - Attribute prefix to remove (e.g., \"@_\")\n * @returns {object} Attributes without prefix (e.g., {\"class\": \"code\"})\n */\nfunction stripAttributePrefix(attrs, prefix) {\n if (!attrs || typeof attrs !== 'object') return {};\n if (!prefix) return attrs;\n\n const rawAttrs = {};\n for (const key in attrs) {\n if (key.startsWith(prefix)) {\n const rawName = key.substring(prefix.length);\n rawAttrs[rawName] = attrs[key];\n } else {\n // Attribute without prefix (shouldn't normally happen, but be safe)\n rawAttrs[key] = attrs[key];\n }\n }\n return rawAttrs;\n}\n\n/**\n * \n * @param {array} node \n * @param {any} options \n * @param {Matcher} matcher - Path matcher instance\n * @returns \n */\nexport default function prettify(node, options, matcher, readonlyMatcher) {\n return compress(node, options, matcher, readonlyMatcher);\n}\n\n/**\n * @param {array} arr \n * @param {object} options \n * @param {Matcher} matcher - Path matcher instance\n * @returns object\n */\nfunction compress(arr, options, matcher, readonlyMatcher) {\n let text;\n const compressedObj = {}; //This is intended to be a plain object\n for (let i = 0; i < arr.length; i++) {\n const tagObj = arr[i];\n const property = propName(tagObj);\n\n // Push current property to matcher WITH RAW ATTRIBUTES (no prefix)\n if (property !== undefined && property !== options.textNodeName) {\n const rawAttrs = stripAttributePrefix(\n tagObj[\":@\"] || {},\n options.attributeNamePrefix\n );\n matcher.push(property, rawAttrs);\n }\n\n if (property === options.textNodeName) {\n if (text === undefined) text = tagObj[property];\n else text += \"\" + tagObj[property];\n } else if (property === undefined) {\n continue;\n } else if (tagObj[property]) {\n\n let val = compress(tagObj[property], options, matcher, readonlyMatcher);\n const isLeaf = isLeafTag(val, options);\n\n if (Object.keys(val).length === 0 && options.alwaysCreateTextNode) {\n val[options.textNodeName] = \"\";\n }\n\n if (tagObj[\":@\"]) {\n assignAttributes(val, tagObj[\":@\"], readonlyMatcher, options);\n } else if (Object.keys(val).length === 1 && val[options.textNodeName] !== undefined && !options.alwaysCreateTextNode) {\n val = val[options.textNodeName];\n } else if (Object.keys(val).length === 0) {\n if (options.alwaysCreateTextNode) val[options.textNodeName] = \"\";\n else val = \"\";\n }\n\n if (tagObj[METADATA_SYMBOL] !== undefined && typeof val === \"object\" && val !== null) {\n val[METADATA_SYMBOL] = tagObj[METADATA_SYMBOL]; // copy over metadata\n }\n\n\n if (compressedObj[property] !== undefined && Object.prototype.hasOwnProperty.call(compressedObj, property)) {\n if (!Array.isArray(compressedObj[property])) {\n compressedObj[property] = [compressedObj[property]];\n }\n compressedObj[property].push(val);\n } else {\n //TODO: if a node is not an array, then check if it should be an array\n //also determine if it is a leaf node\n\n // Pass jPath string or readonlyMatcher based on options.jPath setting\n const jPathOrMatcher = options.jPath ? readonlyMatcher.toString() : readonlyMatcher;\n if (options.isArray(property, jPathOrMatcher, isLeaf)) {\n compressedObj[property] = [val];\n } else {\n compressedObj[property] = val;\n }\n }\n\n // Pop property from matcher after processing\n if (property !== undefined && property !== options.textNodeName) {\n matcher.pop();\n }\n }\n\n }\n // if(text && text.length > 0) compressedObj[options.textNodeName] = text;\n if (typeof text === \"string\") {\n if (text.length > 0) compressedObj[options.textNodeName] = text;\n } else if (text !== undefined) compressedObj[options.textNodeName] = text;\n\n\n return compressedObj;\n}\n\nfunction propName(obj) {\n const keys = Object.keys(obj);\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n if (key !== \":@\") return key;\n }\n}\n\nfunction assignAttributes(obj, attrMap, readonlyMatcher, options) {\n if (attrMap) {\n const keys = Object.keys(attrMap);\n const len = keys.length; //don't make it inline\n for (let i = 0; i < len; i++) {\n const atrrName = keys[i]; // This is the PREFIXED name (e.g., \"@_class\")\n\n // Strip prefix for matcher path (for isArray callback)\n const rawAttrName = atrrName.startsWith(options.attributeNamePrefix)\n ? atrrName.substring(options.attributeNamePrefix.length)\n : atrrName;\n\n // For attributes, we need to create a temporary path\n // Pass jPath string or matcher based on options.jPath setting\n const jPathOrMatcher = options.jPath\n ? readonlyMatcher.toString() + \".\" + rawAttrName\n : readonlyMatcher;\n\n if (options.isArray(atrrName, jPathOrMatcher, true, true)) {\n obj[atrrName] = [attrMap[atrrName]];\n } else {\n obj[atrrName] = attrMap[atrrName];\n }\n }\n }\n}\n\nfunction isLeafTag(obj, options) {\n const { textNodeName } = options;\n const propCount = Object.keys(obj).length;\n\n if (propCount === 0) {\n return true;\n }\n\n if (\n propCount === 1 &&\n (obj[textNodeName] || typeof obj[textNodeName] === \"boolean\" || obj[textNodeName] === 0)\n ) {\n return true;\n }\n\n return false;\n}", "/* global Uint8Array */\nimport { buildOptions } from './OptionsBuilder.js';\nimport OrderedObjParser from './OrderedObjParser.js';\nimport prettify from './node2json.js';\nimport { validate } from \"../validator.js\";\nimport XmlNode from './xmlNode.js';\n\nexport default class XMLParser {\n\n constructor(options) {\n this.externalEntities = {};\n this.options = buildOptions(options);\n\n }\n /**\n * Parse XML dats to JS object \n * @param {string|Uint8Array} xmlData \n * @param {boolean|Object} validationOption \n */\n parse(xmlData, validationOption) {\n if (typeof xmlData !== \"string\" && xmlData.toString) {\n if (xmlData instanceof Uint8Array &&\n !(typeof Buffer !== \"undefined\" && Buffer.isBuffer(xmlData))) {\n xmlData = new TextDecoder(\"utf-8\", { ignoreBOM: true }).decode(xmlData);\n } else {\n xmlData = xmlData.toString();\n }\n } else if (typeof xmlData !== \"string\") {\n throw new Error(\"XML data is accepted in String or Bytes[] form.\")\n }\n\n if (validationOption) {\n if (validationOption === true) validationOption = {}; //validate with default options\n\n const result = validate(xmlData, validationOption);\n if (result !== true) {\n throw Error(`${result.err.msg}:${result.err.line}:${result.err.col}`)\n }\n }\n const orderedObjParser = new OrderedObjParser(this.options, this.externalEntities);\n // orderedObjParser.entityDecoder.setExternalEntities(this.externalEntities);\n const orderedResult = orderedObjParser.parseXml(xmlData);\n if (this.options.preserveOrder || orderedResult === undefined) return orderedResult;\n else return prettify(orderedResult, this.options, orderedObjParser.matcher, orderedObjParser.readonlyMatcher);\n }\n\n /**\n * Add Entity which is not by default supported by this library\n * @param {string} key \n * @param {string} value \n */\n addEntity(key, value) {\n if (value.indexOf(\"&\") !== -1) {\n throw new Error(\"Entity value can't have '&'\")\n } else if (key.indexOf(\"&\") !== -1 || key.indexOf(\";\") !== -1) {\n throw new Error(\"An entity must be set without '&' and ';'. Eg. use '#xD' for '&#xD;'\")\n } else if (value === \"&\") {\n throw new Error(\"An entity with value '&' is not permitted\");\n } else {\n this.externalEntities[key] = value;\n }\n }\n\n /**\n * Returns a Symbol that can be used to access the metadata\n * property on a node.\n * \n * If Symbol is not available in the environment, an ordinary property is used\n * and the name of the property is here returned.\n * \n * The XMLMetaData property is only present when `captureMetaData`\n * is true in the options.\n */\n static getMetaDataSymbol() {\n return XmlNode.getMetaDataSymbol();\n }\n}", "'use strict';\n\nimport { validate } from './validator.js';\nimport XMLParser from './xmlparser/XMLParser.js';\nimport XMLBuilder from './xmlbuilder/json2xml.js';\n\nconst XMLValidator = {\n validate: validate\n}\nexport {\n XMLParser,\n XMLValidator,\n XMLBuilder\n};", "import { XMLParser, XMLValidator } from \"fast-xml-parser\"\n\n/** AWS XML uses string scalars; callers convert numbers according to the service model. */\nexport const awsParseXml = (source: string): Record<string, unknown> => {\n if (/<!DOCTYPE|<!ENTITY/i.test(source) || XMLValidator.validate(source) !== true)\n throw new TypeError(\"Malformed XML\")\n return new XMLParser({\n ignoreAttributes: true,\n parseTagValue: false,\n trimValues: false,\n processEntities: true,\n }).parse(source) as Record<string, unknown>\n}\n\nexport const awsXmlEscape = (value: unknown): string =>\n String(value)\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\")\n\nexport const awsXml = (value: unknown, listTag = \"member\"): string => {\n if (value === null || value === undefined) return \"\"\n if (Array.isArray(value))\n return value.map((item) => `<${listTag}>${awsXml(item, listTag)}</${listTag}>`).join(\"\")\n if (typeof value !== \"object\") return awsXmlEscape(value)\n return Object.entries(value)\n .filter(([, item]) => item !== undefined)\n .map(([key, item]) => `<${key}>${awsXml(item, listTag)}</${key}>`)\n .join(\"\")\n}\n", "import type { SqliteClient, SqliteStatement } from \"@crvouga/mockingbird-sqlite\"\n\n/** Every stored record carries a monotonically increasing sequence for stable ordering. */\nexport type Stored<T> = { seq: number; value: T }\n\nexport type ListRecordsOptions<T> = {\n /** Keep only records passing the predicate. */\n where?: (value: T, seq: number) => boolean\n /** Sort order; default newest first. */\n order?: \"newest\" | \"oldest\"\n}\n\ntype RecordRow = { id: string; seq: number; value: string }\n\n/**\n * A SQLite-backed table of JSON records addressed by id. Ordering is by insertion\n * sequence, never by id lexicographic order, so list semantics stay stable.\n */\nexport class Collection<T> {\n private readonly statements = new Map<string, SqliteStatement>()\n\n private prepare(sql: string): SqliteStatement {\n let statement = this.statements.get(sql)\n if (!statement) {\n statement = this.sqlite.prepare(sql)\n this.statements.set(sql, statement)\n }\n return statement\n }\n\n constructor(\n private readonly sqlite: SqliteClient,\n /** Storage namespace. Admin introspection uses this to ignore another namespace's tables. */\n readonly namespace: string,\n /** Table name inside the namespace. Stable across resets of the rows themselves. */\n readonly collectionName: string,\n ) {}\n\n private bumpCollectionSeq(): number {\n const row = this.prepare(\n \"SELECT value FROM mockingbird_sequences WHERE namespace = ? AND name = ? AND kind = 'collection'\",\n ).get<{ value: number }>(this.namespace, this.collectionName)\n const next = (row?.value ?? 0) + 1\n this.prepare(\n `INSERT INTO mockingbird_sequences (namespace, name, kind, value) VALUES (?, ?, 'collection', ?)\n ON CONFLICT(namespace, name, kind) DO UPDATE SET value = excluded.value`,\n ).run(this.namespace, this.collectionName, next)\n return next\n }\n\n nextSequence(): number {\n return this.sqlite.transaction(() => this.bumpCollectionSeq())\n }\n\n get(id: string): T | undefined {\n const row = this.prepare(\n \"SELECT value FROM mockingbird_records WHERE namespace = ? AND collection = ? AND id = ?\",\n ).get<{ value: string }>(this.namespace, this.collectionName, id)\n if (!row) return undefined\n return (JSON.parse(row.value) as Stored<T>).value\n }\n\n has(id: string): boolean {\n const row = this.prepare(\n \"SELECT 1 AS ok FROM mockingbird_records WHERE namespace = ? AND collection = ? AND id = ?\",\n ).get<{ ok: number }>(this.namespace, this.collectionName, id)\n return row !== undefined\n }\n\n /** Insert a new record, assigning it the next sequence number. */\n insert(id: string, value: T): Stored<T> {\n return this.sqlite.transaction(() => {\n const seq = this.bumpCollectionSeq()\n const stored = { seq, value }\n this.prepare(\n `INSERT INTO mockingbird_records (namespace, collection, id, seq, value)\n VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(namespace, collection, id) DO UPDATE SET seq = excluded.seq, value = excluded.value`,\n ).run(this.namespace, this.collectionName, id, seq, JSON.stringify(stored))\n return stored\n })\n }\n\n /** Replace an existing record's value, keeping its position. */\n update(id: string, value: T): Stored<T> | undefined {\n return this.sqlite.transaction(() => {\n const row = this.prepare(\n \"SELECT seq, value FROM mockingbird_records WHERE namespace = ? AND collection = ? AND id = ?\",\n ).get<{ seq: number; value: string }>(this.namespace, this.collectionName, id)\n if (!row) return undefined\n const stored = { seq: row.seq, value }\n this.prepare(\n \"UPDATE mockingbird_records SET value = ? WHERE namespace = ? AND collection = ? AND id = ?\",\n ).run(JSON.stringify(stored), this.namespace, this.collectionName, id)\n return stored\n })\n }\n\n delete(id: string): boolean {\n const result = this.prepare(\n \"DELETE FROM mockingbird_records WHERE namespace = ? AND collection = ? AND id = ?\",\n ).run(this.namespace, this.collectionName, id)\n return result.changes > 0\n }\n\n /** How many records the collection holds, without reading them. */\n count(): number {\n const row = this.prepare(\n \"SELECT COUNT(*) AS n FROM mockingbird_records WHERE namespace = ? AND collection = ?\",\n ).get<{ n: number }>(this.namespace, this.collectionName)\n return Number(row?.n ?? 0)\n }\n\n list(options: ListRecordsOptions<T> = {}): Array<Stored<T> & { id: string }> {\n const rows = this.prepare(\n \"SELECT id, seq, value FROM mockingbird_records WHERE namespace = ? AND collection = ?\",\n ).all<RecordRow>(this.namespace, this.collectionName)\n const out: Array<Stored<T> & { id: string }> = []\n for (const row of rows) {\n const stored = JSON.parse(row.value) as Stored<T>\n if (options.where && !options.where(stored.value, stored.seq)) continue\n out.push({ id: row.id, seq: stored.seq, value: stored.value })\n }\n out.sort((a, b) => (options.order === \"oldest\" ? a.seq - b.seq : b.seq - a.seq))\n return out\n }\n}\n", "import type { SqliteClient } from \"@crvouga/mockingbird-sqlite\"\n\nconst ALPHABET = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\"\n\n/** FNV-1a over a string, mixed once more so consecutive counters look unrelated. */\nconst mix = (input: string): number => {\n let hash = 0x811c9dc5\n for (let i = 0; i < input.length; i++) {\n hash ^= input.charCodeAt(i)\n hash = Math.imul(hash, 0x01000193) >>> 0\n }\n hash ^= hash >>> 16\n hash = Math.imul(hash, 0x85ebca6b) >>> 0\n hash ^= hash >>> 13\n return hash >>> 0\n}\n\n/** Deterministic, opaque-looking alphanumeric token of `length` characters derived from `input`. */\nexport const opaqueToken = (input: string, length: number): string => {\n let out = \"\"\n let round = 0\n while (out.length < length) {\n let hash = mix(`${input}:${round++}`)\n for (let i = 0; i < 5 && out.length < length; i++) {\n out += ALPHABET.charAt(hash % ALPHABET.length)\n hash = Math.floor(hash / ALPHABET.length)\n }\n }\n return out\n}\n\n/**\n * What names an id base: a non-negative safe integer (or its decimal string) or `\"boot\"`,\n * which derives the base from the wall clock when the runtime is created.\n */\nexport type IdBase = number | string\n\nconst ID_BASES = new WeakMap<SqliteClient, number>()\n\n/**\n * Resolve an id base. `\"boot\"` is the wall clock in epoch milliseconds, so every boot gets\n * a different base. Anything else must be a non-negative safe integer or a string of digits.\n */\nexport const normalizeIdBase = (\n value: unknown,\n label = \"idBase\",\n wallNow: () => number = Date.now,\n): number => {\n if (value === \"boot\") return wallNow()\n const base =\n typeof value === \"string\" && /^\\d+$/.test(value.trim())\n ? Number(value.trim())\n : typeof value === \"number\"\n ? value\n : Number.NaN\n if (!Number.isSafeInteger(base) || base < 0)\n throw new RangeError(\n `${label} must be a non-negative integer or \"boot\" (got ${JSON.stringify(value)})`,\n )\n return base\n}\n\n/**\n * Give every {@link IdSequence} over `sqlite` this base. `0` is the default and changes\n * nothing; any other base yields a different, unrelated run of ids from the same counters.\n */\nexport const setIdBase = (sqlite: SqliteClient, base: number): void => {\n if (base === 0) ID_BASES.delete(sqlite)\n else ID_BASES.set(sqlite, base)\n}\n\n/** The id base in force over `sqlite` (`0` unless one was set). */\nexport const idBaseOf = (sqlite: SqliteClient): number => ID_BASES.get(sqlite) ?? 0\n\n/**\n * Sequential id source persisted in SQLite. Ids are deterministic for a given\n * sequence history (`cus_` + 14 opaque chars), so reproductions stay stable.\n * A runtime's `idBase` is mixed in, so a different base reissues none of another's ids.\n */\nexport class IdSequence {\n constructor(\n private readonly sqlite: SqliteClient,\n private readonly namespace: string,\n private readonly salt = \"mockingbird\",\n ) {}\n\n next(prefix: string, length = 14): string {\n return this.sqlite.transaction(() => {\n const row = this.sqlite\n .prepare(\n \"SELECT value FROM mockingbird_sequences WHERE namespace = ? AND name = ? AND kind = 'id'\",\n )\n .get<{ value: number }>(this.namespace, prefix)\n const value = (row?.value ?? 0) + 1\n this.sqlite\n .prepare(\n `INSERT INTO mockingbird_sequences (namespace, name, kind, value) VALUES (?, ?, 'id', ?)\n ON CONFLICT(namespace, name, kind) DO UPDATE SET value = excluded.value`,\n )\n .run(this.namespace, prefix, value)\n const base = idBaseOf(this.sqlite)\n const seed = base === 0 ? this.salt : `${this.salt}#${base}`\n return `${prefix}${opaqueToken(`${seed}:${prefix}:${value}`, length)}`\n })\n }\n}\n", "import type { OpenAPIDocument, ReferenceObject } from \"./types.js\"\n\nexport class OpenAPIReferenceError extends Error {\n constructor(readonly ref: string) {\n super(`unresolvable $ref: ${ref}`)\n this.name = \"OpenAPIReferenceError\"\n }\n}\n\nconst unescapePointer = (segment: string) => segment.replace(/~1/g, \"/\").replace(/~0/g, \"~\")\n\n/** True when `value` is a `{ $ref }` object. */\nexport const isReference = (value: unknown): value is ReferenceObject =>\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { $ref?: unknown }).$ref === \"string\"\n\n/** Resolve a local JSON pointer reference (`#/components/schemas/customer`) inside `document`. */\nexport const resolveRef = (document: OpenAPIDocument, ref: string): unknown => {\n if (!ref.startsWith(\"#/\")) throw new OpenAPIReferenceError(ref)\n let cursor: unknown = document\n for (const raw of ref.slice(2).split(\"/\")) {\n const segment = unescapePointer(raw)\n if (typeof cursor !== \"object\" || cursor === null || !(segment in cursor)) {\n throw new OpenAPIReferenceError(ref)\n }\n cursor = (cursor as Record<string, unknown>)[segment]\n }\n if (cursor === undefined) throw new OpenAPIReferenceError(ref)\n return cursor\n}\n\n/**\n * Follow `$ref` chains until a concrete object is reached. Guards against cycles.\n * Sibling keys next to `$ref` are ignored, as in OpenAPI 3.0/3.1 for non-schema objects.\n */\nexport const deref = <T>(document: OpenAPIDocument, value: T | ReferenceObject): T => {\n let current: unknown = value\n const seen = new Set<string>()\n while (isReference(current)) {\n if (seen.has(current.$ref)) throw new OpenAPIReferenceError(`${current.$ref} (cycle)`)\n seen.add(current.$ref)\n current = resolveRef(document, current.$ref)\n }\n return current as T\n}\n\n/** The component name at the end of a `#/components/<kind>/<name>` reference, if any. */\nexport const componentNameOf = (ref: string): string | undefined => {\n const match = /^#\\/components\\/[^/]+\\/(.+)$/.exec(ref)\n return match?.[1] === undefined ? undefined : unescapePointer(match[1])\n}\n", "/**\n * The slice of OpenAPI 3.1 (and JSON Schema 2020-12) Mockingbird understands.\n * Unknown keys (including `x-*` extensions) are preserved on every object.\n */\n\nexport type JsonPrimitive = string | number | boolean | null\nexport type JsonValue = JsonPrimitive | JsonValue[] | { [key: string]: JsonValue }\n\nexport type ReferenceObject = { $ref: string; description?: string; summary?: string }\n\nexport type SchemaType = \"string\" | \"number\" | \"integer\" | \"boolean\" | \"object\" | \"array\" | \"null\"\n\nexport type SchemaObject = {\n $ref?: string\n type?: SchemaType | SchemaType[]\n title?: string\n description?: string\n format?: string\n enum?: JsonValue[]\n const?: JsonValue\n default?: JsonValue\n example?: JsonValue\n examples?: JsonValue[]\n nullable?: boolean\n deprecated?: boolean\n readOnly?: boolean\n writeOnly?: boolean\n minimum?: number\n maximum?: number\n exclusiveMinimum?: number\n exclusiveMaximum?: number\n multipleOf?: number\n minLength?: number\n maxLength?: number\n pattern?: string\n minItems?: number\n maxItems?: number\n uniqueItems?: boolean\n items?: SchemaObject\n prefixItems?: SchemaObject[]\n minProperties?: number\n maxProperties?: number\n required?: string[]\n properties?: Record<string, SchemaObject>\n additionalProperties?: boolean | SchemaObject\n propertyNames?: SchemaObject\n oneOf?: SchemaObject[]\n anyOf?: SchemaObject[]\n allOf?: SchemaObject[]\n not?: SchemaObject\n discriminator?: { propertyName: string; mapping?: Record<string, string> }\n [extension: `x-${string}`]: unknown\n}\n\nexport type ParameterLocation = \"path\" | \"query\" | \"header\" | \"cookie\"\n\nexport type ParameterObject = {\n name: string\n in: ParameterLocation\n description?: string\n required?: boolean\n deprecated?: boolean\n style?: string\n explode?: boolean\n schema?: SchemaObject\n content?: Record<string, MediaTypeObject>\n example?: JsonValue\n [extension: `x-${string}`]: unknown\n}\n\nexport type MediaTypeObject = {\n schema?: SchemaObject\n example?: JsonValue\n examples?: Record<string, unknown>\n encoding?: Record<string, unknown>\n [extension: `x-${string}`]: unknown\n}\n\nexport type RequestBodyObject = {\n description?: string\n required?: boolean\n content: Record<string, MediaTypeObject>\n [extension: `x-${string}`]: unknown\n}\n\nexport type HeaderObject = {\n description?: string\n required?: boolean\n schema?: SchemaObject\n [extension: `x-${string}`]: unknown\n}\n\nexport type ResponseObject = {\n description: string\n headers?: Record<string, HeaderObject | ReferenceObject>\n content?: Record<string, MediaTypeObject>\n [extension: `x-${string}`]: unknown\n}\n\nexport type ResponsesObject = Record<string, ResponseObject | ReferenceObject>\n\nexport type SecurityRequirementObject = Record<string, string[]>\n\nexport type OperationObject = {\n operationId?: string\n summary?: string\n description?: string\n tags?: string[]\n deprecated?: boolean\n parameters?: Array<ParameterObject | ReferenceObject>\n requestBody?: RequestBodyObject | ReferenceObject\n responses: ResponsesObject\n security?: SecurityRequirementObject[]\n [extension: `x-${string}`]: unknown\n}\n\nexport const HTTP_METHODS = [\n \"get\",\n \"put\",\n \"post\",\n \"delete\",\n \"options\",\n \"head\",\n \"patch\",\n \"trace\",\n] as const\nexport type HttpMethod = (typeof HTTP_METHODS)[number]\n\nexport type PathItemObject = {\n summary?: string\n description?: string\n parameters?: Array<ParameterObject | ReferenceObject>\n [extension: `x-${string}`]: unknown\n} & Partial<Record<HttpMethod, OperationObject>>\n\nexport type SecuritySchemeObject = {\n type: \"apiKey\" | \"http\" | \"oauth2\" | \"openIdConnect\" | \"mutualTLS\"\n description?: string\n name?: string\n in?: ParameterLocation\n scheme?: string\n bearerFormat?: string\n flows?: Record<string, unknown>\n openIdConnectUrl?: string\n [extension: `x-${string}`]: unknown\n}\n\nexport type ComponentsObject = {\n schemas?: Record<string, SchemaObject>\n responses?: Record<string, ResponseObject>\n parameters?: Record<string, ParameterObject>\n requestBodies?: Record<string, RequestBodyObject>\n headers?: Record<string, HeaderObject>\n securitySchemes?: Record<string, SecuritySchemeObject>\n [extension: `x-${string}`]: unknown\n}\n\nexport type ServerObject = {\n url: string\n description?: string\n variables?: Record<string, unknown>\n [extension: `x-${string}`]: unknown\n}\n\nexport type InfoObject = {\n title: string\n version: string\n description?: string\n [extension: `x-${string}`]: unknown\n}\n\nexport type OpenAPIDocument = {\n openapi: string\n info: InfoObject\n servers?: ServerObject[]\n paths: Record<string, PathItemObject>\n components?: ComponentsObject\n security?: SecurityRequirementObject[]\n tags?: Array<{ name: string; description?: string }>\n [extension: `x-${string}`]: unknown\n}\n\n/** One concrete HTTP operation discovered in a document. */\nexport type Operation = {\n operationId: string\n method: HttpMethod\n /** OpenAPI path template, e.g. `/v1/customers/{customer}`. */\n path: string\n operation: OperationObject\n /** Path-level parameters merged with operation-level ones (operation wins), `$ref`s resolved. */\n parameters: ParameterObject[]\n requestBody: RequestBodyObject | undefined\n responses: Record<string, ResponseObject>\n}\n", "import { deref, isReference, resolveRef } from \"./refs.js\"\nimport {\n HTTP_METHODS,\n type HttpMethod,\n type OpenAPIDocument,\n type Operation,\n type ParameterObject,\n type PathItemObject,\n type RequestBodyObject,\n type ResponseObject,\n} from \"./types.js\"\n\nexport class OpenAPIDocumentError extends Error {\n constructor(readonly issues: string[]) {\n super(`invalid OpenAPI document:\\n${issues.map((issue) => ` - ${issue}`).join(\"\\n\")}`)\n this.name = \"OpenAPIDocumentError\"\n }\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n\n/**\n * Accept an already-parsed JSON/YAML value and return it typed as an {@link OpenAPIDocument}.\n * Performs the structural checks Mockingbird relies on (see {@link validateOpenAPIDocument}) and\n * throws {@link OpenAPIDocumentError} listing every problem.\n */\nexport const parseOpenAPIDocument = (value: unknown): OpenAPIDocument => {\n const issues: string[] = []\n if (!isRecord(value)) throw new OpenAPIDocumentError([\"document must be an object\"])\n if (typeof value.openapi !== \"string\" || !/^3\\.[01]\\./.test(value.openapi)) {\n issues.push(\n `openapi must be a 3.0.x or 3.1.x version string, got ${JSON.stringify(value.openapi)}`,\n )\n }\n if (\n !isRecord(value.info) ||\n typeof value.info.title !== \"string\" ||\n typeof value.info.version !== \"string\"\n ) {\n issues.push(\"info.title and info.version are required strings\")\n }\n if (!isRecord(value.paths)) issues.push(\"paths must be an object\")\n if (issues.length > 0) throw new OpenAPIDocumentError(issues)\n const document = value as unknown as OpenAPIDocument\n const problems = validateOpenAPIDocument(document)\n if (problems.length > 0) throw new OpenAPIDocumentError(problems)\n return document\n}\n\nconst walkRefs = (\n document: OpenAPIDocument,\n node: unknown,\n at: string,\n issues: string[],\n seen: Set<unknown>,\n) => {\n if (typeof node !== \"object\" || node === null || seen.has(node)) return\n seen.add(node)\n if (isReference(node)) {\n try {\n resolveRef(document, node.$ref)\n } catch {\n issues.push(`${at}: unresolvable $ref ${node.$ref}`)\n }\n }\n for (const [key, child] of Object.entries(node))\n walkRefs(document, child, `${at}/${key}`, issues, seen)\n}\n\nconst templateParams = (path: string) =>\n [...path.matchAll(/\\{([^}]+)\\}/g)].map((m) => m[1] as string)\n\n/**\n * Mockingbird's document rules:\n * - every operation has a unique `operationId`\n * - every `$ref` resolves\n * - every `{param}` in a path template has a matching required path parameter\n * - every path parameter appears in the template\n */\nexport const validateOpenAPIDocument = (document: OpenAPIDocument): string[] => {\n const issues: string[] = []\n walkRefs(document, document, \"#\", issues, new Set())\n if (issues.length > 0) return issues\n const seenIds = new Map<string, string>()\n for (const [path, item] of Object.entries(document.paths)) {\n if (!isRecord(item)) {\n issues.push(`paths.${path}: must be an object`)\n continue\n }\n const inTemplate = new Set(templateParams(path))\n for (const method of HTTP_METHODS) {\n const operation = item[method]\n if (operation === undefined) continue\n const label = `${method.toUpperCase()} ${path}`\n if (typeof operation.operationId !== \"string\" || operation.operationId.length === 0) {\n issues.push(`${label}: operationId is required`)\n continue\n }\n const previous = seenIds.get(operation.operationId)\n if (previous !== undefined)\n issues.push(`${label}: duplicate operationId ${operation.operationId} (also ${previous})`)\n seenIds.set(operation.operationId, label)\n if (!isRecord(operation.responses) || Object.keys(operation.responses).length === 0) {\n issues.push(`${label}: responses must declare at least one status`)\n }\n const parameters = mergeParameters(document, item, operation.parameters)\n const declared = new Set(parameters.filter((p) => p.in === \"path\").map((p) => p.name))\n for (const name of inTemplate) {\n if (!declared.has(name)) issues.push(`${label}: path parameter {${name}} is not declared`)\n }\n for (const parameter of parameters) {\n if (parameter.in === \"path\") {\n if (!inTemplate.has(parameter.name))\n issues.push(`${label}: path parameter ${parameter.name} is not in the template`)\n if (parameter.required !== true)\n issues.push(`${label}: path parameter ${parameter.name} must be required`)\n }\n }\n }\n }\n return issues\n}\n\nconst mergeParameters = (\n document: OpenAPIDocument,\n item: PathItemObject,\n own: PathItemObject[\"parameters\"],\n): ParameterObject[] => {\n const merged = new Map<string, ParameterObject>()\n for (const raw of item.parameters ?? []) {\n const parameter = deref<ParameterObject>(document, raw)\n merged.set(`${parameter.in}:${parameter.name}`, parameter)\n }\n for (const raw of own ?? []) {\n const parameter = deref<ParameterObject>(document, raw)\n merged.set(`${parameter.in}:${parameter.name}`, parameter)\n }\n return [...merged.values()]\n}\n\n/** Enumerate every operation in the document in path, then method order. */\nexport const listOperations = (document: OpenAPIDocument): Operation[] => {\n const operations: Operation[] = []\n for (const [path, item] of Object.entries(document.paths)) {\n for (const method of HTTP_METHODS) {\n const operation = item[method]\n if (operation?.operationId === undefined) continue\n const responses: Record<string, ResponseObject> = {}\n for (const [status, response] of Object.entries(operation.responses)) {\n responses[status] = deref<ResponseObject>(document, response)\n }\n operations.push({\n operationId: operation.operationId,\n method,\n path,\n operation,\n parameters: mergeParameters(document, item, operation.parameters),\n requestBody:\n operation.requestBody === undefined\n ? undefined\n : deref<RequestBodyObject>(document, operation.requestBody),\n responses,\n })\n }\n }\n return operations\n}\n\n/** Find one operation by id. */\nexport const findOperation = (\n document: OpenAPIDocument,\n operationId: string,\n): Operation | undefined =>\n listOperations(document).find((operation) => operation.operationId === operationId)\n\n/** Parameter names inside a path template, in order. */\nexport const pathTemplateParameters = templateParams\n\n/** Substitute `{name}` placeholders. Values are percent-encoded as path segments. */\nexport const expandPathTemplate = (template: string, values: Record<string, string>): string =>\n template.replace(/\\{([^}]+)\\}/g, (_, name: string) => {\n const value = values[name]\n if (value === undefined) throw new RangeError(`missing path parameter ${name}`)\n return encodeURIComponent(value)\n })\n\n/** The response object matching an HTTP status: exact match, then `2XX`-style range, then `default`. */\nexport const responseForStatus = (\n responses: Record<string, ResponseObject>,\n status: number,\n): ResponseObject | undefined =>\n responses[String(status)] ?? responses[`${Math.floor(status / 100)}XX`] ?? responses.default\n\nexport type { HttpMethod }\n", "/**\n * Mockingbird's OpenAPI extensions. They are deliberately generic: nothing here knows about any\n * particular provider. Provider specifics live in each provider's `openapi.yaml`.\n */\n\n/** `x-mockingbird` on an operation. */\nexport type OperationExtension = {\n /** Opt in to a terminal path parameter spanning slash-separated segments. */\n path?: { parameter: string; allowEmpty?: boolean }\n /** `false` marks an operation the mock explicitly does not implement. Default `true`. */\n supported?: boolean\n /** Human explanation, required when `supported: false` or `parity.enabled: false`. */\n reason?: string\n parity?: {\n /** Whether the differential runner generates this operation. Defaults to `supported`. */\n enabled?: boolean\n /** `false` for operations that must never hit a real account (destructive, billing\u2026). Default `true`. */\n safe?: boolean\n reason?: string\n }\n}\n\nexport type OperationMetadata = {\n path?: { parameter: string; allowEmpty?: boolean }\n supported: boolean\n reason: string | undefined\n parity: { enabled: boolean; safe: boolean; reason: string | undefined }\n}\n\n/** `x-mockingbird-resource`: this string value is the identity of a resource. */\nexport type ResourceIdentityExtension = { type: string; identity: true }\n\n/** `x-mockingbird-resource-ref`: this value must reference an existing resource of `type`. */\nexport type ResourceRefExtension = {\n type: string\n /** A well-formed id that does not exist, used to exercise not-found behaviour. */\n missing?: string\n}\n\nexport const VOLATILE_KINDS = [\"id\", \"timestamp\", \"token\", \"url\", \"account\", \"opaque\"] as const\nexport type VolatileKind = (typeof VOLATILE_KINDS)[number]\n\n/** `x-mockingbird-volatile`: nondeterministic on the real side; compared by shape only. */\nexport type VolatileExtension = { kind: VolatileKind }\n\nexport const SCOPE_VALUES = [\"run-id\", \"walk-start-unix\", \"walk-start-iso\"] as const\nexport type ScopeValue = (typeof SCOPE_VALUES)[number]\n\n/** `x-mockingbird-scope`: always generate this run-scoped value instead of a random one. */\nexport type ScopeExtension = { value: ScopeValue }\n\n/** `x-mockingbird-unsupported`: the mock does not implement this parameter/property. */\nexport type UnsupportedExtension = true | { reason?: string }\n\nexport type SchemaMetadata = {\n resource: ResourceIdentityExtension | undefined\n resourceRef: ResourceRefExtension | undefined\n volatile: VolatileExtension | undefined\n scope: ScopeExtension | undefined\n unsupported: { reason: string | undefined } | undefined\n}\n\nexport const EXTENSION_KEYS = {\n operation: \"x-mockingbird\",\n resource: \"x-mockingbird-resource\",\n resourceRef: \"x-mockingbird-resource-ref\",\n volatile: \"x-mockingbird-volatile\",\n scope: \"x-mockingbird-scope\",\n unsupported: \"x-mockingbird-unsupported\",\n parityHeader: \"x-mockingbird-parity-header\",\n} as const\n", "import type {\n HeaderObject,\n OpenAPIDocument,\n OperationObject,\n ParameterObject,\n ResponseObject,\n SchemaObject,\n} from \"@crvouga/mockingbird-openapi\"\nimport { deref, resolveSchema } from \"@crvouga/mockingbird-openapi\"\nimport {\n EXTENSION_KEYS,\n type OperationExtension,\n type OperationMetadata,\n SCOPE_VALUES,\n type SchemaMetadata,\n VOLATILE_KINDS,\n} from \"./types.js\"\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n\nconst extensionOf = (holder: object, key: string): unknown =>\n (holder as Record<string, unknown>)[key]\n\n/** Read `x-mockingbird` from an operation, applying defaults. */\nexport const operationMetadata = (operation: OperationObject): OperationMetadata => {\n const raw = extensionOf(operation, EXTENSION_KEYS.operation)\n const ext: OperationExtension = isRecord(raw) ? (raw as OperationExtension) : {}\n const supported = ext.supported ?? true\n const parity = ext.parity ?? {}\n return {\n ...(ext.path === undefined ? {} : { path: ext.path }),\n supported,\n reason: typeof ext.reason === \"string\" ? ext.reason : undefined,\n parity: {\n enabled: supported && (parity.enabled ?? true),\n safe: parity.safe ?? true,\n reason: typeof parity.reason === \"string\" ? parity.reason : undefined,\n },\n }\n}\n\nconst readResource = (raw: unknown): SchemaMetadata[\"resource\"] => {\n if (!isRecord(raw) || typeof raw.type !== \"string\" || raw.identity !== true) return undefined\n return { type: raw.type, identity: true }\n}\n\nconst readResourceRef = (raw: unknown): SchemaMetadata[\"resourceRef\"] => {\n if (!isRecord(raw) || typeof raw.type !== \"string\") return undefined\n return { type: raw.type, ...(typeof raw.missing === \"string\" ? { missing: raw.missing } : {}) }\n}\n\nconst readVolatile = (raw: unknown): SchemaMetadata[\"volatile\"] => {\n if (!isRecord(raw) || typeof raw.kind !== \"string\") return undefined\n const kind = VOLATILE_KINDS.find((k) => k === raw.kind)\n return kind === undefined ? undefined : { kind }\n}\n\nconst readScope = (raw: unknown): SchemaMetadata[\"scope\"] => {\n if (!isRecord(raw) || typeof raw.value !== \"string\") return undefined\n const value = SCOPE_VALUES.find((v) => v === raw.value)\n return value === undefined ? undefined : { value }\n}\n\nconst readUnsupported = (raw: unknown): SchemaMetadata[\"unsupported\"] => {\n if (raw === true) return { reason: undefined }\n if (isRecord(raw)) return { reason: typeof raw.reason === \"string\" ? raw.reason : undefined }\n return undefined\n}\n\n/**\n * Read Mockingbird's schema-level extensions from a (resolved) schema or parameter.\n * Extensions on a `$ref` wrapper win over the target's, matching {@link resolveSchema}.\n */\nexport const schemaMetadata = (holder: SchemaObject | ParameterObject): SchemaMetadata => ({\n resource: readResource(extensionOf(holder, EXTENSION_KEYS.resource)),\n resourceRef: readResourceRef(extensionOf(holder, EXTENSION_KEYS.resourceRef)),\n volatile: readVolatile(extensionOf(holder, EXTENSION_KEYS.volatile)),\n scope: readScope(extensionOf(holder, EXTENSION_KEYS.scope)),\n unsupported: readUnsupported(extensionOf(holder, EXTENSION_KEYS.unsupported)),\n})\n\n/** Metadata of a parameter: extensions on the parameter itself win over its schema's. */\nexport const parameterMetadata = (\n document: OpenAPIDocument,\n parameter: ParameterObject,\n): SchemaMetadata => {\n const own = schemaMetadata(parameter)\n const fromSchema = parameter.schema\n ? schemaMetadata(resolveSchema(document, parameter.schema))\n : undefined\n return {\n resource: own.resource ?? fromSchema?.resource,\n resourceRef: own.resourceRef ?? fromSchema?.resourceRef,\n volatile: own.volatile ?? fromSchema?.volatile,\n scope: own.scope ?? fromSchema?.scope,\n unsupported: own.unsupported ?? fromSchema?.unsupported,\n }\n}\n\n/** Lower-cased names of response headers flagged with `x-mockingbird-parity-header: true`. */\nexport const parityHeaders = (document: OpenAPIDocument, response: ResponseObject): string[] => {\n const names: string[] = []\n for (const [name, raw] of Object.entries(response.headers ?? {})) {\n const header = deref<HeaderObject>(document, raw)\n if (extensionOf(header, EXTENSION_KEYS.parityHeader) === true) names.push(name.toLowerCase())\n }\n return names.sort()\n}\n", "//#region src/request/constants.ts\nconst GET_MATCH_RESULT = Symbol();\n//#endregion\nexport { GET_MATCH_RESULT };\n", "import { sha256 } from \"./crypto.js\";\n//#region src/utils/buffer.ts\n/**\n* @module\n* Buffer utility.\n*/\nconst equal = (a, b) => {\n\tif (a === b) return true;\n\tif (a.byteLength !== b.byteLength) return false;\n\tconst va = new DataView(a);\n\tconst vb = new DataView(b);\n\tlet i = va.byteLength;\n\twhile (i--) if (va.getUint8(i) !== vb.getUint8(i)) return false;\n\treturn true;\n};\nconst constantTimeEqualString = (a, b) => {\n\tconst aLen = a.length;\n\tconst bLen = b.length;\n\tconst maxLen = Math.max(aLen, bLen);\n\tlet out = aLen ^ bLen;\n\tfor (let i = 0; i < maxLen; i++) {\n\t\tconst aChar = i < aLen ? a.charCodeAt(i) : 0;\n\t\tconst bChar = i < bLen ? b.charCodeAt(i) : 0;\n\t\tout |= aChar ^ bChar;\n\t}\n\treturn out === 0;\n};\nconst timingSafeEqualString = async (a, b, hashFunction) => {\n\tif (!hashFunction) hashFunction = sha256;\n\tconst [sa, sb] = await Promise.all([hashFunction(a), hashFunction(b)]);\n\tif (sa == null || sb == null || typeof sa !== \"string\" || typeof sb !== \"string\") return false;\n\tconst hashEqual = constantTimeEqualString(sa, sb);\n\tconst originalEqual = constantTimeEqualString(a, b);\n\treturn hashEqual && originalEqual;\n};\nconst timingSafeEqual = async (a, b, hashFunction) => {\n\tif (typeof a === \"string\" && typeof b === \"string\") return timingSafeEqualString(a, b, hashFunction);\n\tif (!hashFunction) hashFunction = sha256;\n\tconst [sa, sb] = await Promise.all([hashFunction(a), hashFunction(b)]);\n\tif (!sa || !sb || typeof sa !== \"string\" || typeof sb !== \"string\") return false;\n\treturn timingSafeEqualString(sa, sb);\n};\nconst bufferToString = (buffer) => {\n\tif (buffer instanceof ArrayBuffer) return new TextDecoder(\"utf-8\").decode(buffer);\n\treturn buffer;\n};\nconst bufferToFormData = (arrayBuffer, contentType) => {\n\treturn new Response(arrayBuffer, { headers: { \"Content-Type\": contentType.replace(/^[^;]+/, (mediaType) => mediaType.toLowerCase()) } }).formData();\n};\n//#endregion\nexport { bufferToFormData, bufferToString, equal, timingSafeEqual };\n", "import { bufferToFormData } from \"./buffer.js\";\n//#region src/utils/body.ts\nconst MAX_NESTED_OBJECTS = 1e4;\nconst isRawRequest = (request) => \"headers\" in request;\nconst parseBody = async (request, options = Object.create(null)) => {\n\tconst { all = false, dot = false } = options;\n\tconst mediaType = (isRawRequest(request) ? request.headers : request.raw.headers).get(\"Content-Type\")?.split(\";\")[0].trim().toLowerCase();\n\tif (mediaType === \"multipart/form-data\" || mediaType === \"application/x-www-form-urlencoded\") return parseFormData(request, {\n\t\tall,\n\t\tdot\n\t});\n\treturn {};\n};\n/**\n* Parses form data from a request.\n*\n* @template T - The type of the parsed body data.\n* @param {HonoRequest | Request} request - The request object containing form data.\n* @param {ParseBodyOptions} options - Options for parsing the form data.\n* @returns {Promise<T>} The parsed body data.\n*/\nasync function parseFormData(request, options) {\n\tif (!isRawRequest(request) && request.bodyCache.formData) return convertFormDataToBodyData(await request.bodyCache.formData, options);\n\tconst headers = isRawRequest(request) ? request.headers : request.raw.headers;\n\tconst arrayBuffer = await request.arrayBuffer();\n\tconst formDataPromise = bufferToFormData(arrayBuffer, headers.get(\"Content-Type\") || \"\");\n\tif (!isRawRequest(request)) request.bodyCache.formData = formDataPromise;\n\tconst formData = await formDataPromise;\n\tif (formData) return convertFormDataToBodyData(formData, options);\n\treturn {};\n}\n/**\n* Converts form data to body data based on the provided options.\n*\n* @template T - The type of the parsed body data.\n* @param {FormData} formData - The form data to convert.\n* @param {ParseBodyOptions} options - Options for parsing the form data.\n* @returns {T} The converted body data.\n*/\nfunction convertFormDataToBodyData(formData, options) {\n\tconst form = Object.create(null);\n\tconst nestingState = { count: 0 };\n\tformData.forEach((value, key) => {\n\t\tif (!(options.all || key.endsWith(\"[]\"))) form[key] = value;\n\t\telse handleParsingAllValues(form, key, value);\n\t});\n\tif (options.dot) Object.entries(form).forEach(([key, value]) => {\n\t\tif (key.includes(\".\")) {\n\t\t\thandleParsingNestedValues(form, key, value, nestingState);\n\t\t\tdelete form[key];\n\t\t}\n\t});\n\treturn form;\n}\n/**\n* Handles parsing all values for a given key, supporting multiple values as arrays.\n*\n* @param {BodyData} form - The form data object.\n* @param {string} key - The key to parse.\n* @param {FormDataEntryValue} value - The value to assign.\n*/\nconst handleParsingAllValues = (form, key, value) => {\n\tif (form[key] !== void 0) {\n\t\tif (Array.isArray(form[key])) form[key].push(value);\n\t\telse form[key] = [form[key], value];\n\t} else if (!key.endsWith(\"[]\")) form[key] = value;\n\telse form[key] = [value];\n};\n/**\n* Handles parsing nested values using dot notation keys.\n*\n* @param {BodyData} form - The form data object.\n* @param {string} key - The dot notation key.\n* @param {BodyDataValue} value - The value to assign.\n*/\nconst handleParsingNestedValues = (form, key, value, state) => {\n\tif (/(?:^|\\.)__proto__\\./.test(key)) return;\n\tlet nestedForm = form;\n\tconst keys = key.split(\".\", 34);\n\tif (keys.length > 33) throwNestingLimitExceeded();\n\tkeys.forEach((key, index) => {\n\t\tif (index === keys.length - 1) nestedForm[key] = value;\n\t\telse {\n\t\t\tif (!nestedForm[key] || typeof nestedForm[key] !== \"object\" || Array.isArray(nestedForm[key]) || nestedForm[key] instanceof File) {\n\t\t\t\tif (state.count++ >= MAX_NESTED_OBJECTS) throwNestingLimitExceeded();\n\t\t\t\tnestedForm[key] = Object.create(null);\n\t\t\t}\n\t\t\tnestedForm = nestedForm[key];\n\t\t}\n\t});\n};\nconst throwNestingLimitExceeded = () => {\n\tthrow new Error(\"Nesting limit exceeded\");\n};\n//#endregion\nexport { parseBody };\n", "//#region src/utils/url.ts\nconst splitPath = (path) => {\n\tconst paths = path.split(\"/\");\n\tif (paths[0] === \"\") paths.shift();\n\treturn paths;\n};\nconst splitRoutingPath = (routePath) => {\n\tconst { groups, path } = extractGroupsFromPath(routePath);\n\tconst paths = splitPath(path);\n\treturn replaceGroupMarks(paths, groups);\n};\nconst extractGroupsFromPath = (path) => {\n\tconst groups = [];\n\tpath = path.replace(/\\{[^}]+\\}/g, (match, index) => {\n\t\tconst mark = `@${index}`;\n\t\tgroups.push([mark, match]);\n\t\treturn mark;\n\t});\n\treturn {\n\t\tgroups,\n\t\tpath\n\t};\n};\nconst replaceGroupMarks = (paths, groups) => {\n\tfor (let i = groups.length - 1; i >= 0; i--) {\n\t\tconst [mark] = groups[i];\n\t\tfor (let j = paths.length - 1; j >= 0; j--) if (paths[j].includes(mark)) {\n\t\t\tpaths[j] = paths[j].replace(mark, groups[i][1]);\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn paths;\n};\nconst patternCache = {};\nconst getPattern = (label, next) => {\n\tif (label === \"*\") return \"*\";\n\tconst match = label.match(/^\\:([^\\{\\}]+)(?:\\{(.+)\\})?$/);\n\tif (match) {\n\t\tconst cacheKey = `${label}#${next}`;\n\t\tif (!patternCache[cacheKey]) {\n\t\t\tif (match[2]) patternCache[cacheKey] = next && next[0] !== \":\" && next[0] !== \"*\" ? [\n\t\t\t\tcacheKey,\n\t\t\t\tmatch[1],\n\t\t\t\tnew RegExp(`^${match[2]}(?=/${next})`)\n\t\t\t] : [\n\t\t\t\tlabel,\n\t\t\t\tmatch[1],\n\t\t\t\tnew RegExp(`^${match[2]}$`)\n\t\t\t];\n\t\t\telse patternCache[cacheKey] = [\n\t\t\t\tlabel,\n\t\t\t\tmatch[1],\n\t\t\t\ttrue\n\t\t\t];\n\t\t}\n\t\treturn patternCache[cacheKey];\n\t}\n\treturn null;\n};\nconst tryDecode = (str, decoder) => {\n\ttry {\n\t\treturn decoder(str);\n\t} catch {\n\t\treturn str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match) => {\n\t\t\ttry {\n\t\t\t\treturn decoder(match);\n\t\t\t} catch {\n\t\t\t\treturn match;\n\t\t\t}\n\t\t});\n\t}\n};\n/**\n* Try to apply decodeURI() to given string.\n* If it fails, skip invalid percent encoding or invalid UTF-8 sequences, and apply decodeURI() to the rest as much as possible.\n* @param str The string to decode.\n* @returns The decoded string that sometimes contains undecodable percent encoding.\n* @example\n* tryDecodeURI('Hello%20World') // 'Hello World'\n* tryDecodeURI('Hello%20World/%A4%A2') // 'Hello World/%A4%A2'\n*/\nconst tryDecodeURI = (str) => tryDecode(str, decodeURI);\nconst getPath = (request) => {\n\tconst url = request.url;\n\tconst start = url.indexOf(\"/\", url.indexOf(\":\") + 4);\n\tlet i = start;\n\tfor (; i < url.length; i++) {\n\t\tconst charCode = url.charCodeAt(i);\n\t\tif (charCode === 37) {\n\t\t\tconst queryIndex = url.indexOf(\"?\", i);\n\t\t\tconst hashIndex = url.indexOf(\"#\", i);\n\t\t\tconst end = queryIndex === -1 ? hashIndex === -1 ? void 0 : hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex);\n\t\t\tconst path = url.slice(start, end);\n\t\t\treturn tryDecodeURI(path.includes(\"%25\") ? path.replace(/%25/g, \"%2525\") : path);\n\t\t} else if (charCode === 63 || charCode === 35) break;\n\t}\n\treturn url.slice(start, i);\n};\n/**\n* @deprecated\n* Use the `URL` API instead.\n*/\nconst getQueryStrings = (url) => {\n\tconst queryIndex = url.indexOf(\"?\", 8);\n\tif (queryIndex === -1) return \"\";\n\tconst hashIndex = url.indexOf(\"#\", 8);\n\treturn hashIndex === -1 ? url.slice(queryIndex) : queryIndex < hashIndex ? url.slice(queryIndex, hashIndex) : \"\";\n};\nconst getPathNoStrict = (request) => {\n\tconst result = getPath(request);\n\treturn result.length > 1 && result.at(-1) === \"/\" ? result.slice(0, -1) : result;\n};\n/**\n* Merge paths.\n* @param {string[]} ...paths - The paths to merge.\n* @returns {string} The merged path.\n* @example\n* mergePath('/api', '/users') // '/api/users'\n* mergePath('/api/', '/users') // '/api/users'\n* mergePath('/api', '/') // '/api'\n* mergePath('/api/', '/') // '/api/'\n*/\nconst mergePath = (base, sub, ...rest) => {\n\tif (rest.length) sub = mergePath(sub, ...rest);\n\treturn `${base?.[0] === \"/\" ? \"\" : \"/\"}${base}${sub === \"/\" ? \"\" : `${base?.at(-1) === \"/\" ? \"\" : \"/\"}${sub?.[0] === \"/\" ? sub.slice(1) : sub}`}`;\n};\nconst checkOptionalParameter = (path) => {\n\tif (path.charCodeAt(path.length - 1) !== 63 || !path.includes(\":\")) return null;\n\tconst segments = path.split(\"/\");\n\tconst results = [];\n\tlet basePath = \"\";\n\tsegments.forEach((segment) => {\n\t\tif (segment !== \"\" && !/\\:/.test(segment)) basePath += \"/\" + segment;\n\t\telse if (/\\:/.test(segment)) {\n\t\t\tif (segment.charCodeAt(segment.length - 1) === 63) {\n\t\t\t\tif (results.length === 0 && basePath === \"\") results.push(\"/\");\n\t\t\t\telse results.push(basePath);\n\t\t\t\tconst optionalSegment = segment.slice(0, -1);\n\t\t\t\tbasePath += \"/\" + optionalSegment;\n\t\t\t\tresults.push(basePath);\n\t\t\t} else basePath += \"/\" + segment;\n\t\t}\n\t});\n\treturn results.filter((v, i, a) => a.indexOf(v) === i);\n};\nconst tryDecodeURIComponent = (str) => str.indexOf(\"%\") !== -1 ? tryDecode(str, decodeURIComponent_) : str;\nconst _decodeURI = (value) => {\n\tif (value.indexOf(\"+\") !== -1) value = value.replace(/\\+/g, \" \");\n\treturn tryDecodeURIComponent(value);\n};\nconst _getQueryParam = (url, key, multiple) => {\n\tconst hashIndex = url.indexOf(\"#\", 8);\n\tif (hashIndex !== -1) url = url.slice(0, hashIndex);\n\tlet encoded;\n\tif (!multiple && key && key.indexOf(\"%\") === -1 && key.indexOf(\"+\") === -1) {\n\t\tlet keyIndex = url.indexOf(\"?\", 8);\n\t\tif (keyIndex === -1) return;\n\t\tif (!url.startsWith(key, keyIndex + 1)) keyIndex = url.indexOf(`&${key}`, keyIndex + 1);\n\t\twhile (keyIndex !== -1) {\n\t\t\tconst trailingKeyCode = url.charCodeAt(keyIndex + key.length + 1);\n\t\t\tif (trailingKeyCode === 61) {\n\t\t\t\tconst valueIndex = keyIndex + key.length + 2;\n\t\t\t\tconst endIndex = url.indexOf(\"&\", valueIndex);\n\t\t\t\treturn _decodeURI(url.slice(valueIndex, endIndex === -1 ? void 0 : endIndex));\n\t\t\t} else if (trailingKeyCode == 38 || isNaN(trailingKeyCode)) return \"\";\n\t\t\tkeyIndex = url.indexOf(`&${key}`, keyIndex + 1);\n\t\t}\n\t\tencoded = /[%+]/.test(url);\n\t\tif (!encoded) return;\n\t}\n\tconst results = Object.create(null);\n\tencoded ??= /[%+]/.test(url);\n\tlet keyIndex = url.indexOf(\"?\", 8);\n\twhile (keyIndex !== -1) {\n\t\tconst nextKeyIndex = url.indexOf(\"&\", keyIndex + 1);\n\t\tlet valueIndex = url.indexOf(\"=\", keyIndex);\n\t\tif (valueIndex > nextKeyIndex && nextKeyIndex !== -1) valueIndex = -1;\n\t\tlet name = url.slice(keyIndex + 1, valueIndex === -1 ? nextKeyIndex === -1 ? void 0 : nextKeyIndex : valueIndex);\n\t\tif (encoded) name = _decodeURI(name);\n\t\tkeyIndex = nextKeyIndex;\n\t\tif (name === \"\") continue;\n\t\tlet value;\n\t\tif (valueIndex === -1) value = \"\";\n\t\telse {\n\t\t\tvalue = url.slice(valueIndex + 1, nextKeyIndex === -1 ? void 0 : nextKeyIndex);\n\t\t\tif (encoded) value = _decodeURI(value);\n\t\t}\n\t\tif (multiple) {\n\t\t\tif (!(results[name] && Array.isArray(results[name]))) results[name] = [];\n\t\t\tresults[name].push(value);\n\t\t} else results[name] ??= value;\n\t}\n\treturn key ? results[key] : results;\n};\nconst getQueryParam = _getQueryParam;\nconst getQueryParams = (url, key) => {\n\treturn _getQueryParam(url, key, true);\n};\nconst decodeURIComponent_ = decodeURIComponent;\n//#endregion\nexport { checkOptionalParameter, decodeURIComponent_, getPath, getPathNoStrict, getPattern, getQueryParam, getQueryParams, getQueryStrings, mergePath, splitPath, splitRoutingPath, tryDecode, tryDecodeURI, tryDecodeURIComponent };\n", "import { HTTPException } from \"./http-exception.js\";\nimport { GET_MATCH_RESULT } from \"./request/constants.js\";\nimport { parseBody } from \"./utils/body.js\";\nimport { getQueryParam, getQueryParams, tryDecodeURIComponent } from \"./utils/url.js\";\n//#region src/request.ts\nvar HonoRequest = class {\n\t/**\n\t* `.raw` can get the raw Request object.\n\t*\n\t* @see {@link https://hono.dev/docs/api/request#raw}\n\t*\n\t* @example\n\t* ```ts\n\t* // For Cloudflare Workers\n\t* app.post('/', async (c) => {\n\t* const metadata = c.req.raw.cf?.hostMetadata?\n\t* ...\n\t* })\n\t* ```\n\t*/\n\traw;\n\t#validatedData;\n\t#matchResult;\n\trouteIndex = 0;\n\t/**\n\t* `.path` can get the pathname of the request.\n\t*\n\t* @see {@link https://hono.dev/docs/api/request#path}\n\t*\n\t* @example\n\t* ```ts\n\t* app.get('/about/me', (c) => {\n\t* const pathname = c.req.path // `/about/me`\n\t* })\n\t* ```\n\t*/\n\tpath;\n\tbodyCache = {};\n\tconstructor(request, path = \"/\", matchResult = [[]]) {\n\t\tthis.raw = request;\n\t\tthis.path = path;\n\t\tthis.#matchResult = matchResult;\n\t}\n\tparam(key) {\n\t\treturn key ? this.#getDecodedParam(key) : this.#getAllDecodedParams();\n\t}\n\t#getDecodedParam(key) {\n\t\tconst paramKey = this.#matchResult[0][this.routeIndex]?.[1][key];\n\t\tconst param = this.#getParamValue(paramKey);\n\t\treturn param && tryDecodeURIComponent(param);\n\t}\n\t#getAllDecodedParams() {\n\t\tconst decoded = {};\n\t\tconst keys = Object.keys(this.#matchResult[0][this.routeIndex]?.[1] ?? {});\n\t\tfor (const key of keys) {\n\t\t\tconst value = this.#getParamValue(this.#matchResult[0][this.routeIndex][1][key]);\n\t\t\tif (value !== void 0) decoded[key] = tryDecodeURIComponent(value);\n\t\t}\n\t\treturn decoded;\n\t}\n\t#getParamValue(paramKey) {\n\t\treturn this.#matchResult[1] ? this.#matchResult[1][paramKey] : paramKey;\n\t}\n\tquery(key) {\n\t\treturn getQueryParam(this.url, key);\n\t}\n\tqueries(key) {\n\t\treturn getQueryParams(this.url, key);\n\t}\n\theader(name) {\n\t\tif (name) return this.raw.headers.get(name) ?? void 0;\n\t\tconst headerData = Object.create(null);\n\t\tthis.raw.headers.forEach((value, key) => {\n\t\t\theaderData[key] = value;\n\t\t});\n\t\treturn headerData;\n\t}\n\tasync parseBody(options) {\n\t\treturn parseBody(this, options);\n\t}\n\t#cachedBody = (key) => {\n\t\tconst { bodyCache, raw } = this;\n\t\tconst cachedBody = bodyCache[key];\n\t\tif (cachedBody) return cachedBody;\n\t\tfor (const anyCachedKey in bodyCache) return bodyCache[anyCachedKey].then((body) => {\n\t\t\tif (anyCachedKey === \"json\") body = JSON.stringify(body);\n\t\t\tconst contentType = anyCachedKey === \"formData\" ? void 0 : raw.headers.get(\"content-type\");\n\t\t\treturn new Response(body, { headers: contentType ? { \"Content-Type\": contentType } : void 0 })[key]();\n\t\t});\n\t\treturn bodyCache[key] = raw[key]();\n\t};\n\t/**\n\t* `.json()` can parse Request body of type `application/json`\n\t*\n\t* @see {@link https://hono.dev/docs/api/request#json}\n\t*\n\t* @example\n\t* ```ts\n\t* app.post('/entry', async (c) => {\n\t* const body = await c.req.json()\n\t* })\n\t* ```\n\t*/\n\tjson() {\n\t\treturn this.#cachedBody(\"text\").then((text) => JSON.parse(text));\n\t}\n\t/**\n\t* `.text()` can parse Request body of type `text/plain`\n\t*\n\t* @see {@link https://hono.dev/docs/api/request#text}\n\t*\n\t* @example\n\t* ```ts\n\t* app.post('/entry', async (c) => {\n\t* const body = await c.req.text()\n\t* })\n\t* ```\n\t*/\n\ttext() {\n\t\treturn this.#cachedBody(\"text\");\n\t}\n\t/**\n\t* `.arrayBuffer()` parse Request body as an `ArrayBuffer`\n\t*\n\t* @see {@link https://hono.dev/docs/api/request#arraybuffer}\n\t*\n\t* @example\n\t* ```ts\n\t* app.post('/entry', async (c) => {\n\t* const body = await c.req.arrayBuffer()\n\t* })\n\t* ```\n\t*/\n\tarrayBuffer() {\n\t\treturn this.#cachedBody(\"arrayBuffer\");\n\t}\n\t/**\n\t* `.bytes()` parses the request body as a `Uint8Array`.\n\t*\n\t* @see {@link https://hono.dev/docs/api/request#bytes}\n\t*\n\t* @example\n\t* ```ts\n\t* app.post('/entry', async (c) => {\n\t* const body = await c.req.bytes()\n\t* })\n\t* ```\n\t*/\n\tbytes() {\n\t\treturn this.#cachedBody(\"arrayBuffer\").then((buffer) => new Uint8Array(buffer));\n\t}\n\t/**\n\t* Parses the request body as a `Blob`.\n\t* @example\n\t* ```ts\n\t* app.post('/entry', async (c) => {\n\t* const body = await c.req.blob();\n\t* });\n\t* ```\n\t* @see https://hono.dev/docs/api/request#blob\n\t*/\n\tblob() {\n\t\treturn this.#cachedBody(\"blob\");\n\t}\n\t/**\n\t* Parses the request body as `FormData`.\n\t* @example\n\t* ```ts\n\t* app.post('/entry', async (c) => {\n\t* const body = await c.req.formData();\n\t* });\n\t* ```\n\t* @see https://hono.dev/docs/api/request#formdata\n\t*/\n\tformData() {\n\t\treturn this.#cachedBody(\"formData\");\n\t}\n\t/**\n\t* Adds validated data to the request.\n\t*\n\t* @param target - The target of the validation.\n\t* @param data - The validated data to add.\n\t*/\n\taddValidatedData(target, data) {\n\t\t(this.#validatedData ??= {})[target] = data;\n\t}\n\tvalid(target) {\n\t\treturn this.#validatedData?.[target];\n\t}\n\t/**\n\t* `.url()` can get the request url strings.\n\t*\n\t* @see {@link https://hono.dev/docs/api/request#url}\n\t*\n\t* @example\n\t* ```ts\n\t* app.get('/about/me', (c) => {\n\t* const url = c.req.url // `http://localhost:8787/about/me`\n\t* ...\n\t* })\n\t* ```\n\t*/\n\tget url() {\n\t\treturn this.raw.url;\n\t}\n\t/**\n\t* `.method()` can get the method name of the request.\n\t*\n\t* @see {@link https://hono.dev/docs/api/request#method}\n\t*\n\t* @example\n\t* ```ts\n\t* app.get('/about/me', (c) => {\n\t* const method = c.req.method // `GET`\n\t* })\n\t* ```\n\t*/\n\tget method() {\n\t\treturn this.raw.method;\n\t}\n\tget [GET_MATCH_RESULT]() {\n\t\treturn this.#matchResult;\n\t}\n\t/**\n\t* `.matchedRoutes()` can return a matched route in the handler\n\t*\n\t* @deprecated\n\t*\n\t* Use matchedRoutes helper defined in \"hono/route\" instead.\n\t*\n\t* @see {@link https://hono.dev/docs/api/request#matchedroutes}\n\t*\n\t* @example\n\t* ```ts\n\t* app.use('*', async function logger(c, next) {\n\t* await next()\n\t* c.req.matchedRoutes.forEach(({ handler, method, path }, i) => {\n\t* const name = handler.name || (handler.length < 2 ? '[handler]' : '[middleware]')\n\t* console.log(\n\t* method,\n\t* ' ',\n\t* path,\n\t* ' '.repeat(Math.max(10 - path.length, 0)),\n\t* name,\n\t* i === c.req.routeIndex ? '<- respond from here' : ''\n\t* )\n\t* })\n\t* })\n\t* ```\n\t*/\n\tget matchedRoutes() {\n\t\treturn this.#matchResult[0].map(([[, route]]) => route);\n\t}\n\t/**\n\t* `routePath()` can retrieve the path registered within the handler\n\t*\n\t* @deprecated\n\t*\n\t* Use routePath helper defined in \"hono/route\" instead.\n\t*\n\t* @see {@link https://hono.dev/docs/api/request#routepath}\n\t*\n\t* @example\n\t* ```ts\n\t* app.get('/posts/:id', (c) => {\n\t* return c.json({ path: c.req.routePath })\n\t* })\n\t* ```\n\t*/\n\tget routePath() {\n\t\treturn this.#matchResult[0].map(([[, route]]) => route)[this.routeIndex].path;\n\t}\n};\n/**\n* Clones a HonoRequest's underlying raw Request object.\n*\n* This utility handles both consumed and unconsumed request bodies:\n* - If the request body hasn't been consumed, it uses the native `clone()` method\n* - If the request body has been consumed, it reconstructs a new Request using cached body data\n*\n* This is particularly useful when you need to:\n* - Process the same request body multiple times\n* - Pass requests to external services after validation\n*\n* @param req - The HonoRequest object to clone\n* @returns A Promise that resolves to a new Request object with the same properties\n* @throws {HTTPException} If the request body was consumed directly via `req.raw`\n* without using HonoRequest methods (e.g., `req.json()`, `req.text()`), making it\n* impossible to reconstruct the body from cache\n*\n* @example\n* ```ts\n* // Clone after consuming the body (e.g., after validation)\n* app.post('/forward',\n* validator('json', (data) => data),\n* async (c) => {\n* const validated = c.req.valid('json')\n* // Body has been consumed, but cloneRawRequest still works\n* const clonedReq = await cloneRawRequest(c.req)\n* return fetch('http://backend-service.com', clonedReq)\n* }\n* )\n* ```\n*/\nconst cloneRawRequest = async (req) => {\n\tif (!req.raw.bodyUsed) return req.raw.clone();\n\tconst cacheKey = Object.keys(req.bodyCache)[0];\n\tif (!cacheKey) throw new HTTPException(500, { message: \"Cannot clone request: body was already consumed and not cached. Please use HonoRequest methods (e.g., req.json(), req.text()) instead of consuming req.raw directly.\" });\n\tlet body = await req[cacheKey]();\n\tconst headers = req.header();\n\tif (cacheKey === \"json\") {\n\t\tbody = JSON.stringify(body);\n\t\tdelete headers[\"content-length\"];\n\t} else if (body instanceof FormData) {\n\t\tdelete headers[\"content-type\"];\n\t\tdelete headers[\"content-length\"];\n\t}\n\tconst requestInit = {\n\t\tbody,\n\t\tcache: req.raw.cache,\n\t\tcredentials: req.raw.credentials,\n\t\theaders,\n\t\tintegrity: req.raw.integrity,\n\t\tkeepalive: req.raw.keepalive,\n\t\tmethod: req.method,\n\t\tmode: req.raw.mode,\n\t\tredirect: req.raw.redirect,\n\t\treferrer: req.raw.referrer,\n\t\treferrerPolicy: req.raw.referrerPolicy,\n\t\tsignal: req.raw.signal\n\t};\n\treturn new Request(req.url, requestInit);\n};\n//#endregion\nexport { HonoRequest, cloneRawRequest };\n", "//#region src/router/utils.ts\nconst createNullObject = () => Object.create(null);\n//#endregion\nexport { createNullObject };\n", "import { checkOptionalParameter } from \"../../utils/url.js\";\nimport { MESSAGE_MATCHER_IS_ALREADY_BUILT, UnsupportedPathError } from \"../../router.js\";\nimport { createNullObject } from \"../utils.js\";\nimport { emptyParam, match } from \"./matcher.js\";\nimport { LABEL_REG_EXP_STR, PATH_ERROR, TAIL_WILDCARD_REG_EXP_STR } from \"./node.js\";\nimport { Trie } from \"./trie.js\";\n//#region src/router/reg-exp-router/router.ts\nlet wildcardRegExpCache = createNullObject();\nfunction buildWildcardRegExp(path) {\n\treturn wildcardRegExpCache[path] ??= new RegExp(`^${path.replace(/\\/:[^/{}]+(?:\\{\\[\\^\\/]\\+})?(?=[/{]|$)|\\/?\\*$|([.\\\\+*[^\\]$()?{}|])/g, (match, metaChar) => metaChar ? `\\\\${metaChar}` : match === \"/*\" ? TAIL_WILDCARD_REG_EXP_STR : match === \"*\" ? \".*\" : `/:${LABEL_REG_EXP_STR}`)}$`);\n}\nfunction findMiddleware(middleware, path) {\n\tfor (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) if (buildWildcardRegExp(k).test(path)) return [...middleware[k]];\n}\nvar RegExpRouter = class {\n\tname = \"RegExpRouter\";\n\t#middleware;\n\t#routes;\n\t#tries;\n\tconstructor() {\n\t\tthis.#middleware = { [\"ALL\"]: createNullObject() };\n\t\tthis.#routes = { [\"ALL\"]: createNullObject() };\n\t\tthis.#tries = { [\"ALL\"]: new Trie() };\n\t}\n\t#insertPath(method, path) {\n\t\ttry {\n\t\t\tthis.#tries[method].insert(path, !/\\*|\\/:/.test(path));\n\t\t} catch (e) {\n\t\t\tthrow e === PATH_ERROR ? new UnsupportedPathError(path) : e;\n\t\t}\n\t}\n\tadd(method, path, handler) {\n\t\tconst middleware = this.#middleware;\n\t\tconst routes = this.#routes;\n\t\tif (!middleware) throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);\n\t\tif (!middleware[method]) {\n\t\t\tthis.#tries[method] = new Trie();\n\t\t\tfor (const handlerMap of [middleware, routes]) {\n\t\t\t\thandlerMap[method] = createNullObject();\n\t\t\t\tfor (const p in handlerMap[\"ALL\"]) {\n\t\t\t\t\thandlerMap[method][p] = [...handlerMap[\"ALL\"][p]];\n\t\t\t\t\tthis.#insertPath(method, p);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (path === \"/*\") path = \"*\";\n\t\tconst methods = method === \"ALL\" ? Object.keys(middleware) : [method];\n\t\tif (/\\*$/.test(path)) {\n\t\t\tconst re = buildWildcardRegExp(path);\n\t\t\tfor (const m of methods) if (!middleware[m][path]) {\n\t\t\t\tthis.#insertPath(m, path);\n\t\t\t\tmiddleware[m][path] = findMiddleware(middleware[m], path) || findMiddleware(middleware[\"ALL\"], path) || [];\n\t\t\t}\n\t\t\tfor (const handlerMap of [middleware, routes]) for (const m of methods) for (const p in handlerMap[m]) re.test(p) && handlerMap[m][p].push([handler, path]);\n\t\t\treturn;\n\t\t}\n\t\tconst paths = checkOptionalParameter(path) || [path];\n\t\tfor (const path of paths) for (const m of methods) {\n\t\t\tif (!routes[m][path]) {\n\t\t\t\tthis.#insertPath(m, path);\n\t\t\t\troutes[m][path] = findMiddleware(middleware[m], path) || findMiddleware(middleware[\"ALL\"], path) || [];\n\t\t\t}\n\t\t\troutes[m][path].push([handler, path]);\n\t\t}\n\t}\n\tmatch = match;\n\tbuildAllMatchers() {\n\t\tconst matchers = createNullObject();\n\t\tfor (const method of Object.keys(this.#routes)) matchers[method] = this.#buildMatcher(method);\n\t\tthis.#middleware = this.#routes = this.#tries = void 0;\n\t\twildcardRegExpCache = createNullObject();\n\t\treturn matchers;\n\t}\n\t#buildMatcher(method) {\n\t\tconst middleware = this.#middleware[method];\n\t\tconst routes = this.#routes[method];\n\t\tconst trie = this.#tries[method];\n\t\tconst staticMap = createNullObject();\n\t\tconst handlerData = [];\n\t\tconst [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();\n\t\tfor (const r of [middleware, routes]) for (const path in r) {\n\t\t\tconst handlers = r[path];\n\t\t\tconst pathData = trie.paths[path];\n\t\t\tif (!pathData) {\n\t\t\t\tstaticMap[path] = [handlers.map(([h]) => [h, createNullObject()]), emptyParam];\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\thandlerData[pathData[0]] = handlers.map(([h, handlerPath]) => [h, trie.paths[handlerPath][1].reduceRight((map, [key], i) => {\n\t\t\t\tmap[key] = paramReplacementMap[pathData[1][i][1]];\n\t\t\t\treturn map;\n\t\t\t}, createNullObject())]);\n\t\t}\n\t\treturn [\n\t\t\tregexp,\n\t\t\tindexReplacementMap.map((i) => handlerData[i]),\n\t\t\tstaticMap\n\t\t];\n\t}\n};\n//#endregion\nexport { RegExpRouter };\n", "import { getPattern, splitPath, splitRoutingPath } from \"../../utils/url.js\";\nimport \"../../router.js\";\nimport { createNullObject } from \"../utils.js\";\n//#region src/router/trie-router/node.ts\nconst emptyParams = createNullObject();\nlet order = 0;\nvar Node = class Node {\n\t#methods = [];\n\t#children = createNullObject();\n\t#patterns = [];\n\t#pattern;\n\t#params = emptyParams;\n\tinsert(method, path, handler) {\n\t\tlet curNode = this;\n\t\tconst parts = splitRoutingPath(path);\n\t\tconst possibleKeys = /* @__PURE__ */ new Set();\n\t\tlet i = 0;\n\t\tfor (const p of parts) {\n\t\t\tconst nextP = parts[++i];\n\t\t\tconst pattern = getPattern(p, nextP) || (nextP === void 0 && p && p.indexOf(\"*\") === p.length - 1 ? p : null);\n\t\t\tconst isParam = Array.isArray(pattern);\n\t\t\tconst key = isParam ? pattern[0] : pattern || p;\n\t\t\tconst child = curNode.#children[key] ||= new Node();\n\t\t\tif (pattern && !child.#pattern) {\n\t\t\t\tchild.#pattern = pattern;\n\t\t\t\tcurNode.#patterns.push(child);\n\t\t\t}\n\t\t\tcurNode = child;\n\t\t\tif (isParam) possibleKeys.add(pattern[1]);\n\t\t}\n\t\tcurNode.#methods.push({ [method]: {\n\t\t\thandler,\n\t\t\tpossibleKeys: [...possibleKeys],\n\t\t\tscore: ++order\n\t\t} });\n\t}\n\t#pushHandlerSets(handlerSets, node, method, nodeParams, params) {\n\t\tfor (let i = 0, len = node.#methods.length; i < len; i++) {\n\t\t\tconst m = node.#methods[i];\n\t\t\tconst handlerSet = m[method] || m[\"ALL\"];\n\t\t\tif (handlerSet) {\n\t\t\t\thandlerSet.params = createNullObject();\n\t\t\t\thandlerSets.push(handlerSet);\n\t\t\t\tfor (let i = 0, len = handlerSet.possibleKeys.length; i < len; i++) {\n\t\t\t\t\tconst key = handlerSet.possibleKeys[i];\n\t\t\t\t\thandlerSet.params[key] = params?.[key] && !i ? params[key] : nodeParams[key] ?? params?.[key];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tsearch(method, path) {\n\t\tconst handlerSets = [];\n\t\tthis.#params = emptyParams;\n\t\tlet curNodes = [this];\n\t\tconst parts = splitPath(path);\n\t\tconst curNodesQueue = [];\n\t\tconst len = parts.length;\n\t\tlet partOffsets = null;\n\t\tfor (let i = 0; i < len; i++) {\n\t\t\tconst part = parts[i];\n\t\t\tconst isLast = i === len - 1;\n\t\t\tconst tempNodes = [];\n\t\t\tfor (let j = 0, len2 = curNodes.length; j < len2; j++) {\n\t\t\t\tconst node = curNodes[j];\n\t\t\t\tconst nextNode = node.#children[part];\n\t\t\t\tif (nextNode) {\n\t\t\t\t\tnextNode.#params = node.#params;\n\t\t\t\t\tif (isLast) {\n\t\t\t\t\t\tif (nextNode.#children[\"*\"]) this.#pushHandlerSets(handlerSets, nextNode.#children[\"*\"], method, node.#params);\n\t\t\t\t\t\tthis.#pushHandlerSets(handlerSets, nextNode, method, node.#params);\n\t\t\t\t\t} else tempNodes.push(nextNode);\n\t\t\t\t}\n\t\t\t\tfor (const child of node.#patterns) {\n\t\t\t\t\tconst pattern = child.#pattern;\n\t\t\t\t\tconst params = node.#params === emptyParams ? {} : { ...node.#params };\n\t\t\t\t\tif (typeof pattern === \"string\") {\n\t\t\t\t\t\tif (pattern === \"*\" || part.startsWith(pattern.slice(0, -1))) {\n\t\t\t\t\t\t\tthis.#pushHandlerSets(handlerSets, child, method, node.#params);\n\t\t\t\t\t\t\tif (pattern === \"*\") {\n\t\t\t\t\t\t\t\tchild.#params = params;\n\t\t\t\t\t\t\t\ttempNodes.push(child);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst [, name, matcher] = pattern;\n\t\t\t\t\tif (!part && matcher === true) continue;\n\t\t\t\t\tif (matcher !== true) {\n\t\t\t\t\t\tif (!partOffsets) {\n\t\t\t\t\t\t\tpartOffsets = [];\n\t\t\t\t\t\t\tlet offset = path[0] === \"/\" ? 1 : 0;\n\t\t\t\t\t\t\tfor (let p = 0; p < len; p++) {\n\t\t\t\t\t\t\t\tpartOffsets[p] = offset;\n\t\t\t\t\t\t\t\toffset += parts[p].length + 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst restPathString = path.slice(partOffsets[i]);\n\t\t\t\t\t\tconst m = matcher.exec(restPathString);\n\t\t\t\t\t\tif (m) {\n\t\t\t\t\t\t\tparams[name] = m[0];\n\t\t\t\t\t\t\tthis.#pushHandlerSets(handlerSets, child, method, node.#params, params);\n\t\t\t\t\t\t\tif (m[0].length === restPathString.length && child.#children[\"*\"]) this.#pushHandlerSets(handlerSets, child.#children[\"*\"], method, node.#params, params);\n\t\t\t\t\t\t\tfor (const _ in child.#children) {\n\t\t\t\t\t\t\t\tchild.#params = params;\n\t\t\t\t\t\t\t\tconst componentCount = m[0].match(/\\//g)?.length ?? 0;\n\t\t\t\t\t\t\t\t(curNodesQueue[componentCount] ||= []).push(child);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (matcher === true || matcher.test(part)) {\n\t\t\t\t\t\tparams[name] = part;\n\t\t\t\t\t\tif (isLast) {\n\t\t\t\t\t\t\tthis.#pushHandlerSets(handlerSets, child, method, params, node.#params);\n\t\t\t\t\t\t\tif (child.#children[\"*\"]) this.#pushHandlerSets(handlerSets, child.#children[\"*\"], method, params, node.#params);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tchild.#params = params;\n\t\t\t\t\t\t\ttempNodes.push(child);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst shifted = curNodesQueue.shift();\n\t\t\tcurNodes = shifted ? tempNodes.concat(shifted) : tempNodes;\n\t\t}\n\t\tif (handlerSets[1]) handlerSets.sort((a, b) => {\n\t\t\treturn a.score - b.score;\n\t\t});\n\t\treturn [handlerSets.map(({ handler, params }) => [handler, params])];\n\t}\n};\n//#endregion\nexport { Node };\n", "import type { RequestLog } from \"./metrics.js\"\nimport type { BodyIssue } from \"./validation.js\"\n\n/** One journal entry: a request log stamped with when (on the mock clock) it was handled. */\nexport type JournalEntry = RequestLog & { at: string }\n\nexport type JournalQuery = {\n /** Only this namespace. Omit for every namespace, oldest first across all of them. */\n namespace?: string\n operationId?: string\n /** Only this HTTP method, case-insensitive. */\n method?: string\n /** Only this exact path. */\n path?: string\n /** Only requests this fault rule answered or shaped. */\n faultId?: string\n status?: number\n /** Only entries at or after this instant (epoch ms). */\n since?: number\n /** At most this many, the most recent kept. */\n limit?: number\n}\n\nexport type Journal = {\n readonly size: number\n record(entry: JournalEntry): void\n list(query?: JournalQuery): JournalEntry[]\n /** Forget one namespace's entries, or every namespace's. */\n clear(namespace?: string): void\n}\n\n/** Default number of entries each namespace keeps. */\nexport const DEFAULT_JOURNAL_SIZE = 1000\n\n/**\n * The last `size` requests per namespace, in a ring buffer: what the mock actually saw,\n * so a test can prove a request arrived (or never did) without reading logs.\n */\nexport const createJournal = (size: number = DEFAULT_JOURNAL_SIZE): Journal => {\n const capacity = Math.max(0, Math.floor(size))\n const rings = new Map<string, { entries: JournalEntry[]; next: number }>()\n let sequence = 0\n const order = new WeakMap<JournalEntry, number>()\n const inOrder = (ring: { entries: JournalEntry[]; next: number }): JournalEntry[] =>\n ring.entries.length < capacity\n ? ring.entries\n : [...ring.entries.slice(ring.next), ...ring.entries.slice(0, ring.next)]\n return {\n size: capacity,\n record(entry) {\n if (capacity === 0) return\n order.set(entry, sequence++)\n let ring = rings.get(entry.namespace)\n if (!ring) {\n ring = { entries: [], next: 0 }\n rings.set(entry.namespace, ring)\n }\n if (ring.entries.length < capacity) ring.entries.push(entry)\n else {\n ring.entries[ring.next] = entry\n ring.next = (ring.next + 1) % capacity\n }\n },\n list(query = {}) {\n const source =\n query.namespace !== undefined\n ? inOrder(rings.get(query.namespace) ?? { entries: [], next: 0 })\n : [...rings.values()]\n .flatMap(inOrder)\n .sort((a, b) => (order.get(a) ?? 0) - (order.get(b) ?? 0))\n const matched = source.filter(\n (entry) =>\n (query.operationId === undefined || entry.operationId === query.operationId) &&\n (query.method === undefined ||\n entry.method.toUpperCase() === query.method.toUpperCase()) &&\n (query.path === undefined || entry.path === query.path) &&\n (query.faultId === undefined || entry.faultId === query.faultId) &&\n (query.status === undefined || entry.status === query.status) &&\n (query.since === undefined || Date.parse(entry.at) >= query.since),\n )\n if (query.limit === undefined) return matched\n // `slice(-0)` is the whole list, so no entries has to be said outright.\n return query.limit <= 0 ? [] : matched.slice(-query.limit)\n },\n clear(namespace) {\n if (namespace === undefined) rings.clear()\n else rings.delete(namespace)\n },\n }\n}\n\n/** What a service knows about a request that the runtime cannot see from outside. */\nexport type ResponseNotes = {\n /** Node upgrade admission: actual wire status; the Fetch carrier remains 200. */\n wireStatus?: 101\n /** Resource ids the handler touched, e.g. `{ userId, orderId }`. */\n ids?: Record<string, string>\n /** Set when the handler created a resource the request referred to but did not exist. */\n adopted?: boolean\n /** The body validation issues behind a rejection; the runtime logs them, never the body. */\n issues?: BodyIssue[]\n}\n\nconst notes = new WeakMap<Response, ResponseNotes>()\n\n/**\n * Attach notes to a response for the request journal and structured log. They travel\n * beside the response, never in it, so nothing the vendor would not send reaches a client.\n */\nexport const annotateResponse = (response: Response, extra: ResponseNotes): Response => {\n const existing = notes.get(response)\n notes.set(response, {\n ...existing,\n ...extra,\n ...(existing?.ids || extra.ids ? { ids: { ...existing?.ids, ...extra.ids } } : {}),\n })\n return response\n}\n\nexport const responseNotes = (response: Response): ResponseNotes | undefined => notes.get(response)\n", "import type { Operation } from \"@crvouga/mockingbird-openapi\"\nimport { operationMetadata } from \"@crvouga/mockingbird-openapi-metadata\"\n\n/** Compile the same explicit terminal-tail contract for dispatch and observation. */\nexport const operationPath = (operation: Operation) => {\n const tail = operationMetadata(operation.operation).path\n if (\n tail &&\n (typeof tail.parameter !== \"string\" ||\n !tail.parameter ||\n !operation.path.endsWith(`/{${tail.parameter}}`) ||\n (tail.allowEmpty !== undefined && typeof tail.allowEmpty !== \"boolean\"))\n )\n throw new Error(`Invalid path metadata for ${operation.operationId}`)\n const segments = operation.path.split(\"/\")\n const ordinary = (segment: string) =>\n segment\n .split(/(\\{[^}]+\\})/)\n .map((part) =>\n /^\\{[^}]+\\}$/.test(part) ? \"[^/]+?\" : part.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"),\n )\n .join(\"\")\n const hono = operation.path.replace(/\\{([^}]+)\\}/g, (_, name: string) =>\n name === tail?.parameter ? `:${name}{.+}` : `:${name}`,\n )\n const prefix = tail ? segments.slice(0, -1).map(ordinary).join(\"/\") : undefined\n const pattern = tail\n ? `${prefix}${tail.allowEmpty ? \"(?:/.*)?\" : \"/.+\"}`\n : segments.map(ordinary).join(\"/\")\n const routes = [hono]\n if (tail?.allowEmpty) {\n const base = operation.path\n .slice(0, -`/{${tail.parameter}}`.length)\n .replace(/\\{([^}]+)\\}/g, \":$1\")\n routes.push(base, `${base}/`)\n }\n return {\n routes,\n pattern: new RegExp(`^${pattern}/?$`),\n emptyParameter: tail?.allowEmpty ? tail.parameter : undefined,\n }\n}\n", "import type { FetchAPI } from \"@crvouga/mockingbird-core\"\nimport {\n type DecodedBody,\n decodeFormPairs,\n type FormObject,\n readBody,\n} from \"@crvouga/mockingbird-http-codec\"\nimport { listOperations, type OpenAPIDocument, type Operation } from \"@crvouga/mockingbird-openapi\"\nimport { operationMetadata } from \"@crvouga/mockingbird-openapi-metadata\"\nimport {\n clearNamespace,\n migrateCore,\n resolveSqlite,\n type SqliteClient,\n} from \"@crvouga/mockingbird-sqlite\"\nimport { type Context, Hono } from \"hono\"\nimport { annotateResponse } from \"./journal.js\"\nimport { operationPath } from \"./path.js\"\nimport { recordedIssues } from \"./validation.js\"\n\n/** A rejection carries the issues `bodyIssues` found, for the runtime's log entry. */\nconst withIssues = (request: Request, response: Response): Response => {\n const issues = response.status >= 400 ? recordedIssues(request) : undefined\n return issues && issues.length > 0 ? annotateResponse(response, { issues }) : response\n}\n\n/** Options every provider constructor accepts. */\nexport type APIOptions = {\n /** Sync SQLite client. Defaults to `@crvouga/mockingbird-service-sqlite`. */\n sqlite?: SqliteClient\n /** Clock used for `created`-style fields. Default `Date.now`. */\n now?: () => number\n /**\n * Storage namespace for this instance's records. Instances sharing one SQLite\n * client stay isolated when their namespaces differ. Defaults to the service name.\n */\n namespace?: string\n}\n\nexport type OperationContext = {\n request: Request\n url: URL\n /** Path parameters. */\n params: Record<string, string>\n /** Query string decoded with bracket notation (`created[gte]=1` -> `{ created: { gte: \"1\" } }`). */\n query: FormObject\n body: DecodedBody\n /** Shared SQLite client for this service (already migrated). */\n sqlite: SqliteClient\n /** Service namespace used for records / sequences. */\n namespace: string\n operation: Operation\n /** The vendor contract the service was built from. */\n document: OpenAPIDocument\n now: () => number\n}\n\nexport type OperationHandler = (context: OperationContext) => Promise<Response> | Response\n\nexport type OperationHandlers = Record<string, OperationHandler>\n\n/** Identity helper that keeps handler maps type-checked against a fixed set of operation ids. */\nexport const defineOperations = <Id extends string>(\n handlers: Record<Id, OperationHandler>,\n): Record<Id, OperationHandler> => handlers\n\nexport class OperationRegistryError extends Error {\n constructor(readonly problems: string[]) {\n super(`operation registry is inconsistent:\\n${problems.map((p) => ` - ${p}`).join(\"\\n\")}`)\n this.name = \"OperationRegistryError\"\n }\n}\n\n/**\n * Cross-check handlers against the document: every supported operation needs exactly one\n * handler, no handler may target an unknown or unsupported operation, no duplicate ids.\n */\nexport const verifyOperations = (\n document: OpenAPIDocument,\n handlers: OperationHandlers,\n): string[] => {\n const problems: string[] = []\n const operations = listOperations(document)\n const seen = new Set<string>()\n for (const operation of operations) {\n if (seen.has(operation.operationId))\n problems.push(`duplicate operationId ${operation.operationId}`)\n seen.add(operation.operationId)\n const supported = operationMetadata(operation.operation).supported\n const handler = handlers[operation.operationId]\n if (supported && !handler)\n problems.push(`supported operation ${operation.operationId} has no handler`)\n if (!supported && handler)\n problems.push(`operation ${operation.operationId} is marked unsupported but has a handler`)\n }\n for (const id of Object.keys(handlers)) {\n if (!seen.has(id)) problems.push(`handler ${id} has no OpenAPI operation`)\n }\n return problems\n}\n\nexport type ServiceOptions = {\n document: OpenAPIDocument\n handlers: OperationHandlers\n sqlite: SqliteClient\n /** Namespace isolating this service's records and sequences. */\n namespace: string\n now?: (() => number) | undefined\n /** Response for paths/methods outside the contract. */\n notFound: (request: Request) => Response | Promise<Response>\n /** Response for operations declared but marked `supported: false`. Default: `notFound`. */\n unsupported?: (request: Request, operation: Operation) => Response | Promise<Response>\n /** Convert handler exceptions into a provider-shaped response. */\n onError: (error: unknown, request: Request) => Response | Promise<Response>\n /** Runs before every operation; return a Response to short-circuit (e.g. authentication). */\n before?: (context: OperationContext) => Promise<Response | undefined> | Response | undefined\n}\n\nexport type Service = FetchAPI & {\n app: Hono\n sqlite: SqliteClient\n namespace: string\n /** Delete every record and sequence in the service namespace. */\n reset(): Promise<void>\n}\n\nconst escapePattern = (value: string): string => value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n/** Hono treats `:id:action` as one parameter. Match embedded OpenAPI parameters\n * with a segment regex, then extract only the template's parameter values. */\nconst serviceRoute = (template: string) => {\n const names: string[] = []\n let pattern = \"\",\n end = 0\n for (const match of template.matchAll(/\\{([^}]+)\\}/g)) {\n pattern += `${escapePattern(template.slice(end, match.index))}([^/]+?)`\n const name = match[1]\n if (!name) throw new Error(`Invalid OpenAPI route template: ${template}`)\n names.push(name)\n end = match.index + match[0].length\n }\n pattern += escapePattern(template.slice(end))\n const matcher = new RegExp(`^${pattern}$`)\n const path = template\n .split(\"/\")\n .map((segment, index) => {\n if (!segment.includes(\"{\")) return segment\n const literal = /^\\{([^}]+)\\}$/.exec(segment)\n if (literal) return `:${literal[1]}`\n let expression = \"\",\n offset = 0\n for (const match of segment.matchAll(/\\{[^}]+\\}/g)) {\n expression += `${escapePattern(segment.slice(offset, match.index))}[^/]+?`\n offset = match.index + match[0].length\n }\n expression += escapePattern(segment.slice(offset))\n return `:mockingbirdSegment${index}{${expression}}`\n })\n .join(\"/\")\n return {\n path,\n params: (pathname: string): Record<string, string> => {\n const values = matcher.exec(pathname)\n return Object.fromEntries(\n names.map((name, index) => [name, decodeURIComponent(values?.[index + 1] ?? \"\")]),\n )\n },\n }\n}\n\n/** Static segments before parameters so `/v1/customers/search` beats `/v1/customers/:id`. */\nconst routeOrder = (a: Operation, b: Operation) => {\n const sa = a.path.split(\"/\")\n const sb = b.path.split(\"/\")\n for (let i = 0; i < Math.max(sa.length, sb.length); i++) {\n const x = sa[i] ?? \"\"\n const y = sb[i] ?? \"\"\n const px = x.startsWith(\"{\")\n const py = y.startsWith(\"{\")\n if (px !== py) return px ? 1 : -1\n if (x !== y) return x < y ? -1 : 1\n }\n return 0\n}\n\nconst queryOf = (url: URL): FormObject => decodeFormPairs(url.searchParams.entries())\n\n/**\n * Resolve optional `sqlite`, run core migrations, and return the ready client.\n * Call this from every provider constructor before building state.\n */\nexport const bootSqlite = (sqlite?: SqliteClient): SqliteClient => {\n const client = resolveSqlite(sqlite)\n migrateCore(client)\n return client\n}\n\n/** Build a Fetch-native service whose routes are exactly the document's operations. */\nexport const createService = (options: ServiceOptions): Service => {\n const problems = verifyOperations(options.document, options.handlers)\n if (problems.length > 0) throw new OperationRegistryError(problems)\n migrateCore(options.sqlite)\n const now = options.now ?? (() => Date.now())\n const app = new Hono()\n app.notFound((c) => options.notFound(c.req.raw))\n app.onError((error, c) => options.onError(error, c.req.raw))\n\n const operations = [...listOperations(options.document)].sort(routeOrder)\n for (const operation of operations) {\n const path = operationPath(operation)\n const metadata = operationMetadata(operation.operation)\n const handler = options.handlers[operation.operationId]\n const registeredRoute = serviceRoute(operation.path)\n const route = async (c: Context) => {\n const request = c.req.raw\n if (!metadata.supported || !handler) {\n return options.unsupported\n ? options.unsupported(request, operation)\n : options.notFound(request)\n }\n const url = new URL(request.url)\n const context: OperationContext = {\n request,\n url,\n params: metadata.path\n ? { ...(path.emptyParameter ? { [path.emptyParameter]: \"\" } : {}), ...c.req.param() }\n : registeredRoute.params(url.pathname),\n query: queryOf(url),\n body: await readBody(request),\n sqlite: options.sqlite,\n namespace: options.namespace,\n operation,\n document: options.document,\n now,\n }\n const short = await options.before?.(context)\n return withIssues(request, short ?? (await handler(context)))\n }\n app.on(\n operation.method.toUpperCase(),\n metadata.path ? path.routes : [registeredRoute.path],\n route,\n )\n }\n\n return {\n app,\n sqlite: options.sqlite,\n namespace: options.namespace,\n fetch: async (request) => app.fetch(request),\n reset: async () => {\n clearNamespace(options.sqlite, options.namespace)\n },\n }\n}\n", "import { clearNamespace, type SqliteClient } from \"@crvouga/mockingbird-sqlite\"\nimport { awsParseXml, awsXml } from \"./aws-xml.js\"\nimport { Collection } from \"./collection.js\"\nimport { IdSequence } from \"./ids.js\"\nimport { type APIOptions, bootSqlite } from \"./service.js\"\n\nexport type AwsInput = Record<string, unknown>\nexport class AwsError extends Error {\n constructor(\n readonly code: string,\n message: string,\n readonly status = 400,\n ) {\n super(message)\n }\n}\nexport type AwsProtocolOptions = APIOptions & { region?: string; accountId?: string }\nexport type AwsOperation = { operation: string; input: AwsInput; request: Request; url: URL }\nexport const awsRecord = (value: unknown): AwsInput =>\n typeof value === \"object\" && value !== null && !Array.isArray(value) ? (value as AwsInput) : {}\nexport const awsList = (value: unknown): unknown[] =>\n Array.isArray(value) ? value : value === undefined || value === null ? [] : [value]\nexport const awsRequired = (input: AwsInput, key: string): string => {\n if (typeof input[key] !== \"string\" || !(input[key] as string).length)\n throw new AwsError(\"ValidationException\", `${key} is required`)\n return input[key] as string\n}\nexport const awsPage = <T>(\n values: T[],\n input: AwsInput,\n tokenKey = \"NextToken\",\n limitKey = \"MaxResults\",\n) => {\n const offset = Number(input[tokenKey] ?? 0),\n max = Number(input[limitKey] ?? 100)\n if (!Number.isInteger(offset) || offset < 0 || !Number.isInteger(max) || max < 1 || max > 10000)\n throw new AwsError(\"InvalidParameterException\", \"Invalid pagination\")\n return {\n items: values.slice(offset, offset + max),\n ...(offset + max < values.length ? { token: String(offset + max) } : {}),\n }\n}\n\n/** Fetch-native AWS wire transport. Service subclasses own operations and persisted state. */\nexport abstract class AwsProtocolAPI {\n readonly sqlite: SqliteClient\n readonly namespace: string\n readonly now: () => number\n readonly region: string\n readonly accountId: string\n readonly ids: IdSequence\n private readonly collections = new Map<string, Collection<AwsInput>>()\n constructor(\n readonly service: string,\n options: AwsProtocolOptions = {},\n ) {\n this.sqlite = bootSqlite(options.sqlite)\n this.namespace = options.namespace ?? service\n this.now = options.now ?? Date.now\n this.region = options.region ?? \"us-east-1\"\n this.accountId = options.accountId ?? \"000000000000\"\n this.ids = new IdSequence(this.sqlite, this.namespace, service)\n }\n collection(name: string): Collection<AwsInput> {\n let collection = this.collections.get(name)\n if (!collection) {\n collection = new Collection(\n this.sqlite,\n this.namespace,\n `${this.service.replace(/-/g, \"_\")}_${name}`,\n )\n this.collections.set(name, collection)\n }\n return collection\n }\n arn(type: string, name: string, service = this.service) {\n return `arn:aws:${service}:${this.region}:${this.accountId}:${type}${name}`\n }\n async reset() {\n clearNamespace(this.sqlite, this.namespace)\n }\n abstract dispatch(context: AwsOperation): unknown | Promise<unknown>\n route(_method: string, _pathname: string): { operation: string; params: AwsInput } | undefined {\n return undefined\n }\n async fetch(request: Request): Promise<Response> {\n const url = new URL(request.url)\n const requestId = this.ids.next(\"req-\", 32)\n let query = false\n let operation = \"\"\n try {\n let input: AwsInput = {}\n const route = this.route(request.method, url.pathname)\n const target = request.headers.get(\"x-amz-target\")\n if (target) {\n operation = target.split(\".\").at(-1) ?? \"\"\n input = awsRecord(await request.json())\n } else if (route) {\n operation = route.operation\n const raw =\n request.method === \"GET\" || request.method === \"DELETE\" || request.method === \"HEAD\"\n ? \"\"\n : await request.text()\n input = raw\n ? request.headers.get(\"content-type\")?.includes(\"xml\")\n ? awsParseXml(raw)\n : awsRecord(JSON.parse(raw))\n : {}\n Object.assign(input, Object.fromEntries(url.searchParams), route.params)\n } else {\n const params = new URLSearchParams(\n request.method === \"GET\" ? url.search : await request.text(),\n )\n operation = params.get(\"Action\") ?? \"\"\n query = true\n input = decodeAwsQuery(params)\n }\n if (!operation) throw new AwsError(\"UnknownOperationException\", \"Unknown operation\", 400)\n const result = await this.dispatch({ operation, input, request, url })\n if (result instanceof Response) return result\n const headers = { \"x-amzn-requestid\": requestId, \"x-amz-request-id\": requestId }\n if (query) {\n const ec2 = this.service === \"ec2\"\n return new Response(\n ec2\n ? `<${operation}Response xmlns=\"http://ec2.amazonaws.com/doc/2016-11-15/\"><requestId>${requestId}</requestId>${awsXml(result, \"item\")}</${operation}Response>`\n : `<${operation}Response><${operation}Result>${awsXml(result)}</${operation}Result><ResponseMetadata><RequestId>${requestId}</RequestId></ResponseMetadata></${operation}Response>`,\n { headers: { ...headers, \"content-type\": \"text/xml\" } },\n )\n }\n return new Response(JSON.stringify(result ?? {}), {\n headers: {\n ...headers,\n \"content-type\": target\n ? (request.headers.get(\"content-type\") ?? \"application/x-amz-json-1.1\")\n : \"application/json\",\n },\n })\n } catch (error) {\n const failure =\n error instanceof AwsError\n ? error\n : new AwsError(\n error instanceof SyntaxError ? \"SerializationException\" : \"ValidationException\",\n error instanceof Error ? error.message : \"Invalid request\",\n )\n if (query)\n return new Response(\n `<ErrorResponse><Error><Type>Sender</Type><Code>${awsXml(failure.code)}</Code><Message>${awsXml(failure.message)}</Message></Error><RequestId>${requestId}</RequestId></ErrorResponse>`,\n { status: failure.status, headers: { \"content-type\": \"text/xml\" } },\n )\n return new Response(\n JSON.stringify({\n __type: failure.code,\n message: failure.message,\n Message: failure.message,\n }),\n {\n status: failure.status,\n headers: {\n \"content-type\": \"application/x-amz-json-1.1\",\n \"x-amzn-errortype\": failure.code,\n \"x-amzn-requestid\": requestId,\n },\n },\n )\n }\n }\n unsupported(operation: string): never {\n throw new AwsError(\"UnknownOperationException\", `Unsupported operation ${operation}`)\n }\n get(collection: string, id: string, code = \"ResourceNotFoundException\") {\n const value = this.collection(collection).get(id)\n if (!value) throw new AwsError(code, `Resource ${id} does not exist`)\n return value\n }\n}\n\nexport function decodeAwsQuery(params: URLSearchParams): AwsInput {\n const result: AwsInput = {}\n for (const [key, value] of params) {\n if (key === \"Action\" || key === \"Version\") continue\n const parts = key.split(\".\").filter((part) => part !== \"member\")\n let current: AwsInput | unknown[] = result\n for (let index = 0; index < parts.length; index++) {\n const part = parts[index] as string\n const numeric = /^\\d+$/.test(part)\n const slot = numeric ? Number(part) - 1 : part\n const object = current as AwsInput\n if (index === parts.length - 1) object[slot] = value\n else {\n const array = /^\\d+$/.test(parts[index + 1] ?? \"\") || parts[index + 1] === \"member\"\n if (!object[slot]) object[slot] = array ? [] : {}\n current = object[slot] as AwsInput | unknown[]\n }\n }\n }\n return result\n}\n", "/**\n * The single source of time for a service.\n *\n * Every timestamp a mock writes reads from here, so a suite moves time instead of\n * sleeping: appointment windows, result delays and expiries become reachable in\n * milliseconds. A frozen clock also makes timestamps reproducible from a seed.\n */\nexport type ClockState = {\n /** Current epoch milliseconds. */\n now: number\n /** True while time does not advance on its own. */\n frozen: boolean\n /** Milliseconds a running clock adds to its underlying source. `0` while frozen. */\n offsetMs: number\n}\n\nexport type Clock = {\n now(): number\n /** Pin the clock to an exact instant, keeping it frozen if it already was. */\n set(epochMs: number): void\n /** Move the clock forward, or back with a negative delta. */\n advance(deltaMs: number): void\n /** Stop time at the current instant. */\n freeze(): void\n /** Resume from the current instant. */\n unfreeze(): void\n /** Drop back to the underlying source, live. */\n reset(): void\n state(): ClockState\n}\n\n/** A {@link Clock} over `source` (default `Date.now`), live and unfrozen. */\nexport const createClock = (source: () => number = Date.now): Clock => {\n let offsetMs = 0\n let frozenAt: number | undefined\n const now = () => frozenAt ?? source() + offsetMs\n return {\n now,\n set: (epochMs) => {\n if (frozenAt !== undefined) frozenAt = epochMs\n else offsetMs = epochMs - source()\n },\n advance: (deltaMs) => {\n if (frozenAt !== undefined) frozenAt += deltaMs\n else offsetMs += deltaMs\n },\n freeze: () => {\n frozenAt = now()\n },\n unfreeze: () => {\n if (frozenAt === undefined) return\n offsetMs = frozenAt - source()\n frozenAt = undefined\n },\n reset: () => {\n offsetMs = 0\n frozenAt = undefined\n },\n // A frozen clock does not follow its source, so it has no offset to report.\n state: () => ({\n now: now(),\n frozen: frozenAt !== undefined,\n offsetMs: frozenAt !== undefined ? 0 : offsetMs,\n }),\n }\n}\n\n/** A clock over a base clock, which can tell its own freeze from the base's. */\nexport type DerivedClock = Clock & {\n /** True while this clock itself is frozen, and so no longer follows the base. */\n pinned(): boolean\n /** Put the clock at an instant: pinned there, or following the base from there. */\n place(state: { now: number; pinned: boolean }): void\n}\n\n/**\n * A clock that follows `base` \u2014 its time, its freezes, its jumps \u2014 plus an offset and a\n * freeze of its own. Moving it never moves `base`, so a namespace can travel in time alone.\n * It reports `frozen` while either clock is, and no offset while it stands still. `moved` is\n * called after anything moves it, for whatever keeps a schedule by this clock.\n */\nexport const deriveClock = (base: Clock, moved: () => void = () => {}): DerivedClock => {\n const own = createClock(() => base.now())\n /** Tell whoever is driven by this clock that its time is no longer what it was. */\n const moving =\n <A extends unknown[]>(change: (...args: A) => void) =>\n (...args: A): void => {\n change(...args)\n moved()\n }\n return {\n ...own,\n set: moving(own.set),\n advance: moving(own.advance),\n reset: moving(own.reset),\n state: () => {\n const state = own.state()\n const frozen = state.frozen || base.state().frozen\n return { now: state.now, frozen, offsetMs: frozen ? 0 : state.offsetMs }\n },\n pinned: () => own.state().frozen,\n place: moving(({ now, pinned }) => {\n own.reset()\n // Frozen first, so the instant is set exactly instead of read back from the base.\n if (pinned) own.freeze()\n own.set(now)\n }),\n }\n}\n\n/**\n * Put a clock at an instant, frozen or running. Frozen first, so the instant is set exactly:\n * setting a live clock and freezing it afterwards reads the source again and can land a tick late.\n */\nexport const restoreClock = (clock: Clock, state: { now: number; frozen: boolean }): void => {\n clock.freeze()\n clock.set(state.now)\n if (!state.frozen) clock.unfreeze()\n}\n", "import type { FaultRule } from \"./faults.js\"\n\n/**\n * The admin controls every mock shares, as one document.\n *\n * The same shape is accepted in three places, and means the same thing in each:\n *\n * - at boot: `createRuntime({ adminControls })`, `serve --admin-controls`,\n * `MOCKINGBIRD_ADMIN_CONTROLS`\n * - over HTTP: `PUT /__admin/controls`\n * - per request: the `x-mockingbird-*` headers in {@link CONTROL_HEADERS}\n *\n * Every control is deterministic: given the same seed, clock and requests, a mock answers\n * the same bytes. Nothing here reads the wall clock or `Math.random`.\n */\n\n/** Milliseconds, or a string like `\"250ms\"`, `\"2s\"`, `\"15m\"`, `\"1h\"`, `\"3d\"`. */\nexport type Duration = number | string\n/** Epoch milliseconds, or an ISO-8601 string. */\nexport type Instant = number | string\n\n/** A control that cannot be applied: a bad value, an unknown key, a missing snapshot. */\nexport class ControlError extends RangeError {\n constructor(message: string) {\n super(message)\n this.name = \"ControlError\"\n }\n}\n\nconst UNITS: Record<string, number> = {\n ms: 1,\n s: 1000,\n m: 60_000,\n h: 3_600_000,\n d: 86_400_000,\n}\n\n/** Milliseconds from a number, a numeric string, or a duration like `\"90s\"`, `\"15m\"`, `\"2h\"`. */\nexport const parseDuration = (value: unknown): number | undefined => {\n if (typeof value === \"number\") return Number.isFinite(value) ? value : undefined\n if (typeof value !== \"string\") return undefined\n const match = /^(-?\\d+(?:\\.\\d+)?)\\s*(ms|s|m|h|d)?$/.exec(value.trim())\n if (!match) return undefined\n return Number(match[1]) * (UNITS[match[2] ?? \"ms\"] as number)\n}\n\n/** Epoch milliseconds from a number, a string of digits, or an ISO-8601 string. */\nexport const parseInstant = (value: unknown): number | undefined => {\n if (typeof value === \"number\") return Number.isFinite(value) ? value : undefined\n if (typeof value !== \"string\") return undefined\n const text = value.trim()\n if (/^-?\\d+$/.test(text)) return Number(text)\n const parsed = Date.parse(text)\n return Number.isNaN(parsed) ? undefined : parsed\n}\n\n/** {@link parseDuration}, or a {@link ControlError} naming `label`. Negative only when allowed. */\nexport const durationMs = (value: unknown, label: string, negative = false): number => {\n const parsed = parseDuration(value)\n if (parsed === undefined)\n throw new ControlError(`${label}: expected milliseconds or a duration like \"250ms\" or \"15m\"`)\n if (!negative && parsed < 0) throw new ControlError(`${label}: must not be negative`)\n return parsed\n}\n\n/** {@link parseInstant}, or a {@link ControlError} naming `label`. */\nexport const instantMs = (value: unknown, label: string): number => {\n const parsed = parseInstant(value)\n if (parsed === undefined) throw new ControlError(`${label}: expected epoch ms or ISO-8601`)\n return parsed\n}\n\n/** A string of digits is that number, so `--seed 7`, `{\"seed\": 7}` and a header agree. */\nexport const normalizeSeed = (seed: unknown, label = \"seed\"): number | string => {\n if (typeof seed === \"number\" && Number.isFinite(seed)) return seed\n if (typeof seed === \"string\" && seed !== \"\") return /^\\d+$/.test(seed) ? Number(seed) : seed\n throw new ControlError(`${label}: expected a number or a non-empty string`)\n}\n\nexport type ClockControls = {\n /** Move the clock to this instant. */\n now?: Instant\n /** Stop time. A frozen clock moves only when told to, so timestamps replay exactly. */\n frozen?: boolean\n /**\n * Step the clock forward by this much before every vendor request. With a frozen clock\n * each request still gets its own, reproducible timestamp.\n */\n autoAdvance?: Duration\n}\n\n/** How long a response takes: a fixed delay plus seeded jitter in `[0, jitter]`. */\nexport type LatencyRuleInput = { delay?: Duration; jitter?: Duration }\n\nexport type LatencyControls = LatencyRuleInput & {\n /** Per-operation overrides, keyed by operationId. A bare duration is its `delay`. */\n operations?: Record<string, Duration | LatencyRuleInput>\n}\n\n/** A fault to add: a rule (the id is assigned when omitted), or a named preset with overrides. */\nexport type FaultInput =\n | (Omit<FaultRule, \"id\"> & { id?: string })\n | ({ preset: string } & Partial<FaultRule>)\n\n/** Identifies a {@link SnapshotDocument}. */\nexport const SNAPSHOT_FORMAT = \"mockingbird.snapshot/v1\"\n\n/**\n * A namespace, as portable JSON: what `GET /__admin/snapshots/:id` returns and what\n * `PUT /__admin/snapshots/:id` and the boot `snapshot` control accept. Only `format` and\n * `records` are required, so a hand-written seed file is a valid snapshot.\n */\nexport type SnapshotDocument = {\n format: typeof SNAPSHOT_FORMAT\n /** The service that wrote it. A snapshot is rejected by any other service. */\n service?: string\n /**\n * Stored rows. `seq` orders a collection; omitted, rows keep their listed order. `raw` is\n * the stored text of a row that is not a plain record, and replaces `value` when present.\n */\n records: { collection: string; id: string; seq?: number; value?: unknown; raw?: string }[]\n /** Id counters, so the next generated id continues where the snapshot left off. */\n sequences?: { name: string; kind: string; value: number }[]\n clock?: { now: number; frozen: boolean; autoAdvanceMs?: number }\n seed?: number | string\n /** Positions of the seeded random streams. */\n rng?: { state: number; faults?: number; latency?: number }\n faults?: unknown\n latency?: unknown\n virtualTime?: boolean\n /** Quiescent webhook endpoints, delivery history and fault state. Contains private configuration. */\n webhooks?: unknown\n}\n\n/** Controls for one namespace. */\nexport type NamespaceControls = {\n /** Seeds every random choice: fault rates, jitter, and whatever the service invents. */\n seed?: number | string\n clock?: ClockControls\n /**\n * Spend injected waits (latency, fault delays, timeouts) on the mock clock instead of the\n * wall clock: the request returns at once, the clock has moved, and the journal records\n * the wait exactly. Default `false`: waits are real, so a client's own timeout can fire.\n */\n virtualTime?: boolean\n /** Baseline response time for every vendor request. A bare duration is its `delay`. */\n latency?: Duration | LatencyControls\n faults?: readonly FaultInput[]\n /** Start from this state instead of the service's own seed data. */\n snapshot?: SnapshotDocument\n}\n\n/** {@link NamespaceControls} for every namespace, with per-namespace overrides. */\nexport type MockControls = NamespaceControls & {\n /** Vendor credential \u2192 namespace, for SDKs that cannot send a namespace header. */\n credentials?: Record<string, string>\n /** Overrides for named namespaces. A key given here replaces the shared value. */\n namespaces?: Record<string, NamespaceControls>\n}\n\nconst NAMESPACE_KEYS = new Set([\"seed\", \"clock\", \"virtualTime\", \"latency\", \"faults\", \"snapshot\"])\nconst MOCK_KEYS = new Set([...NAMESPACE_KEYS, \"credentials\", \"namespaces\"])\n/**\n * What `GET /__admin/controls` reports beside the controls themselves. Accepted and ignored,\n * so what was read from one namespace can be applied to another as it is.\n */\nconst REPORTED_KEYS = new Set([\"namespace\", \"snapshots\"])\nconst REPORTED_CLOCK_KEYS = new Set([\"iso\", \"offsetMs\"])\n\n/** What a namespace, a branch, a snapshot and a fault's namespace may be called. */\nexport const KEY_PATTERN = /^[A-Za-z0-9_.-]{1,64}$/\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n\nconst unknownKeys = (\n value: Record<string, unknown>,\n known: Set<string>,\n label: string,\n reported?: Set<string>,\n): void => {\n for (const key of Object.keys(value)) {\n if (!known.has(key) && !reported?.has(key))\n throw new ControlError(\n `${label}: unknown control ${JSON.stringify(key)}; expected ${[...known].join(\", \")}`,\n )\n }\n}\n\n/** A latency rule in milliseconds. */\nexport type LatencyRule = { delayMs: number; jitterMs: number }\n/** Baseline latency for a namespace, normalized. */\nexport type LatencyState = LatencyRule & { operations: Record<string, LatencyRule> }\n\nconst latencyRule = (value: unknown, label: string): LatencyRule => {\n if (!isRecord(value)) return { delayMs: durationMs(value, label), jitterMs: 0 }\n unknownKeys(value, new Set([\"delay\", \"jitter\", \"delayMs\", \"jitterMs\", \"operations\"]), label)\n return {\n delayMs: durationMs(value.delay ?? value.delayMs ?? 0, `${label}.delay`),\n jitterMs: durationMs(value.jitter ?? value.jitterMs ?? 0, `${label}.jitter`),\n }\n}\n\n/** Validate and normalize a `latency` control. */\nexport const normalizeLatency = (value: unknown, label = \"latency\"): LatencyState => {\n const base = latencyRule(value, label)\n const operations: Record<string, LatencyRule> = {}\n if (isRecord(value) && value.operations !== undefined) {\n if (!isRecord(value.operations))\n throw new ControlError(`${label}.operations: expected an object keyed by operationId`)\n for (const [operationId, rule] of Object.entries(value.operations)) {\n if (isRecord(rule) && rule.operations !== undefined)\n throw new ControlError(`${label}.operations.${operationId}: cannot nest operations`)\n operations[operationId] = latencyRule(rule, `${label}.operations.${operationId}`)\n }\n }\n return { ...base, operations }\n}\n\n/** A clock control, normalized. Absent keys leave that part of the clock alone. */\nexport type ClockPlan = { now?: number; frozen?: boolean; autoAdvanceMs?: number }\n\n/** Validate and normalize a `clock` control. Accepts the `POST /clock` spellings too. */\nexport const normalizeClock = (value: unknown, label = \"clock\"): ClockPlan => {\n if (!isRecord(value)) throw new ControlError(`${label}: expected an object`)\n unknownKeys(\n value,\n new Set([\"now\", \"set\", \"frozen\", \"freeze\", \"autoAdvance\", \"autoAdvanceMs\"]),\n label,\n REPORTED_CLOCK_KEYS,\n )\n const plan: ClockPlan = {}\n const now = value.now ?? value.set\n if (now !== undefined) plan.now = instantMs(now, `${label}.now`)\n const frozen = value.frozen ?? value.freeze\n if (frozen !== undefined) {\n if (typeof frozen !== \"boolean\") throw new ControlError(`${label}.frozen: expected a boolean`)\n plan.frozen = frozen\n }\n const auto = value.autoAdvance ?? value.autoAdvanceMs\n if (auto !== undefined) plan.autoAdvanceMs = durationMs(auto, `${label}.autoAdvance`)\n return plan\n}\n\n/** {@link NamespaceControls} with every value checked and every duration in milliseconds. */\nexport type ControlPlan = {\n seed?: number | string\n clock?: ClockPlan\n virtualTime?: boolean\n latency?: LatencyState\n faults?: readonly FaultInput[]\n snapshot?: SnapshotDocument\n}\n\n/** Check a snapshot document's shape. The runtime checks `service` when it restores one. */\nexport const assertSnapshotDocument = (value: unknown, label = \"snapshot\"): SnapshotDocument => {\n if (!isRecord(value)) throw new ControlError(`${label}: expected a snapshot document`)\n if (value.format !== SNAPSHOT_FORMAT)\n throw new ControlError(`${label}.format: expected ${JSON.stringify(SNAPSHOT_FORMAT)}`)\n if (!Array.isArray(value.records)) throw new ControlError(`${label}.records: expected a list`)\n value.records.forEach((row: unknown, index: number) => {\n if (\n !isRecord(row) ||\n typeof row.collection !== \"string\" ||\n typeof row.id !== \"string\" ||\n (row.value === undefined && typeof row.raw !== \"string\") ||\n (row.seq !== undefined && !Number.isSafeInteger(row.seq))\n )\n throw new ControlError(`${label}.records[${index}]: expected {collection, id, value, seq?}`)\n })\n if (value.sequences !== undefined) {\n if (!Array.isArray(value.sequences))\n throw new ControlError(`${label}.sequences: expected a list`)\n value.sequences.forEach((row: unknown, index: number) => {\n if (\n !isRecord(row) ||\n typeof row.name !== \"string\" ||\n typeof row.kind !== \"string\" ||\n !Number.isSafeInteger(row.value)\n )\n throw new ControlError(`${label}.sequences[${index}]: expected {name, kind, value}`)\n })\n }\n if (value.clock !== undefined) {\n if (\n !isRecord(value.clock) ||\n typeof value.clock.now !== \"number\" ||\n !Number.isFinite(value.clock.now) ||\n typeof value.clock.frozen !== \"boolean\"\n )\n throw new ControlError(`${label}.clock: expected {now, frozen}`)\n }\n return value as SnapshotDocument\n}\n\n/** Validate one namespace's controls. Fault rules are checked when they are added. */\nexport const normalizeControls = (value: unknown, label = \"controls\"): ControlPlan => {\n if (!isRecord(value)) throw new ControlError(`${label}: expected an object`)\n unknownKeys(value, NAMESPACE_KEYS, label, REPORTED_KEYS)\n const plan: ControlPlan = {}\n if (value.seed !== undefined) plan.seed = normalizeSeed(value.seed, `${label}.seed`)\n if (value.clock !== undefined) plan.clock = normalizeClock(value.clock, `${label}.clock`)\n if (value.virtualTime !== undefined) {\n if (typeof value.virtualTime !== \"boolean\")\n throw new ControlError(`${label}.virtualTime: expected a boolean`)\n plan.virtualTime = value.virtualTime\n }\n if (value.latency !== undefined)\n plan.latency = normalizeLatency(value.latency, `${label}.latency`)\n if (value.faults !== undefined) {\n if (!Array.isArray(value.faults) || !value.faults.every(isRecord))\n throw new ControlError(`${label}.faults: expected a list of fault rules`)\n plan.faults = value.faults as FaultInput[]\n }\n if (value.snapshot !== undefined)\n plan.snapshot = assertSnapshotDocument(value.snapshot, `${label}.snapshot`)\n return plan\n}\n\n/** Boot controls, checked once when the runtime is created. */\nexport type BootPlan = {\n shared: ControlPlan\n namespaces: Record<string, ControlPlan>\n credentials: Record<string, string>\n}\n\n/** Validate a boot {@link MockControls} document. */\nexport const normalizeBootControls = (value: unknown, label = \"controls\"): BootPlan => {\n if (value === undefined) return { shared: {}, namespaces: {}, credentials: {} }\n if (!isRecord(value)) throw new ControlError(`${label}: expected an object`)\n unknownKeys(value, MOCK_KEYS, label)\n const { credentials, namespaces, ...shared } = value\n const plan: BootPlan = {\n shared: normalizeControls(shared, label),\n namespaces: {},\n credentials: {},\n }\n if (namespaces !== undefined) {\n if (!isRecord(namespaces)) throw new ControlError(`${label}.namespaces: expected an object`)\n for (const [name, each] of Object.entries(namespaces)) {\n if (!KEY_PATTERN.test(name))\n throw new ControlError(`${label}.namespaces: bad namespace ${JSON.stringify(name)}`)\n plan.namespaces[name] = normalizeControls(each, `${label}.namespaces.${name}`)\n }\n }\n if (credentials !== undefined) {\n if (!isRecord(credentials)) throw new ControlError(`${label}.credentials: expected an object`)\n for (const [credential, namespace] of Object.entries(credentials)) {\n if (typeof namespace !== \"string\" || !KEY_PATTERN.test(namespace))\n throw new ControlError(`${label}.credentials: bad namespace for a credential`)\n plan.credentials[credential] = namespace\n }\n }\n return plan\n}\n\n// \u2500\u2500 request headers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Every header a request can carry a control in. Selection headers pick what a request\n * reads; the rest act exactly like the matching admin call made just before the request.\n */\nexport const CONTROL_HEADERS = {\n namespace: \"x-mockingbird-namespace\",\n adminKey: \"x-mockingbird-admin-key\",\n branch: \"x-mockingbird-branch\",\n at: \"x-mockingbird-at\",\n reset: \"x-mockingbird-reset\",\n restore: \"x-mockingbird-restore\",\n seed: \"x-mockingbird-seed\",\n time: \"x-mockingbird-time\",\n advance: \"x-mockingbird-advance\",\n virtualTime: \"x-mockingbird-virtual-time\",\n fault: \"x-mockingbird-fault\",\n delay: \"x-mockingbird-delay\",\n timeout: \"x-mockingbird-timeout\",\n snapshot: \"x-mockingbird-snapshot\",\n} as const\n\nexport type ControlHeaderName = keyof typeof CONTROL_HEADERS\n\n/**\n * What each control header does, in the order the runtime applies them. This list is the\n * source for `GET /__admin` and is checked against the guide in `docs/ADMIN_CONTROLS.md`.\n */\nexport const CONTROL_HEADER_REFERENCE: readonly {\n header: string\n value: string\n /** `select` picks what is read; `namespace` changes it and persists; `request` is one request. */\n scope: \"select\" | \"namespace\" | \"request\"\n /** Needs `x-mockingbird-admin-key` when the mock has an admin key. */\n guarded: boolean\n summary: string\n}[] = [\n {\n header: CONTROL_HEADERS.namespace,\n value: \"<key>\",\n scope: \"select\",\n guarded: false,\n summary:\n \"Isolation key. Each key has its own records, clock, random streams, faults, latency, journal and snapshots.\",\n },\n {\n header: CONTROL_HEADERS.branch,\n value: \"<name>\",\n scope: \"select\",\n guarded: false,\n summary: \"Read and write a named copy-on-write branch of the namespace's history.\",\n },\n {\n header: CONTROL_HEADERS.at,\n value: \"<checkpoint>\",\n scope: \"select\",\n guarded: false,\n summary: \"Read the namespace as it was at a checkpoint. With a branch, start the branch there.\",\n },\n {\n header: CONTROL_HEADERS.reset,\n value: \"true\",\n scope: \"namespace\",\n guarded: true,\n summary: \"Reset the namespace to its boot state before the request is handled.\",\n },\n {\n header: CONTROL_HEADERS.restore,\n value: \"<snapshot>\",\n scope: \"namespace\",\n guarded: true,\n summary: \"Restore a snapshot before the request is handled.\",\n },\n {\n header: CONTROL_HEADERS.seed,\n value: \"<seed>\",\n scope: \"namespace\",\n guarded: true,\n summary: \"Restart the namespace's random streams from this seed.\",\n },\n {\n header: CONTROL_HEADERS.time,\n value: \"<epoch ms | ISO-8601>\",\n scope: \"namespace\",\n guarded: true,\n summary: \"Freeze the namespace clock at this instant.\",\n },\n {\n header: CONTROL_HEADERS.advance,\n value: \"<duration>\",\n scope: \"namespace\",\n guarded: true,\n summary: \"Move the namespace clock by this much, forward or (negative) back.\",\n },\n {\n header: CONTROL_HEADERS.virtualTime,\n value: \"true | false\",\n scope: \"namespace\",\n guarded: true,\n summary: \"Spend injected waits on the mock clock (true) or the wall clock (false).\",\n },\n {\n header: CONTROL_HEADERS.delay,\n value: \"<duration>\",\n scope: \"request\",\n guarded: true,\n summary: \"Hold this response back this long, on top of the namespace's latency.\",\n },\n {\n header: CONTROL_HEADERS.timeout,\n value: \"<duration>\",\n scope: \"request\",\n guarded: true,\n summary: \"Never answer this request: hold it this long, then drop the connection.\",\n },\n {\n header: CONTROL_HEADERS.fault,\n value: '<status> | drop | <preset> | key=value; \u2026 | {\"status\": 503, \u2026}',\n scope: \"request\",\n guarded: true,\n summary: \"Fault this request only. Stored fault rules are not consulted when it answers.\",\n },\n {\n header: CONTROL_HEADERS.snapshot,\n value: \"<name>\",\n scope: \"namespace\",\n guarded: true,\n summary: \"Snapshot the namespace after the request is handled. Echoed on the response.\",\n },\n]\n\n/** The controls one request carries in its headers, parsed and checked. */\nexport type RequestControls = {\n reset?: true\n restore?: string\n seed?: number | string\n time?: number\n advance?: number\n virtualTime?: boolean\n delay?: number\n timeout?: number\n fault?: Record<string, unknown>\n snapshot?: string\n}\n\nconst flag = (value: string, header: string): boolean => {\n const text = value.trim().toLowerCase()\n if (text === \"true\" || text === \"1\") return true\n if (text === \"false\" || text === \"0\") return false\n throw new ControlError(`${header}: expected true or false`)\n}\n\nconst name = (value: string, header: string): string => {\n const text = value.trim()\n if (!KEY_PATTERN.test(text)) throw new ControlError(`${header}: must match ${KEY_PATTERN}`)\n return text\n}\n\nconst FAULT_PAIRS = new Set([\n \"status\",\n \"delay\",\n \"jitter\",\n \"timeout\",\n \"drop\",\n \"truncate\",\n \"effect\",\n \"preset\",\n \"body\",\n])\n\n/**\n * Parse an `x-mockingbird-fault` value into a fault rule (or preset reference):\n *\n * - `503` \u2014 answer with that status\n * - `drop` \u2014 drop the connection\n * - `rate_limited` \u2014 a preset, by name\n * - `status=503; delay=2s; header.retry-after=5` \u2014 `key=value` pairs\n * - `{\"status\": 503, \"body\": {\u2026}}` \u2014 a rule as JSON\n */\nexport const parseFaultHeader = (\n value: string,\n header: string = CONTROL_HEADERS.fault,\n): Record<string, unknown> => {\n const text = value.trim()\n if (text === \"\") throw new ControlError(`${header}: expected a fault`)\n if (text.startsWith(\"{\")) {\n let parsed: unknown\n try {\n parsed = JSON.parse(text)\n } catch {\n throw new ControlError(`${header}: not valid JSON`)\n }\n if (!isRecord(parsed)) throw new ControlError(`${header}: expected a JSON object`)\n return parsed\n }\n const rule: Record<string, unknown> = {}\n const headers: Record<string, string> = {}\n for (const [index, raw] of text.split(\";\").entries()) {\n const part = raw.trim()\n if (part === \"\") continue\n const equals = part.indexOf(\"=\")\n if (equals < 0) {\n if (index > 0 && part !== \"drop\")\n throw new ControlError(`${header}: expected key=value, got ${JSON.stringify(part)}`)\n if (/^\\d{3}$/.test(part)) rule.status = Number(part)\n else if (part === \"drop\") rule.drop = true\n else rule.preset = name(part, header)\n continue\n }\n const key = part.slice(0, equals).trim().toLowerCase()\n const item = part.slice(equals + 1).trim()\n if (key.startsWith(\"header.\")) headers[key.slice(\"header.\".length)] = item\n else if (!FAULT_PAIRS.has(key))\n throw new ControlError(\n `${header}: unknown key ${JSON.stringify(key)}; expected ${[...FAULT_PAIRS].join(\", \")} or header.<name>`,\n )\n else if (key === \"status\" || key === \"truncate\") {\n if (!/^\\d+$/.test(item)) throw new ControlError(`${header}: ${key} must be a number`)\n rule[key] = Number(item)\n } else if (key === \"drop\") rule.drop = flag(item, `${header} drop`)\n else rule[key] = item\n }\n if (Object.keys(headers).length > 0) rule.headers = headers\n if (Object.keys(rule).length === 0) throw new ControlError(`${header}: expected a fault`)\n return rule\n}\n\nconst GUARDED = CONTROL_HEADER_REFERENCE.filter((each) => each.guarded).map((each) => each.header)\n\n/** Whether a request carries a control that changes the mock or injects a failure. */\nexport const hasGuardedControlHeader = (headers: Headers): boolean =>\n GUARDED.some((header) => headers.has(header))\n\n/** Read a request's control headers. `undefined` when it carries none. Throws {@link ControlError}. */\nexport const parseControlHeaders = (headers: Headers): RequestControls | undefined => {\n if (!hasGuardedControlHeader(headers)) return undefined\n const controls: RequestControls = {}\n const read = (key: ControlHeaderName) => headers.get(CONTROL_HEADERS[key])\n const reset = read(\"reset\")\n if (reset !== null && flag(reset, CONTROL_HEADERS.reset)) controls.reset = true\n const restore = read(\"restore\")\n if (restore !== null) controls.restore = name(restore, CONTROL_HEADERS.restore)\n const seed = read(\"seed\")\n if (seed !== null) controls.seed = normalizeSeed(seed.trim(), CONTROL_HEADERS.seed)\n const time = read(\"time\")\n if (time !== null) controls.time = instantMs(time, CONTROL_HEADERS.time)\n const advance = read(\"advance\")\n if (advance !== null) controls.advance = durationMs(advance, CONTROL_HEADERS.advance, true)\n const virtualTime = read(\"virtualTime\")\n if (virtualTime !== null) controls.virtualTime = flag(virtualTime, CONTROL_HEADERS.virtualTime)\n const delay = read(\"delay\")\n if (delay !== null) controls.delay = durationMs(delay, CONTROL_HEADERS.delay)\n const timeout = read(\"timeout\")\n if (timeout !== null) controls.timeout = durationMs(timeout, CONTROL_HEADERS.timeout)\n const fault = read(\"fault\")\n if (fault !== null) controls.fault = parseFaultHeader(fault)\n const snapshot = read(\"snapshot\")\n if (snapshot !== null) controls.snapshot = name(snapshot, CONTROL_HEADERS.snapshot)\n return controls\n}\n\n/** What {@link controlHeaders} turns into request headers. */\nexport type ControlHeaderInput = {\n namespace?: string\n adminKey?: string\n branch?: string\n at?: string\n reset?: boolean\n restore?: string\n seed?: number | string\n time?: Instant | Date\n advance?: Duration\n virtualTime?: boolean\n delay?: Duration\n timeout?: Duration\n /** A status, `\"drop\"`, a preset name, or a fault rule. */\n fault?: number | string | Record<string, unknown>\n snapshot?: string\n}\n\n/**\n * Build the request headers for a set of controls, to spread into a `fetch` or hand to an\n * SDK's default headers. Values are checked, so a typo fails here and not as a `400` later.\n */\nexport const controlHeaders = (input: ControlHeaderInput): Record<string, string> => {\n const headers: Record<string, string> = {}\n const set = (key: ControlHeaderName, value: string) => {\n headers[CONTROL_HEADERS[key]] = value\n }\n if (input.namespace !== undefined) set(\"namespace\", name(input.namespace, \"namespace\"))\n if (input.adminKey !== undefined) set(\"adminKey\", input.adminKey)\n if (input.branch !== undefined) set(\"branch\", name(input.branch, \"branch\"))\n if (input.at !== undefined) set(\"at\", input.at)\n if (input.reset === true) set(\"reset\", \"true\")\n if (input.restore !== undefined) set(\"restore\", name(input.restore, \"restore\"))\n if (input.seed !== undefined) set(\"seed\", String(normalizeSeed(input.seed)))\n if (input.time !== undefined) {\n const time = input.time instanceof Date ? input.time.getTime() : input.time\n set(\"time\", new Date(instantMs(time, \"time\")).toISOString())\n }\n if (input.advance !== undefined)\n set(\"advance\", String(durationMs(input.advance, \"advance\", true)))\n if (input.virtualTime !== undefined) set(\"virtualTime\", String(input.virtualTime))\n if (input.delay !== undefined) set(\"delay\", String(durationMs(input.delay, \"delay\")))\n if (input.timeout !== undefined) set(\"timeout\", String(durationMs(input.timeout, \"timeout\")))\n if (input.fault !== undefined) {\n const fault =\n typeof input.fault === \"object\" ? JSON.stringify(input.fault) : String(input.fault)\n parseFaultHeader(fault, \"fault\")\n set(\"fault\", fault)\n }\n if (input.snapshot !== undefined) set(\"snapshot\", name(input.snapshot, \"snapshot\"))\n return headers\n}\n", "/**\n * Seeded pseudo-random numbers, so anything a mock invents \u2014 ids, jitter, which\n * request a percentage fault hits \u2014 is reproducible from a seed.\n *\n * mulberry32: small, fast, and stable across runtimes, which matters more here\n * than statistical quality.\n */\nexport type Rng = {\n /** Next value in `[0, 1)`. */\n next(): number\n /** Next integer in `[min, max]`. */\n int(min: number, max: number): number\n /** Restart the stream from its seed. */\n reset(): void\n /** Serializable engine state used by deterministic checkpoints. */\n state(): number\n /** Restore a state previously returned by {@link state}. */\n setState(state: number): void\n /** Restart the stream from a new seed. `reset` then returns to this seed. */\n reseed(seed: number | string): void\n /** The seed the stream currently starts from. */\n readonly seed: number\n}\n\n/** Hash an arbitrary string into a 32-bit seed, so callers can seed by name. */\nexport const seedFrom = (value: string): number => {\n let hash = 2166136261\n for (let i = 0; i < value.length; i++) {\n hash ^= value.charCodeAt(i)\n hash = Math.imul(hash, 16777619)\n }\n return hash >>> 0\n}\n\nexport const createRng = (seed: number | string = 0): Rng => {\n const toNumeric = (value: number | string) =>\n typeof value === \"string\" ? seedFrom(value) : value >>> 0\n let numeric = toNumeric(seed)\n let state = numeric\n const next = () => {\n state = (state + 0x6d2b79f5) >>> 0\n let t = state\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n return {\n next,\n int: (min, max) => min + Math.floor(next() * (max - min + 1)),\n reset: () => {\n state = numeric\n },\n state: () => state,\n setState: (next) => {\n if (!Number.isSafeInteger(next) || next < 0 || next > 0xffffffff) {\n throw new RangeError(\"rng state must be an unsigned 32-bit integer\")\n }\n state = next >>> 0\n },\n reseed: (next) => {\n numeric = toNumeric(next)\n state = numeric\n },\n get seed() {\n return numeric\n },\n }\n}\n", "import {\n ControlError,\n type Duration,\n durationMs,\n type Instant,\n isRecord,\n KEY_PATTERN,\n parseDuration,\n parseInstant,\n} from \"./controls.js\"\nimport { createRng, type Rng } from \"./rng.js\"\n\n/**\n * A deliberate failure injected in front of an operation.\n *\n * This is how a suite reaches the vendor's failure modes without the vendor: the\n * quota error that only appears when a shared sandbox is full, the 429 that only\n * appears under load, the 5xx that proves a retry path works.\n *\n * A rule has three parts. What it **matches** (`operationId`, `method`, `path`, \u2026), **when**\n * it fires among the matching requests (`after`, `every`, `count`, `rate`, `from`, `until`),\n * and what it **does** (`status`, `delay`, `timeout`, `drop`, `truncate`, `effect`).\n */\nexport type FaultRule = {\n /** Stable id, so a suite can retire exactly the rule it added. Unique within a namespace. */\n id: string\n\n /** Fault only this operation. Omit to match every operation. */\n operationId?: string\n /** Fault only this HTTP method, case-insensitive. Omit to match every method. */\n method?: string\n /** Fault only this exact path. */\n path?: string\n /** Fault only paths starting with this prefix. Omit to match every path. */\n pathPrefix?: string\n /** Fault only paths matching this regular expression (JavaScript syntax, unanchored). */\n pathPattern?: string\n /** Fault only requests carrying these headers. `\"*\"` matches any value. */\n requestHeaders?: Record<string, string>\n /** Fault only requests carrying these query parameters. `\"*\"` matches any value. */\n query?: Record<string, string>\n /**\n * Fault only requests whose JSON body carries these fields. Each key is a dotted path into\n * the parsed body (`\"patient_details.email\"`; a number steps into an array, `\"items.0.sku\"`)\n * and each value is what the field must equal: a string, number, boolean or `null`, compared\n * strictly (`3` is not `\"3\"`). `\"*\"` matches any value that is present. A request whose body\n * is missing, is not JSON, or is not a JSON object never matches. Not `body`, which is the\n * response a rule injects.\n */\n requestBody?: Record<string, RequestBodyValue>\n /**\n * Fault only this namespace. Omit (or `\"*\"`) to fault every namespace \u2014 which is what\n * an in-process caller usually wants, and what a parallel worker usually does not:\n * rules added through `POST /__admin/faults` default to the calling namespace.\n */\n namespace?: string\n\n /** Let this many matching requests through first. */\n after?: number\n /** Then fault only every nth matching request: `3` faults the 3rd, 6th, 9th. */\n every?: number\n /** Retire the rule after this many faults. Omit to keep it until removed. */\n count?: number\n /** Fault this fraction of the remaining requests, `0`\u2013`1`, drawn from the seed. Default `1`. */\n rate?: number\n /**\n * Fault only from this instant on the namespace clock. A duration (`\"5m\"`) counts from the\n * clock when the rule was added. Listed as epoch ms.\n */\n from?: Instant | Duration\n /** Stop faulting at this instant on the namespace clock. A duration counts from when added. */\n until?: Instant | Duration\n\n /**\n * Status of the injected response. Omit for a rule that only delays, times out, drops,\n * truncates, or switches on an `effect`: the request then still reaches the service.\n */\n status?: number\n /** Response body, serialized as JSON. A string is sent as-is. */\n body?: unknown\n /** Response headers. */\n headers?: Record<string, string>\n /** Hold the response back this long. Listed as `delayMs`. */\n delay?: Duration\n /** `delay`, in milliseconds. */\n delayMs?: number\n /** Alias of `delayMs`. */\n latencyMs?: number\n /** Extra seeded delay in `[0, jitter]`. Listed as `jitterMs`. */\n jitter?: Duration\n jitterMs?: number\n /**\n * Never answer: hold the request this long, then drop the connection. Listed as\n * `timeoutMs`. With virtual time the wait is spent on the mock clock.\n */\n timeout?: Duration\n timeoutMs?: number\n /**\n * Drop the connection instead of answering: an in-process `fetch` rejects with a\n * `TypeError`, and a served mock destroys the socket. Models \"unknown outcome\" failures.\n */\n drop?: boolean\n /**\n * Cut the response body off after this many bytes: the status and headers arrive, then\n * the connection dies mid-body.\n */\n truncate?: number\n /**\n * A named service behaviour to switch on for the matching request instead of (or\n * before) a canned response, e.g. `created_but_500` or `numeric_tracking_id`. Services\n * read it with `faultEffects(request)`.\n */\n effect?: string\n /** Parameters for `effect`. */\n params?: Record<string, unknown>\n /** The preset this rule was expanded from, if any. */\n fromPreset?: string\n}\n\n/** What a field of the request body must equal in {@link FaultRule.requestBody}. */\nexport type RequestBodyValue = string | number | boolean | null\n\n/** A fault that fired for one request. */\nexport type FaultHit = {\n id: string\n /** The injected response; absent when the rule only delays, drops, or sets an effect. */\n response?: Response\n drop?: boolean\n /** Set with `drop` when the rule held the request for its `timeout` first. */\n timeout?: boolean\n /** Bytes of response body to let through before the connection dies. */\n truncate?: number\n effect?: { name: string; params: Record<string, unknown> }\n}\n\n/**\n * A named, documented fault a suite switches on by name\n * (`POST /__admin/faults {\"preset\": \"rate_limited\"}`): one or more rules, and optionally a\n * webhook delivery fault.\n */\nexport type FaultPreset = {\n description: string\n rules?: Omit<FaultRule, \"id\">[]\n webhook?: { mode: \"duplicate\" | \"reorder\" | \"drop\"; count?: number }\n}\n\n/**\n * Presets every mock answers to, so a suite uses one vocabulary across vendors. A service\n * preset of the same name replaces the standard one with the vendor's own error body.\n */\nexport const STANDARD_FAULT_PRESETS: Record<string, FaultPreset> = {\n server_error: {\n description: \"The vendor answers 500.\",\n rules: [{ status: 500 }],\n },\n bad_gateway: {\n description: \"A proxy in front of the vendor answers 502.\",\n rules: [{ status: 502 }],\n },\n unavailable: {\n description: \"The vendor is down: 503 with retry-after.\",\n rules: [{ status: 503, headers: { \"retry-after\": \"1\" } }],\n },\n gateway_timeout: {\n description: \"A proxy gives up on the vendor: 504.\",\n rules: [{ status: 504 }],\n },\n rate_limited: {\n description: \"Too many requests: 429 with retry-after.\",\n rules: [{ status: 429, headers: { \"retry-after\": \"1\" } }],\n },\n unauthorized: {\n description: \"The credential is rejected: 401.\",\n rules: [{ status: 401 }],\n },\n forbidden: {\n description: \"The credential lacks permission: 403.\",\n rules: [{ status: 403 }],\n },\n slow: {\n description: \"Every response takes two more seconds.\",\n rules: [{ delayMs: 2_000 }],\n },\n timeout: {\n description:\n \"The vendor never answers: the request hangs 30 seconds, then the connection drops.\",\n rules: [{ timeoutMs: 30_000 }],\n },\n connection_reset: {\n description: \"The connection dies before any response.\",\n rules: [{ drop: true }],\n },\n truncated_response: {\n description: \"The response starts, then the connection dies mid-body.\",\n rules: [{ truncate: 0 }],\n },\n flaky: {\n description: \"Half of the requests answer 503, chosen by the seed.\",\n rules: [{ status: 503, rate: 0.5 }],\n },\n}\n\n/**\n * Body of `GET /__admin/faults/presets`.\n * `presets` is a list of named presets. A record keyed by name is not this type:\n * the admin page maps the list.\n */\nexport type FaultPresetList = {\n presets: readonly { name: string }[]\n}\n\ntype _AssertFaultPresetList<T extends FaultPresetList> = T\n// @ts-expect-error presets is a list of { name }, not a record keyed by name\ntype _RecordIsNotAPresetList = _AssertFaultPresetList<{ presets: Record<string, { name: string }> }>\n\n/** What a request looks like to the fault matcher. */\nexport type FaultCandidate = {\n operationId: string | undefined\n method: string\n path: string\n namespace: string\n /** Request headers and query, for rules that match on them. */\n headers?: Headers\n query?: URLSearchParams\n /**\n * The request body parsed as JSON, read only when a rule matches on `requestBody`. Resolve\n * `undefined` for a body that is missing or not JSON. It must leave the request readable.\n */\n readJson?: () => Promise<unknown>\n /** The namespace clock, for `from` / `until`. Rules with a window are skipped without it. */\n now?: number\n /** How to spend a delay for this request. Default: the registry's own sleep. */\n wait?: (ms: number) => Promise<void>\n}\n\n/** A stored rule and how often it was consulted. */\nexport type FaultListing = FaultRule & {\n /** Faults left before the rule retires. `null` when it has no `count`. */\n remaining: number | null\n /** Times the rule faulted a request. */\n hits: number\n /** Requests that matched the rule, faulted or not. */\n seen: number\n}\n\n/** A namespace's own rules, with their counters, in the order they are tried. */\nexport type FaultSnapshot = {\n /**\n * `position` is how many `\"*\"` rules are tried before the rule, which is what its place\n * in the order means to a request and holds in any process.\n */\n rules: (FaultListing & { position?: number })[]\n /** How many `fault_<n>` ids the namespace has handed out. */\n nextId?: number\n}\n\nexport type FaultRegistry = {\n snapshot(namespace: string): FaultSnapshot\n /** Add a rule, or replace the rule with the same id in the same namespace. */\n add(rule: FaultRule): FaultRule\n /** The next unused `fault_<n>` id in `namespace`. */\n nextId(namespace: string): string\n /** Every rule, or the rules a namespace's requests can hit: its own and the global ones. */\n list(namespace?: string): FaultListing[]\n get(id: string, namespace?: string): FaultListing | undefined\n /** Remove a rule by id: from `namespace` (its own, then a global one), or wherever it is. */\n remove(id: string, namespace?: string): boolean\n /** Remove every rule, or one namespace's own rules. */\n clear(namespace?: string): void\n /** Replace a namespace's own rules with a snapshot's, wherever the snapshot was taken. */\n restore(namespace: string, state: FaultSnapshot): void\n /**\n * Every fault this request should get, in rule order, stopping at the first that answers\n * or drops (effect-only and delay-only rules let later rules match too). Consumes one of\n * each matching rule's remaining uses.\n */\n take(candidate: FaultCandidate): Promise<FaultHit[]>\n /**\n * Fire these rules at one request without storing them: no matching, no schedule, in order,\n * stopping at the first that answers or drops. Jitter draws from the namespace's stream.\n */\n fire(rules: readonly FaultRule[], candidate: FaultCandidate): Promise<FaultHit[]>\n}\n\n/** The namespace of a rule that faults every namespace. */\nconst GLOBAL = \"*\"\n\nconst RULE_KEYS = new Set([\n \"id\",\n \"operationId\",\n \"method\",\n \"path\",\n \"pathPrefix\",\n \"pathPattern\",\n \"requestHeaders\",\n \"query\",\n \"requestBody\",\n \"namespace\",\n \"after\",\n \"every\",\n \"count\",\n \"rate\",\n \"from\",\n \"until\",\n \"status\",\n \"body\",\n \"headers\",\n \"delay\",\n \"delayMs\",\n \"latencyMs\",\n \"jitter\",\n \"jitterMs\",\n \"timeout\",\n \"timeoutMs\",\n \"drop\",\n \"truncate\",\n \"effect\",\n \"params\",\n \"fromPreset\",\n])\n/** Counters a listed rule carries. Accepted and ignored, so a listing can be applied again. */\nconst LISTING_KEYS = new Set([\"remaining\", \"hits\", \"seen\"])\n\nconst stringMap = (value: unknown, label: string): Record<string, string> => {\n if (!isRecord(value) || !Object.values(value).every((each) => typeof each === \"string\"))\n throw new ControlError(`${label}: expected an object of strings`)\n return value as Record<string, string>\n}\n\nconst requestBodyMap = (value: unknown): Record<string, RequestBodyValue> => {\n if (!isRecord(value)) throw new ControlError(\"fault.requestBody: expected an object\")\n for (const [path, expected] of Object.entries(value)) {\n if (path === \"\" || path.split(\".\").includes(\"\"))\n throw new ControlError(`fault.requestBody: ${JSON.stringify(path)} is not a dotted path`)\n const scalar =\n expected === null ||\n typeof expected === \"string\" ||\n typeof expected === \"boolean\" ||\n (typeof expected === \"number\" && Number.isFinite(expected))\n if (!scalar)\n throw new ControlError(\n `fault.requestBody.${path}: expected a string, number, boolean or null`,\n )\n }\n return value as Record<string, RequestBodyValue>\n}\n\nconst count = (value: unknown, label: string, min: number): number => {\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < min)\n throw new ControlError(`${label}: expected an integer of at least ${min}`)\n return value\n}\n\n/** An instant, or a duration counted from `now`. A bare number is always an instant. */\nconst windowEdge = (value: unknown, label: string, now: number | undefined): number => {\n if (typeof value === \"string\" && /[a-z]\\s*$/i.test(value) && !/[T:Z]/.test(value)) {\n const relative = parseDuration(value)\n if (relative !== undefined) {\n if (now === undefined) throw new ControlError(`${label}: a duration needs a clock`)\n return now + relative\n }\n }\n const instant = parseInstant(value)\n if (instant === undefined)\n throw new ControlError(`${label}: expected epoch ms, ISO-8601, or a duration like \"5m\"`)\n return instant\n}\n\n/** Whether a rule does anything at all when it fires. */\nexport const faultHasAction = (rule: Partial<FaultRule>): boolean =>\n rule.status !== undefined ||\n (rule.delayMs ?? 0) > 0 ||\n (rule.jitterMs ?? 0) > 0 ||\n rule.timeoutMs !== undefined ||\n rule.drop === true ||\n rule.truncate !== undefined ||\n rule.effect !== undefined\n\n/**\n * Check a fault rule and put it in its stored form: durations in milliseconds\n * (`delayMs`, `jitterMs`, `timeoutMs`), windows as epoch ms. Throws {@link ControlError}.\n *\n * `strict` rejects unknown keys, so a typo in a request body is an error and not a rule\n * that silently never matches.\n */\nexport const normalizeFault = (\n input: unknown,\n context: { id?: string; namespace?: string; now?: number; strict?: boolean } = {},\n): FaultRule => {\n if (!isRecord(input)) throw new ControlError(\"fault: expected an object\")\n if (context.strict) {\n for (const key of Object.keys(input)) {\n if (!RULE_KEYS.has(key) && !LISTING_KEYS.has(key))\n throw new ControlError(`fault: unknown field ${JSON.stringify(key)}`)\n }\n }\n const id = input.id ?? context.id\n if (typeof id !== \"string\" || id === \"\") throw new ControlError(\"fault.id: expected a string\")\n const rule: FaultRule = { id }\n for (const key of [\n \"operationId\",\n \"method\",\n \"path\",\n \"pathPrefix\",\n \"effect\",\n \"fromPreset\",\n ] as const) {\n const value = input[key]\n if (value === undefined) continue\n if (typeof value !== \"string\") throw new ControlError(`fault.${key}: expected a string`)\n rule[key] = value\n }\n if (input.pathPattern !== undefined) {\n if (typeof input.pathPattern !== \"string\")\n throw new ControlError(\"fault.pathPattern: expected a string\")\n try {\n new RegExp(input.pathPattern)\n } catch {\n throw new ControlError(\"fault.pathPattern: not a valid regular expression\")\n }\n rule.pathPattern = input.pathPattern\n }\n if (input.requestHeaders !== undefined)\n rule.requestHeaders = Object.fromEntries(\n Object.entries(stringMap(input.requestHeaders, \"fault.requestHeaders\")).map(([k, v]) => [\n k.toLowerCase(),\n v,\n ]),\n )\n if (input.query !== undefined) rule.query = stringMap(input.query, \"fault.query\")\n if (input.requestBody !== undefined) rule.requestBody = requestBodyMap(input.requestBody)\n const namespace = input.namespace ?? context.namespace\n if (namespace !== undefined) {\n // A rule for a namespace that cannot exist would be stored and never fire.\n if (typeof namespace !== \"string\" || (namespace !== GLOBAL && !KEY_PATTERN.test(namespace)))\n throw new ControlError(`fault.namespace: expected \"*\" or a key matching ${KEY_PATTERN}`)\n rule.namespace = namespace\n }\n if (input.after !== undefined) rule.after = count(input.after, \"fault.after\", 0)\n if (input.every !== undefined) rule.every = count(input.every, \"fault.every\", 1)\n if (input.count !== undefined) rule.count = count(input.count, \"fault.count\", 0)\n if (input.rate !== undefined) {\n if (typeof input.rate !== \"number\" || !(input.rate >= 0 && input.rate <= 1))\n throw new ControlError(\"fault.rate: expected a number from 0 to 1\")\n rule.rate = input.rate\n }\n if (input.from !== undefined) rule.from = windowEdge(input.from, \"fault.from\", context.now)\n if (input.until !== undefined) rule.until = windowEdge(input.until, \"fault.until\", context.now)\n if (input.status !== undefined) {\n if (\n typeof input.status !== \"number\" ||\n !Number.isInteger(input.status) ||\n input.status < 200 ||\n input.status > 599\n )\n throw new ControlError(\"fault.status: expected an HTTP status from 200 to 599\")\n rule.status = input.status\n }\n if (input.body !== undefined) rule.body = input.body\n if (input.headers !== undefined) rule.headers = stringMap(input.headers, \"fault.headers\")\n const delay = input.delay ?? input.delayMs ?? input.latencyMs\n if (delay !== undefined) rule.delayMs = durationMs(delay, \"fault.delay\")\n const jitter = input.jitter ?? input.jitterMs\n if (jitter !== undefined) rule.jitterMs = durationMs(jitter, \"fault.jitter\")\n const timeout = input.timeout ?? input.timeoutMs\n if (timeout !== undefined) rule.timeoutMs = durationMs(timeout, \"fault.timeout\")\n if (input.drop !== undefined) {\n if (typeof input.drop !== \"boolean\") throw new ControlError(\"fault.drop: expected a boolean\")\n if (input.drop) rule.drop = true\n }\n if (input.truncate !== undefined) rule.truncate = count(input.truncate, \"fault.truncate\", 0)\n if (input.params !== undefined) {\n if (!isRecord(input.params)) throw new ControlError(\"fault.params: expected an object\")\n rule.params = input.params\n }\n return rule\n}\n\ntype Entry = {\n rule: FaultRule\n scope: string\n remaining: number | null\n hits: number\n seen: number\n pattern: RegExp | undefined\n}\n\nconst scopeOf = (rule: FaultRule): string =>\n rule.namespace === undefined || rule.namespace === GLOBAL ? GLOBAL : rule.namespace\n\nconst matchesAll = (\n wanted: Record<string, string> | undefined,\n read: (name: string) => string | null | undefined,\n): boolean => {\n if (!wanted) return true\n for (const [key, value] of Object.entries(wanted)) {\n const actual = read(key)\n if (actual === null || actual === undefined) return false\n if (value !== \"*\" && actual !== value) return false\n }\n return true\n}\n\n/** The value at a dotted path of a parsed JSON body; `undefined` when any step is missing. */\nconst field = (body: unknown, path: string): unknown => {\n let at = body\n for (const step of path.split(\".\")) {\n if (Array.isArray(at)) {\n if (!/^(0|[1-9]\\d*)$/.test(step)) return undefined\n at = at[Number(step)]\n } else if (isRecord(at) && Object.hasOwn(at, step)) at = at[step]\n else return undefined\n }\n return at\n}\n\n/** Whether the parsed body has every field `wanted` names. Only a JSON object can. */\nconst bodyMatches = (wanted: Record<string, RequestBodyValue>, body: unknown): boolean => {\n if (!isRecord(body)) return false\n for (const [path, expected] of Object.entries(wanted)) {\n const actual = field(body, path)\n if (actual === undefined) return false\n if (expected !== \"*\" && actual !== expected) return false\n }\n return true\n}\n\nconst matches = (entry: Entry, candidate: FaultCandidate, body: { value: unknown }): boolean => {\n const { rule } = entry\n if (entry.scope !== GLOBAL && entry.scope !== candidate.namespace) return false\n if (rule.operationId !== undefined && rule.operationId !== candidate.operationId) return false\n if (rule.method !== undefined && rule.method.toUpperCase() !== candidate.method.toUpperCase()) {\n return false\n }\n if (rule.path !== undefined && rule.path !== candidate.path) return false\n if (rule.pathPrefix !== undefined && !candidate.path.startsWith(rule.pathPrefix)) return false\n if (entry.pattern && !entry.pattern.test(candidate.path)) return false\n if (!matchesAll(rule.requestHeaders, (name) => candidate.headers?.get(name))) return false\n if (!matchesAll(rule.query, (name) => candidate.query?.get(name))) return false\n if (rule.requestBody && !bodyMatches(rule.requestBody, body.value)) return false\n if (rule.from !== undefined || rule.until !== undefined) {\n if (candidate.now === undefined) return false\n if (rule.from !== undefined && candidate.now < (rule.from as number)) return false\n if (rule.until !== undefined && candidate.now >= (rule.until as number)) return false\n }\n return true\n}\n\n/** The response a rule with a `status` answers with. */\nexport const faultResponse = (rule: FaultRule): Response => {\n const status = rule.status ?? 500\n const headers = { \"content-type\": \"application/json\", ...rule.headers }\n if (typeof rule.body === \"string\") return new Response(rule.body, { status, headers })\n if (rule.body === null) return new Response(null, { status, headers: rule.headers ?? {} })\n const body = rule.body === undefined ? { detail: \"Injected by Mockingbird\" } : rule.body\n return new Response(JSON.stringify(body), { status, headers })\n}\n\nconst listing = (entry: Entry): FaultListing => ({\n ...entry.rule,\n remaining: entry.remaining,\n hits: entry.hits,\n seen: entry.seen,\n})\n\n/**\n * Rules are matched in the order they were added, so a narrow rule added first\n * wins over a later catch-all. `rate` and `jitter` draw from a seeded stream per namespace,\n * so a partial-failure run replays identically whatever other namespaces are doing.\n *\n * `random` is that stream: a function from namespace to stream, owned by the caller, which\n * the registry draws from and never seeds or rewinds. A single stream is accepted too, for a\n * registry used on its own: it serves `default`, and every other namespace gets a stream of\n * its own from the same seed.\n */\nexport const createFaultRegistry = (\n random: Rng | ((namespace: string) => Rng) = createRng(0),\n sleep: (ms: number) => Promise<void> = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),\n): FaultRegistry => {\n const entries: Entry[] = []\n const counters = new Map<string, number>()\n const own = new Map<string, Rng>()\n const stream =\n typeof random === \"function\"\n ? random\n : (namespace: string): Rng => {\n if (namespace === \"default\") return random\n let found = own.get(namespace)\n if (!found) {\n found = createRng(random.seed)\n own.set(namespace, found)\n }\n return found\n }\n const toEntry = (input: FaultRule, previous?: Partial<Entry>): Entry => {\n const rule = normalizeFault(input)\n return {\n rule,\n scope: scopeOf(rule),\n remaining: previous?.remaining !== undefined ? previous.remaining : (rule.count ?? null),\n hits: previous?.hits ?? 0,\n seen: previous?.seen ?? 0,\n pattern: rule.pathPattern !== undefined ? new RegExp(rule.pathPattern) : undefined,\n }\n }\n const find = (id: string, namespace?: string): number => {\n if (namespace === undefined) return entries.findIndex((e) => e.rule.id === id)\n const mine = entries.findIndex((e) => e.rule.id === id && e.scope === namespace)\n return mine >= 0 ? mine : entries.findIndex((e) => e.rule.id === id && e.scope === GLOBAL)\n }\n const drop = (namespace: string): void => {\n for (let i = entries.length - 1; i >= 0; i--)\n if (entries[i]?.scope === namespace) entries.splice(i, 1)\n }\n return {\n snapshot(namespace) {\n const rules: FaultSnapshot[\"rules\"] = []\n let globals = 0\n for (const entry of entries) {\n if (entry.scope === GLOBAL) globals++\n else if (entry.scope === namespace) rules.push({ ...listing(entry), position: globals })\n }\n return { rules: structuredClone(rules), nextId: counters.get(namespace) ?? 0 }\n },\n add(input) {\n const entry = toEntry(input)\n const existing = entries.findIndex(\n (e) => e.rule.id === entry.rule.id && e.scope === entry.scope,\n )\n if (existing >= 0) entries[existing] = entry\n else entries.push(entry)\n return entry.rule\n },\n nextId(namespace) {\n let next = counters.get(namespace) ?? 0\n let id: string\n do {\n next++\n id = `fault_${next}`\n } while (entries.some((e) => e.rule.id === id && e.scope === namespace))\n counters.set(namespace, next)\n return id\n },\n list: (namespace) =>\n entries\n .filter((e) => namespace === undefined || e.scope === namespace || e.scope === GLOBAL)\n .map(listing),\n get(id, namespace) {\n const entry = entries[find(id, namespace)]\n return entry ? listing(entry) : undefined\n },\n remove(id, namespace) {\n const index = find(id, namespace)\n if (index < 0) return false\n entries.splice(index, 1)\n return true\n },\n clear(namespace) {\n if (namespace === undefined) {\n entries.length = 0\n counters.clear()\n // A registry given one stream owns it, and starts it over with the rules.\n if (typeof random !== \"function\") random.reset()\n own.clear()\n return\n }\n drop(namespace)\n counters.delete(namespace)\n },\n restore(namespace, state) {\n drop(namespace)\n for (const { remaining, hits, seen, position, ...rule } of state.rules) {\n const entry = toEntry({ ...rule, namespace }, { remaining, hits, seen })\n // Back where it stood among the global rules: ahead of the one that followed it.\n let globals = 0\n let index = entries.length\n if (position !== undefined) {\n for (const [at, each] of entries.entries()) {\n if (each.scope !== GLOBAL) continue\n if (globals === position) {\n index = at\n break\n }\n globals++\n }\n }\n entries.splice(index, 0, entry)\n }\n counters.set(namespace, state.nextId ?? 0)\n },\n async take(candidate) {\n const hits: FaultHit[] = []\n const wait = candidate.wait ?? sleep\n const draw = stream(candidate.namespace)\n // Parsed once, and only if a rule that reaches the body gets this far.\n const body: { value: unknown } = { value: undefined }\n let read = false\n // A copy: a rule added while this request waits must not join it halfway.\n for (const entry of [...entries]) {\n if (entry.remaining === 0) continue\n if (entry.rule.requestBody && !read) {\n read = true\n body.value = await candidate.readJson?.().catch(() => undefined)\n }\n if (!matches(entry, candidate, body)) continue\n const { rule } = entry\n entry.seen++\n const position = entry.seen - (rule.after ?? 0)\n if (position <= 0) continue\n if (rule.every !== undefined && position % rule.every !== 0) continue\n // Draw even when the rule always fires, so a seeded stream stays aligned.\n if (draw.next() >= (rule.rate ?? 1)) continue\n entry.hits++\n if (entry.remaining !== null) entry.remaining--\n const hit = await act(rule, draw, wait)\n hits.push(hit)\n if (hit.drop || hit.response) break\n }\n return hits\n },\n async fire(rules, candidate) {\n const hits: FaultHit[] = []\n for (const rule of rules) {\n const hit = await act(rule, stream(candidate.namespace), candidate.wait ?? sleep)\n hits.push(hit)\n if (hit.drop || hit.response) break\n }\n return hits\n },\n }\n}\n\n/** Do what a rule that fired says: wait, then answer, drop, or let the request through. */\nconst act = async (\n rule: FaultRule,\n draw: Rng,\n wait: (ms: number) => Promise<void>,\n): Promise<FaultHit> => {\n const jitter = (rule.jitterMs ?? 0) > 0 ? draw.int(0, Math.floor(rule.jitterMs ?? 0)) : 0\n const delay = (rule.delayMs ?? 0) + jitter\n if (delay > 0) await wait(delay)\n const hit: FaultHit = { id: rule.id }\n if (rule.effect !== undefined) hit.effect = { name: rule.effect, params: rule.params ?? {} }\n if (rule.truncate !== undefined) hit.truncate = rule.truncate\n if (rule.timeoutMs !== undefined) {\n if (rule.timeoutMs > 0) await wait(rule.timeoutMs)\n hit.drop = true\n hit.timeout = true\n } else if (rule.drop === true) hit.drop = true\n else if (rule.status !== undefined) hit.response = faultResponse(rule)\n return hit\n}\n", "import type { LatencyRule, LatencyState } from \"./controls.js\"\nimport type { Rng } from \"./rng.js\"\n\n/**\n * Baseline response time, per namespace: how long every vendor request takes before any\n * fault is considered. Jitter draws from a stream the caller owns, one per namespace and\n * separate from the fault stream, so adding latency never shifts which requests a `rate`\n * fault hits.\n */\nexport type LatencyRegistry = {\n get(namespace: string): LatencyState\n set(namespace: string, state: LatencyState): LatencyState\n /** Remove one namespace's latency, or every namespace's. */\n clear(namespace?: string): void\n /** Milliseconds this request waits. Draws jitter, so call it once per request. */\n take(namespace: string, operationId: string | undefined): number\n}\n\nconst NONE: LatencyState = Object.freeze({ delayMs: 0, jitterMs: 0, operations: {} })\n\nconst copy = (state: LatencyState): LatencyState => ({\n delayMs: state.delayMs,\n jitterMs: state.jitterMs,\n operations: Object.fromEntries(\n Object.entries(state.operations).map(([id, rule]) => [id, { ...rule }]),\n ),\n})\n\n/** `random` is the namespace's jitter stream. The registry never seeds or rewinds it. */\nexport const createLatencyRegistry = (random: (namespace: string) => Rng): LatencyRegistry => {\n const states = new Map<string, LatencyState>()\n return {\n get: (namespace) => copy(states.get(namespace) ?? NONE),\n set(namespace, state) {\n states.set(namespace, copy(state))\n return copy(state)\n },\n clear(namespace) {\n if (namespace === undefined) states.clear()\n else states.delete(namespace)\n },\n take(namespace, operationId) {\n const state = states.get(namespace)\n if (!state) return 0\n const rule: LatencyRule =\n (operationId !== undefined ? state.operations[operationId] : undefined) ?? state\n // Whole milliseconds, inclusive of both ends, so a jitter of 1 can still be 0 or 1.\n const jitter = rule.jitterMs > 0 ? random(namespace).int(0, Math.floor(rule.jitterMs)) : 0\n return rule.delayMs + jitter\n },\n }\n}\n", "import type { Clock, ClockState } from \"./clock.js\"\nimport {\n type BootPlan,\n type ClockPlan,\n ControlError,\n type ControlPlan,\n isRecord,\n type LatencyState,\n normalizeSeed,\n type SnapshotDocument,\n} from \"./controls.js\"\nimport {\n createFaultRegistry,\n type FaultListing,\n type FaultPreset,\n type FaultRegistry,\n type FaultRule,\n type FaultSnapshot,\n faultHasAction,\n normalizeFault,\n STANDARD_FAULT_PRESETS,\n} from \"./faults.js\"\nimport { createLatencyRegistry, type LatencyRegistry } from \"./latency.js\"\nimport { createRng, type Rng } from \"./rng.js\"\n\n/** The controls of a namespace that are plain settings, not registries. */\nexport type ControlSettings = {\n seed: number | string\n virtualTime: boolean\n autoAdvanceMs: number\n}\n\n/** Clock state as the admin API reports it. */\nexport type ControlClock = ClockState & {\n /** `now`, as ISO-8601. */\n iso: string\n /** Milliseconds the clock steps before every vendor request. */\n autoAdvanceMs: number\n}\n\n/** One namespace's controls: the body of `GET /__admin/controls`. */\nexport type ControlState = {\n namespace: string\n seed: number | string\n clock: ControlClock\n virtualTime: boolean\n latency: LatencyState\n faults: FaultListing[]\n}\n\n/**\n * A namespace's controls as a snapshot holds them. Every part is optional: restoring puts\n * back what is there and leaves the rest of the namespace as it is.\n */\nexport type ControlsSnapshot = {\n settings?: Partial<ControlSettings>\n /** Where the fault and latency streams stand. */\n streams?: { faults?: number; latency?: number }\n faults?: FaultSnapshot\n latency?: LatencyState\n}\n\n/** A change to a clock: {@link ClockPlan} plus the one-shot moves `POST /clock` accepts. */\nexport type ClockChange = ClockPlan & { advanceMs?: number; reset?: boolean }\n\n/** What a reboot puts back: everything a boot snapshot holds, or only its controls. */\nexport type BootScope = \"all\" | \"controls\"\n\nexport type NamespaceControls = {\n readonly faults: FaultRegistry\n readonly latency: LatencyRegistry\n /** Standard presets, with the service's own taking precedence. */\n readonly presets: Readonly<Record<string, FaultPreset>>\n /** Boot the namespace the first time it is used. Idempotent. */\n ensure(namespace: string): void\n settings(namespace: string): Readonly<ControlSettings>\n clock(namespace: string): ControlClock\n describe(namespace: string): ControlState\n /** Throw {@link ControlError} unless every part of `plan` can be applied. Changes nothing. */\n check(plan: ControlPlan): void\n /**\n * Apply seed, clock, virtual time, latency and faults. A given key replaces that control.\n * The whole plan is checked first, so a plan that is rejected has changed nothing.\n */\n apply(namespace: string, plan: ControlPlan): void\n changeClock(namespace: string, change: ClockChange): ControlClock\n /** Add one fault from an untrusted body: a rule, or `{\"preset\": \"<name>\", \u2026overrides}`. */\n addFault(namespace: string, input: unknown): FaultRule[]\n /** The rules one request scripts for itself in its headers. Nothing is stored. */\n scriptFaults(\n namespace: string,\n request: { fault?: Record<string, unknown>; timeoutMs?: number },\n ): FaultRule[]\n /** Restart every random stream of a namespace from `seed`. */\n reseed(namespace: string, seed: number | string): void\n /** Put a namespace back to what it was at boot: all of it, or only its controls. */\n reboot(namespace: string, scope?: BootScope): void\n /** Forget every namespace; each boots again when next used. */\n rebootAll(): void\n snapshot(namespace: string): Required<ControlsSnapshot>\n restore(namespace: string, snapshot: ControlsSnapshot): void\n /** Drop a namespace's controls entirely. */\n forget(namespace: string): void\n}\n\nexport type NamespaceControlsOptions = {\n /** What every stream starts from, unless a namespace is given a seed of its own. */\n seed: number | string\n clock(namespace: string): Clock\n boot?: BootPlan\n /** The service's presets. The standard ones fill in behind them. */\n presets?: Readonly<Record<string, FaultPreset>>\n /** How a fault waits on the wall clock, when the request does not say. */\n sleep?(ms: number): Promise<void>\n /** Reseed whatever else draws from the namespace's seed (the service's own stream). */\n onReseed?(namespace: string, seed: number | string): void\n /** A preset was switched on: do the part of it that is not a fault rule. */\n onPreset?(preset: FaultPreset, namespace: string, overrides: Partial<FaultRule>): void\n /** Put a snapshot document into a namespace: the boot `snapshot` control. */\n restoreDocument?(namespace: string, document: SnapshotDocument, scope: BootScope): void\n}\n\nconst NO_BOOT: BootPlan = { shared: {}, namespaces: {}, credentials: {} }\n\n/** What a rule does, without what it matches or when: all one request can script for itself. */\nconst ACTION = [\n \"status\",\n \"body\",\n \"headers\",\n \"delayMs\",\n \"jitterMs\",\n \"timeoutMs\",\n \"drop\",\n \"truncate\",\n \"effect\",\n \"params\",\n] as const\n\n/** Keys that choose requests. A fault in a header has already chosen its request. */\nconst CHOOSES_REQUESTS = [\n \"id\",\n \"operationId\",\n \"method\",\n \"path\",\n \"pathPrefix\",\n \"pathPattern\",\n \"requestHeaders\",\n \"query\",\n \"requestBody\",\n \"namespace\",\n \"after\",\n \"every\",\n \"count\",\n \"rate\",\n \"from\",\n \"until\",\n]\n\ntype Resolved = {\n /** `assign`: the rule takes the namespace's next `fault_<n>` id when it is stored. */\n rules: { rule: FaultRule; assign: boolean }[]\n preset?: { preset: FaultPreset; overrides: Partial<FaultRule> }\n}\n\n/**\n * Per-namespace seed, clock settings, latency and faults, and the one place a control\n * document is checked and applied \u2014 at boot, from `PUT /__admin/controls`, and from request\n * headers. It owns the seeded streams too: a namespace's seed lives here and nowhere else.\n */\nexport const createNamespaceControls = (options: NamespaceControlsOptions): NamespaceControls => {\n const boot = options.boot ?? NO_BOOT\n const presets: Record<string, FaultPreset> = { ...options.presets }\n for (const [name, preset] of Object.entries(STANDARD_FAULT_PRESETS)) presets[name] ??= preset\n\n const settings = new Map<string, ControlSettings>()\n const streams = new Map<string, { faults: Rng; latency: Rng }>()\n const ensured = new Set<string>()\n\n const settingsOf = (namespace: string): ControlSettings => {\n let found = settings.get(namespace)\n if (!found) {\n found = { seed: options.seed, virtualTime: false, autoAdvanceMs: 0 }\n settings.set(namespace, found)\n }\n return found\n }\n const streamsOf = (namespace: string) => {\n let found = streams.get(namespace)\n if (!found) {\n const { seed } = settingsOf(namespace)\n found = { faults: createRng(seed), latency: createRng(seed) }\n streams.set(namespace, found)\n }\n return found\n }\n const faults = createFaultRegistry((namespace) => streamsOf(namespace).faults, options.sleep)\n const latency = createLatencyRegistry((namespace) => streamsOf(namespace).latency)\n\n const reseed = (namespace: string, seed: number | string): void => {\n const next = normalizeSeed(seed)\n settingsOf(namespace).seed = next\n const own = streamsOf(namespace)\n own.faults.reseed(next)\n own.latency.reseed(next)\n options.onReseed?.(namespace, next)\n }\n\n const changeClock = (namespace: string, change: ClockChange): void => {\n const clock = options.clock(namespace)\n if (change.reset === true) {\n clock.reset()\n settingsOf(namespace).autoAdvanceMs = 0\n }\n // Freeze before applying mutations so a compound `{ now, frozen: true }` change is\n // atomic. Setting a live clock adjusts its offset; freezing it afterward would read the\n // source again and could pin it a millisecond past the requested instant.\n if (change.frozen === true) clock.freeze()\n if (change.now !== undefined) clock.set(change.now)\n if (change.advanceMs !== undefined) clock.advance(change.advanceMs)\n if (change.frozen === false) clock.unfreeze()\n if (change.autoAdvanceMs !== undefined)\n settingsOf(namespace).autoAdvanceMs = change.autoAdvanceMs\n }\n\n /** A rule or a preset reference, as the rules it stands for. Checks everything; stores nothing. */\n const resolve = (namespace: string, input: unknown, now: number): Resolved => {\n if (!isRecord(input)) throw new ControlError(\"fault: expected an object\")\n if (typeof input.preset !== \"string\") {\n const rule = normalizeFault(input, {\n id: \"unassigned\",\n // Scoped to the caller's namespace unless it asks for every one, so one worker's\n // injected failure never lands on another's request.\n namespace,\n now,\n strict: true,\n })\n if (!faultHasAction(rule))\n throw new ControlError(\n \"a fault needs a status, a delay, a timeout, drop: true, truncate, an effect, or a preset\",\n )\n return { rules: [{ rule, assign: typeof input.id !== \"string\" }] }\n }\n const { preset: name, ...given } = input\n const preset = presets[name]\n if (!preset)\n throw new ControlError(\n `no fault preset ${JSON.stringify(name)}; known: ${Object.keys(presets).join(\", \")}`,\n )\n // Both sides in stored form first, so an override wins whichever spelling it uses.\n const { id, ...overrides } = normalizeFault(\n { ...given, id: given.id ?? name },\n { now, strict: true },\n )\n const rules = preset.rules ?? []\n return {\n preset: { preset, overrides },\n rules: rules.map((each, index) => {\n const { id: _id, ...base } = normalizeFault({ ...each, id: name }, { now })\n return {\n assign: false,\n rule: {\n namespace,\n ...base,\n ...overrides,\n fromPreset: name,\n id: `${id}${rules.length > 1 ? `_${index + 1}` : \"\"}`,\n },\n }\n }),\n }\n }\n\n const store = (namespace: string, resolved: Resolved): FaultRule[] => {\n const added = resolved.rules.map(({ rule, assign }) =>\n // Only a rule that is accepted takes the next id, so a rejected request leaves no gap.\n faults.add(assign ? { ...rule, id: faults.nextId(rule.namespace ?? namespace) } : rule),\n )\n if (resolved.preset)\n options.onPreset?.(resolved.preset.preset, namespace, resolved.preset.overrides)\n return added\n }\n\n const check = (plan: ControlPlan): void => {\n for (const each of (plan.faults ?? []) as readonly unknown[]) {\n // A document is one namespace's controls. A rule for every namespace would be added\n // again each time another namespace booted or reset.\n if (isRecord(each) && each.namespace === \"*\")\n throw new ControlError(\n 'faults: a control document cannot hold a \"*\" rule; add it with POST /faults',\n )\n resolve(\"default\", each, 0)\n }\n }\n\n /** Apply a plan that has been checked. `replace` clears the namespace's rules first. */\n const commit = (namespace: string, plan: ControlPlan, replace: boolean): void => {\n if (plan.seed !== undefined) reseed(namespace, plan.seed)\n if (plan.clock !== undefined) changeClock(namespace, plan.clock)\n if (plan.virtualTime !== undefined) settingsOf(namespace).virtualTime = plan.virtualTime\n if (plan.latency !== undefined) latency.set(namespace, plan.latency)\n if (plan.faults !== undefined) {\n if (replace) faults.clear(namespace)\n // Resolved now, not when checked: a window given as a duration counts from the clock\n // this same plan may just have moved.\n const now = options.clock(namespace).now()\n for (const each of plan.faults as readonly Record<string, unknown>[])\n store(namespace, resolve(namespace, { ...each, namespace }, now))\n }\n }\n\n /** The namespace's boot plan: the shared controls with its own overrides on top. */\n const bootPlan = (namespace: string): ControlPlan => ({\n ...boot.shared,\n ...boot.namespaces[namespace],\n })\n\n const start = (namespace: string, scope: BootScope): void => {\n ensured.add(namespace)\n const { snapshot, ...plan } = bootPlan(namespace)\n // Rules a caller added in process before the namespace's first use are kept, after the\n // rules it boots with.\n const early = faults.snapshot(namespace).rules\n if (early.length > 0) faults.clear(namespace)\n // The snapshot first, so a control named beside it wins over the one it carries.\n if (snapshot) options.restoreDocument?.(namespace, snapshot, scope)\n commit(namespace, plan, true)\n for (const { remaining: _r, hits: _h, seen: _s, position: _p, ...rule } of early)\n faults.add(rule)\n }\n\n const ensure = (namespace: string): void => {\n if (!ensured.has(namespace)) start(namespace, \"all\")\n }\n\n const clockOf = (namespace: string): ControlClock => {\n ensure(namespace)\n const state = options.clock(namespace).state()\n return {\n ...state,\n iso: new Date(state.now).toISOString(),\n autoAdvanceMs: settingsOf(namespace).autoAdvanceMs,\n }\n }\n\n const wipe = (namespace: string): void => {\n faults.clear(namespace)\n latency.clear(namespace)\n settings.delete(namespace)\n streams.delete(namespace)\n ensured.delete(namespace)\n }\n\n // Fail when the runtime is created, not on the first request to hit a bad boot rule.\n check(boot.shared)\n for (const plan of Object.values(boot.namespaces)) check(plan)\n\n return {\n faults,\n latency,\n presets,\n ensure,\n settings(namespace) {\n ensure(namespace)\n return settingsOf(namespace)\n },\n clock: clockOf,\n describe(namespace) {\n ensure(namespace)\n const current = settingsOf(namespace)\n return {\n namespace,\n seed: current.seed,\n clock: clockOf(namespace),\n virtualTime: current.virtualTime,\n latency: latency.get(namespace),\n faults: faults.list(namespace),\n }\n },\n check,\n apply(namespace, plan) {\n check(plan)\n ensure(namespace)\n commit(namespace, plan, true)\n },\n changeClock(namespace, change) {\n ensure(namespace)\n changeClock(namespace, change)\n return clockOf(namespace)\n },\n addFault(namespace, input) {\n ensure(namespace)\n return store(namespace, resolve(namespace, input, options.clock(namespace).now()))\n },\n scriptFaults(namespace, request) {\n const rules: FaultRule[] = []\n if (request.fault) {\n if (typeof request.fault.preset !== \"string\") {\n const chooses = CHOOSES_REQUESTS.find((key) => key in (request.fault ?? {}))\n if (chooses)\n throw new ControlError(\n `fault: ${chooses} has no meaning here; a fault in a header is for its own request`,\n )\n }\n // A preset's rules say which requests to fault. This request has already been chosen.\n for (const { rule } of resolve(namespace, request.fault, 0).rules) {\n const action: FaultRule = { id: \"request\" }\n for (const key of ACTION)\n if (rule[key] !== undefined) Object.assign(action, { [key]: rule[key] })\n rules.push(action)\n }\n }\n if (request.timeoutMs !== undefined)\n rules.push({ id: \"request\", timeoutMs: request.timeoutMs })\n return rules\n },\n reseed(namespace, seed) {\n ensure(namespace)\n reseed(namespace, seed)\n },\n reboot(namespace, scope = \"all\") {\n wipe(namespace)\n options.clock(namespace).reset()\n options.onReseed?.(namespace, options.seed)\n start(namespace, scope)\n },\n rebootAll() {\n const known = new Set([...ensured, ...settings.keys()])\n faults.clear()\n latency.clear()\n settings.clear()\n streams.clear()\n ensured.clear()\n for (const namespace of known) {\n options.clock(namespace).reset()\n options.onReseed?.(namespace, options.seed)\n }\n },\n snapshot(namespace) {\n ensure(namespace)\n const own = streamsOf(namespace)\n return {\n settings: { ...settingsOf(namespace) },\n streams: { faults: own.faults.state(), latency: own.latency.state() },\n faults: faults.snapshot(namespace),\n latency: latency.get(namespace),\n }\n },\n restore(namespace, snapshot) {\n ensure(namespace)\n const { seed, ...rest } = snapshot.settings ?? {}\n Object.assign(settingsOf(namespace), rest)\n // The seed first: it restarts the streams, and their positions are set after it.\n if (seed !== undefined) reseed(namespace, seed)\n const own = streamsOf(namespace)\n if (snapshot.streams?.faults !== undefined) own.faults.setState(snapshot.streams.faults)\n if (snapshot.streams?.latency !== undefined) own.latency.setState(snapshot.streams.latency)\n if (snapshot.faults) faults.restore(namespace, snapshot.faults)\n if (snapshot.latency) latency.set(namespace, snapshot.latency)\n },\n forget: wipe,\n }\n}\n", "/**\n * HMAC and encoding primitives for vendor webhook signatures, over WebCrypto so they run\n * wherever the mocks do (Node, Bun, workers).\n */\n\nexport type HmacAlgorithm = \"SHA-1\" | \"SHA-256\" | \"SHA-512\"\nexport type ByteEncoding = \"hex\" | \"base64\"\n\nconst encoder = new TextEncoder()\n\nexport const toBase64 = (bytes: ArrayBuffer | Uint8Array): string => {\n let binary = \"\"\n for (const byte of bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes)) {\n binary += String.fromCharCode(byte)\n }\n return btoa(binary)\n}\n\nexport const fromBase64 = (value: string): Uint8Array =>\n Uint8Array.from(atob(value), (char) => char.charCodeAt(0))\n\nexport const toHex = (bytes: ArrayBuffer | Uint8Array): string =>\n [...(bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes))]\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\")\n\nconst keyBytes = (key: string | Uint8Array): Uint8Array =>\n typeof key === \"string\" ? encoder.encode(key) : key\n\n/** HMAC of `message` under `key` (a UTF-8 string or raw bytes), encoded as hex or base64. */\nexport const hmac = async (\n algorithm: HmacAlgorithm,\n key: string | Uint8Array,\n message: string | Uint8Array,\n encoding: ByteEncoding = \"hex\",\n): Promise<string> => {\n const imported = await crypto.subtle.importKey(\n \"raw\",\n keyBytes(key) as BufferSource,\n { name: \"HMAC\", hash: algorithm },\n false,\n [\"sign\"],\n )\n const signed = await crypto.subtle.sign(\n \"HMAC\",\n imported,\n (typeof message === \"string\" ? encoder.encode(message) : message) as BufferSource,\n )\n return encoding === \"hex\" ? toHex(signed) : toBase64(signed)\n}\n\n/** SHA digest of `input`, hex-encoded. */\nexport const sha = async (\n algorithm: \"SHA-1\" | \"SHA-256\" | \"SHA-512\",\n input: string | Uint8Array,\n): Promise<string> =>\n toHex(\n await crypto.subtle.digest(\n algorithm,\n (typeof input === \"string\" ? encoder.encode(input) : input) as BufferSource,\n ),\n )\n\n/**\n * The raw key of a Svix-style secret: `whsec_<base64>` (Svix, Resend, Junction) or\n * `fwhsec_<base64>` (Flex). A bare base64 secret is accepted too.\n */\nexport const svixSecretBytes = (secret: string): Uint8Array => {\n const raw = secret.replace(/^f?whsec_/, \"\")\n try {\n return fromBase64(raw)\n } catch {\n throw new TypeError(\"webhook secret must be whsec_<base64> (as Svix issues it)\")\n }\n}\n\n/** `v1,<base64 HMAC-SHA256>` over `\"<id>.<timestamp>.<body>\"`, as Svix signs. */\nexport const signSvix = async (\n secret: string,\n messageId: string,\n timestampSeconds: number,\n body: string,\n): Promise<string> =>\n `v1,${await hmac(\"SHA-256\", svixSecretBytes(secret), `${messageId}.${timestampSeconds}.${body}`, \"base64\")}`\n\n/** `t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<body>\")>`, as Stripe (and Persona) sign. */\nexport const signTimestamped = async (\n secret: string,\n timestampSeconds: number,\n body: string,\n): Promise<string> =>\n `t=${timestampSeconds},v1=${await hmac(\"SHA-256\", secret, `${timestampSeconds}.${body}`, \"hex\")}`\n\n/**\n * Twilio's `X-Twilio-Signature`: base64 HMAC-SHA1 of the full URL followed by every form\n * parameter as `key + value`, keys sorted. Sign against the public URL the app is\n * configured with, not the address the request is actually posted to.\n */\nexport const signTwilio = async (\n authToken: string,\n url: string,\n params: Record<string, string>,\n): Promise<string> => {\n const payload =\n url +\n Object.keys(params)\n .sort()\n .map((key) => `${key}${params[key]}`)\n .join(\"\")\n return hmac(\"SHA-1\", authToken, payload, \"base64\")\n}\n\n/** Constant-time string comparison, so a verifier in a test double does not leak timing. */\nexport const timingSafeEqual = (a: string, b: string): boolean => {\n if (a.length !== b.length) return false\n let diff = 0\n for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i)\n return diff === 0\n}\n", "import type { SqliteClient } from \"@crvouga/mockingbird-sqlite\"\nimport type { Clock, ClockState } from \"./clock.js\"\nimport type { ControlHeaderInput, MockControls, NamespaceControls } from \"./controls.js\"\nimport type { CredentialRegistry } from \"./credentials.js\"\nimport type { FaultRegistry, FaultRule } from \"./faults.js\"\nimport type { Journal } from \"./journal.js\"\nimport type { LatencyRegistry } from \"./latency.js\"\nimport type { Metrics } from \"./metrics.js\"\nimport type { Rng } from \"./rng.js\"\nimport type { NamespaceSnapshot } from \"./snapshot.js\"\nimport type { StateView } from \"./state-view.js\"\n\n/**\n * What every mock can be called with. A service may accept more fields \u2014 accounts,\n * catalogs, webhook endpoints \u2014 and those stay optional so `createRuntime()` and\n * `createRuntime({ seed, adminKey })` work everywhere.\n */\nexport type MockCreateOptions = {\n sqlite?: SqliteClient\n clock?: Clock\n seed?: number | string\n /** All internal HTTP paths live below this prefix. Default /__admin. */\n adminPrefix?: string\n adminKey?: string\n /**\n * Admin controls to boot with: clock, latency, faults, seed, a starting snapshot, and\n * per-namespace overrides. `POST /__admin/reset` returns to exactly this.\n */\n adminControls?: MockControls\n}\n\n/** A named snapshot, as the admin API and `runtime.snapshots` list it. */\nexport type MockSnapshotInfo = {\n readonly id: string\n readonly namespace: string\n readonly records: number\n readonly at: number\n readonly portable: boolean\n}\n\n/** One namespace's controls, as `GET /__admin/controls` and `runtime.controls()` report them. */\nexport type MockControlState = {\n readonly namespace: string\n readonly seed: number | string\n readonly clock: ClockState & { iso: string; autoAdvanceMs: number }\n readonly virtualTime: boolean\n readonly latency: unknown\n readonly faults: readonly unknown[]\n readonly snapshots: readonly MockSnapshotInfo[]\n}\n\n/** A checkpoint head the admin client can show. Services may return a richer object. */\nexport type MockCheckpoint = {\n readonly id: string\n readonly branch: string\n readonly parent: string | null\n readonly at: number\n}\n\n/** The instance behind one namespace. Vendor methods sit beside these, not instead of them. */\nexport type MockInstanceSurface = {\n fetch(request: Request): Promise<Response>\n reset(): Promise<void>\n}\n\n/**\n * The interface every mock runtime implements.\n *\n * Assignability is one way: a service may add methods (`tick`, a typed webhook hub,\n * account directories) and narrower property types. Removing or renaming a member\n * fails the typecheck. The HTTP control plane (`/__admin/health`, `/__admin/*`) is the same\n * contract on the wire; {@link STANDARD_ADMIN_ROUTES} is that list.\n */\nexport type MockSurface = {\n readonly name: string\n fetch(request: Request): Promise<Response>\n readonly clock: Clock\n readonly faults: FaultRegistry\n /** Baseline response time per namespace. */\n readonly latency: LatencyRegistry\n readonly metrics: Metrics\n readonly journal: Journal\n readonly rng: Rng\n readonly credentials: CredentialRegistry\n /** Present on every runtime. `undefined` when the service has no outbound webhooks. */\n readonly webhooks: unknown\n applyPreset(name: string, namespace?: string, overrides?: Partial<FaultRule>): FaultRule[]\n instance(namespace?: string): MockInstanceSurface\n namespaces(): string[]\n reset(namespace?: string): Promise<void>\n /** A namespace's clock: the base clock for `default`, its own for any other. */\n namespaceClock(namespace?: string): Clock\n /** A namespace's controls: seed, clock, virtual time, latency, faults and snapshots. */\n controls(namespace?: string): MockControlState\n /** Apply a control document to a namespace. A given key replaces that control. */\n configure(controls: NamespaceControls, namespace?: string): MockControlState\n /** Named snapshots of a namespace: records, clock, random streams, faults and latency. */\n readonly snapshots: {\n create(options?: { name?: string; namespace?: string }): MockSnapshotInfo\n list(namespace?: string): MockSnapshotInfo[]\n restore(id: string, namespace?: string): void\n delete(id: string, namespace?: string): boolean\n }\n /** Request headers that carry controls, checked: spread them into a `fetch` or an SDK's defaults. */\n headers(input: ControlHeaderInput): Record<string, string>\n snapshot(namespace?: string): NamespaceSnapshot\n restore(snapshot: NamespaceSnapshot, namespace?: string): void\n checkpoint(namespace?: string, branch?: string): MockCheckpoint\n branch(name: string, options?: { namespace?: string; at?: string }): MockCheckpoint\n checkout(checkpoint: string, options?: { namespace?: string; branch?: string }): void\n timeline(namespace?: string): {\n head(branch?: string): { readonly id: string } | undefined\n branches(): Readonly<Record<string, string>>\n }\n /** Collections in `namespace`, declared by the service and inferred from stored rows. */\n state(namespace?: string): StateView\n readonly sqlite: SqliteClient\n}\n\n/**\n * Keep a service's own runtime type while proving it is a {@link MockSurface}.\n * Extra members stay. A missing member is a type error at the definition.\n */\nexport const defineMock = <T extends MockSurface>(runtime: T): T => runtime\n\n/** Clock state is part of the surface so admin clients can render it without a cast. */\nexport type MockClockState = ClockState\n\n/**\n * What each shared admin route does. `GET /__admin` serves this list, and the guide in\n * `docs/ADMIN_CONTROLS.md` is checked against it.\n */\nexport const ADMIN_ROUTE_REFERENCE = {\n \"GET /\": \"This index: every route and control header, with a one-line summary each.\",\n \"GET /health\": \"Readiness. Never needs the admin key or a vendor credential.\",\n \"GET /controls\":\n \"The namespace's controls in one document: seed, clock, virtual time, latency, faults, snapshots.\",\n \"PUT /controls\":\n \"Apply a control document. Each key given replaces that control; `snapshot` replaces the records.\",\n \"DELETE /controls\": \"Put the namespace's controls back to boot. Records are untouched.\",\n \"POST /reset\":\n \"Return the namespace to its boot state: records, controls, snapshots, journal, metrics. `?all=1` resets every namespace.\",\n \"GET /namespaces\": \"The isolation keys in use.\",\n \"DELETE /namespaces/:name\": \"Reset a namespace and forget it.\",\n \"GET /clock\": \"The namespace clock: `now`, `iso`, `frozen`, `offsetMs`, `autoAdvanceMs`.\",\n \"POST /clock\":\n \"Move time: `now` (or `set`), `advance`, `frozen` (or `freeze`), `autoAdvance`, `reset`.\",\n \"GET /latency\": \"The namespace's baseline response time.\",\n \"PUT /latency\": \"Set it: `delay`, seeded `jitter`, and per-operation `operations`.\",\n \"DELETE /latency\": \"Remove it.\",\n \"GET /faults\": \"Fault rules that can hit this namespace. `?all=1` lists every namespace's.\",\n \"POST /faults\": 'Add a fault rule, or a preset with `{\"preset\": \"<name>\"}`.',\n \"PUT /faults\": 'Replace the namespace\\'s fault rules with `{\"faults\": [...]}`.',\n \"DELETE /faults\":\n \"Remove the namespace's fault rules. `?id=` removes one; `?all=1` every namespace's.\",\n \"GET /faults/presets\": \"Named faults this emulator answers to.\",\n \"POST /faults/presets/:name\": \"Switch a preset on. The body overrides its fields.\",\n \"GET /faults/:id\": \"One fault rule, with its `hits`, `seen` and `remaining` counters.\",\n \"DELETE /faults/:id\": \"Remove one fault rule.\",\n \"GET /snapshots\": \"The namespace's snapshots.\",\n \"POST /snapshots\":\n 'Snapshot the namespace: records, clock, random streams, faults, latency. `{\"name\"}` names it.',\n \"GET /snapshots/:id\": \"A snapshot as portable JSON.\",\n \"PUT /snapshots/:id\": \"Store a snapshot document under this id, without restoring it.\",\n \"POST /snapshots/:id/restore\": \"Replace the namespace with a snapshot.\",\n \"DELETE /snapshots/:id\": \"Delete a snapshot.\",\n \"GET /timeline\": \"The namespace's checkpoint history and branches.\",\n \"POST /checkpoints\": \"Checkpoint a branch now. Successful mutations do this automatically.\",\n \"POST /branches/:name\": \"Create a copy-on-write branch, optionally from a checkpoint (`at`).\",\n \"POST /branches/:name/checkout\": \"Move a branch to a checkpoint.\",\n \"GET /requests\":\n \"The request journal. Filter with `operationId`, `method`, `path`, `status`, `faultId`, `since`, `limit`; `?all=1` for every namespace.\",\n \"DELETE /requests\": \"Clear the journal.\",\n \"GET /metrics\": \"Request counts and unmatched paths, for every namespace or the one named.\",\n \"DELETE /metrics\": \"Clear them.\",\n \"GET /credentials\": \"Vendor credential \u2192 namespace mappings, masked.\",\n \"PUT /credentials\": \"Map vendor credentials to namespaces, for SDKs that cannot send a header.\",\n \"DELETE /credentials\": \"Remove one mapping (`?credential=`) or all.\",\n \"GET /state\": \"The namespace's collections: declared shape and stored rows.\",\n \"GET /state/:collection\": \"A page of rows.\",\n \"GET /state/:collection/:id\": \"One row.\",\n \"POST /state/:collection\": \"Create a row from `{id?, value}`.\",\n \"PUT /state/:collection/:id\": \"Replace a row.\",\n \"PATCH /state/:collection/:id\": \"Shallow-merge into a row.\",\n \"DELETE /state/:collection/:id\": \"Delete a row.\",\n \"GET /ui\": \"The admin UI.\",\n \"GET /ui/\": \"The admin UI.\",\n \"GET /ui/manifest\": \"The admin UI's panels and extensions.\",\n} as const\n\n/**\n * Admin routes every mock answers. A service adds its own keys beside these.\n * A key in this list keeps the shared handler, so the state API and the admin UI\n * stay the same when a service also ships vendor-specific controls.\n */\nexport const STANDARD_ADMIN_ROUTES = Object.keys(\n ADMIN_ROUTE_REFERENCE,\n) as readonly (keyof typeof ADMIN_ROUTE_REFERENCE)[]\n\nexport type StandardAdminRoute = (typeof STANDARD_ADMIN_ROUTES)[number]\n\n/**\n * A contribution the admin shell mounts beside the shared views.\n * `panel` is author-owned markup. `sql` turns on the built-in table explorer\n * and query runner, which call `GET /sql/tables` and `POST /sql/query`.\n * `route` presents an admin action with the shell's prebuilt form and response view.\n */\nexport type AdminExtension =\n | {\n kind: \"route\"\n id: string\n title: string\n description?: string\n /** An existing admin route, including its method and any path parameters. */\n route: string\n /** Initial JSON body shown in the request form. */\n body?: unknown\n }\n | {\n kind: \"panel\"\n id: string\n title: string\n description?: string\n html: string\n script?: string\n }\n | {\n kind: \"sql\"\n /** DOM id suffix. Default `sql`. */\n id?: string\n title?: string\n description?: string\n }\n\n/** A panel the default admin shell mounts after the shared views. */\nexport type AdminPanel = {\n /** DOM id suffix. Lowercase letters, digits, and hyphens. */\n id: string\n title: string\n description?: string\n /** Markup placed inside the panel body. The service author owns it. */\n html: string\n /**\n * Function body called as `(root, api) => void` once the shell has loaded.\n * `root` is the panel body. `api` is `{ get, send, namespace }` against `/__admin`.\n */\n script?: string\n}\n\n/**\n * How a service customizes the admin UI without leaving the shared shell.\n * `panels` add views. `render` replaces the document and can call `defaultHtml()`\n * to wrap the shared shell instead of discarding it.\n */\nexport type AdminUi = {\n panels?: readonly AdminPanel[]\n /** First-class shell contributions. `sql` mounts the shared database explorer. */\n extensions?: readonly AdminExtension[]\n render?: (input: { service: string; defaultHtml: () => string }) => string\n}\n\nconst PANEL_ID = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/\nconst RESERVED_VIEWS = new Set([\n \"overview\",\n \"manual\",\n \"state\",\n \"clock\",\n \"latency\",\n \"faults\",\n \"snapshots\",\n \"journal\",\n \"routes\",\n \"checkpoints\",\n])\n\nconst checkPanel = (\n panel: { id: string; title: string },\n seen: Set<string>,\n label: string,\n): void => {\n if (!PANEL_ID.test(panel.id)) {\n throw new RangeError(`${label} id must match ${PANEL_ID}: ${JSON.stringify(panel.id)}`)\n }\n if (RESERVED_VIEWS.has(panel.id)) {\n throw new RangeError(`${label} id ${panel.id} is reserved by the admin shell`)\n }\n if (seen.has(panel.id)) throw new RangeError(`duplicate admin view id ${panel.id}`)\n seen.add(panel.id)\n if (panel.title.trim() === \"\") throw new RangeError(`${label} ${panel.id} needs a title`)\n}\n\n/** Reject a panel or extension the shell cannot mount. Called when the runtime is created. */\nexport const assertAdminUi = (ui: AdminUi | undefined): void => {\n if (!ui) return\n const seen = new Set<string>()\n for (const panel of ui.panels ?? []) checkPanel(panel, seen, \"admin panel\")\n for (const extension of ui.extensions ?? []) {\n if (extension.kind === \"panel\" || extension.kind === \"route\") {\n checkPanel(extension, seen, \"admin extension\")\n if (\n extension.kind === \"route\" &&\n !/^(GET|POST|PUT|PATCH|DELETE) \\/\\S*$/.test(extension.route)\n )\n throw new RangeError(`admin extension ${extension.id} needs a method and route path`)\n continue\n }\n const id = extension.id ?? \"sql\"\n checkPanel({ id, title: extension.title ?? \"SQL\" }, seen, \"admin extension\")\n }\n}\n", "import type { Clock } from \"./clock.js\"\nimport {\n assertSnapshotDocument,\n CONTROL_HEADER_REFERENCE,\n CONTROL_HEADERS,\n ControlError,\n type ControlPlan,\n durationMs,\n isRecord,\n KEY_PATTERN,\n normalizeClock,\n normalizeControls,\n normalizeLatency,\n parseInstant,\n type SnapshotDocument,\n} from \"./controls.js\"\nimport type { FaultPresetList } from \"./faults.js\"\nimport type { Journal } from \"./journal.js\"\nimport type { Metrics } from \"./metrics.js\"\nimport { createNamespaceControls, type NamespaceControls } from \"./namespace-controls.js\"\nimport { timingSafeEqual } from \"./signing.js\"\nimport { ADMIN_ROUTE_REFERENCE } from \"./surface.js\"\n\nexport { parseDuration } from \"./controls.js\"\n\n/** Unauthenticated readiness probe, served ahead of every vendor auth gate. */\nexport const HEALTH_PATH = \"/__admin/health\"\n/** Prefix of every control-plane route; never part of a vendor contract. */\nexport const ADMIN_PREFIX = \"/__admin\"\n/** Resolve once at construction; ambiguous URL forms are never accepted. */\nexport const resolveAdminPrefix = (prefix: string = ADMIN_PREFIX): string => {\n if (!/^\\/[A-Za-z0-9_-]+(?:\\/[A-Za-z0-9_-]+)*$/.test(prefix)) {\n throw new Error(\n \"adminPrefix must be an absolute non-root path of literal segments, without a trailing slash\",\n )\n }\n return prefix\n}\n\n/** Segment-boundary matching prevents /__administer from entering the control plane. */\nexport const isAdminPath = (path: string, prefix: string): boolean =>\n path === prefix || path.startsWith(`${prefix}/`)\n\n/** SDK base URL namespace carrier, entirely inside the configured internal route tree. */\nexport const matchNamespacePath = (path: string, prefix: string): RegExpExecArray | null =>\n /^\\/ns\\/([^/]+)(\\/.*)?$/.exec(isAdminPath(path, prefix) ? path.slice(prefix.length) : \"\")\n\n/** Fail before serving when the declared vendor contract overlaps the reserved tree. */\nexport const assertAdminPrefixAvailable = (prefix: string, paths: readonly string[]): void => {\n const reserved = prefix.split(\"/\").slice(1)\n for (const path of paths) {\n const segments = path.split(\"/\").slice(1)\n // Catch-all vendor roots (e.g. S3 /{bucket}/{key}) share the listener.\n // The internal tree is reserved before vendor dispatch, regardless of the wildcard.\n if (segments.length < reserved.length || /^\\{[^}]+\\}$/.test(segments[0] ?? \"\")) continue\n if (\n reserved.every((part, i) => segments[i] === part || /^\\{[^}]+\\}$/.test(segments[i] ?? \"\"))\n ) {\n throw new Error(\n `vendor route ${path} collides with adminPrefix ${prefix}; choose a different adminPrefix`,\n )\n }\n }\n}\n\n/** Carries the admin key, which is separate from any vendor credential. */\nexport const ADMIN_KEY_HEADER = CONTROL_HEADERS.adminKey\n/** The admin shell's brand catalog, under the admin prefix. Public, like the shell. */\nexport const ADMIN_BRANDS_PATH = \"/ui/brands.json\"\n\n/**\n * Whether `headers` carry `adminKey`. Constant-time, so response timing does not tell a caller\n * how many leading characters of a guess were right.\n */\nexport const hasAdminKey = (headers: Headers, adminKey: string): boolean => {\n const sent = headers.get(ADMIN_KEY_HEADER)\n return sent !== null && timingSafeEqual(sent, adminKey)\n}\n/** Selects the isolated namespace a request reads and writes. */\nexport const NAMESPACE_HEADER = CONTROL_HEADERS.namespace\n/** Where the admin controls are documented, for people and agents. */\nexport const ADMIN_DOCS_URL = \"https://mockingbird.chrisvouga.dev/docs/admin-controls\"\n\n/**\n * The guide's page for each control, with the shared routes (by first path segment) and the\n * request headers that page defines. `GET /__admin` links every route and header to its page,\n * and the guide in `docs/admin-controls/` is checked against this list.\n */\nexport const ADMIN_CONTROL_PAGES: readonly {\n page: string\n title: string\n routes: readonly string[]\n headers: readonly string[]\n}[] = [\n {\n page: \"namespaces\",\n title: \"Namespaces\",\n routes: [\"/namespaces\", \"/credentials\"],\n headers: [CONTROL_HEADERS.namespace],\n },\n { page: \"reset\", title: \"Reset\", routes: [\"/reset\"], headers: [CONTROL_HEADERS.reset] },\n {\n page: \"snapshot-and-restore\",\n title: \"Snapshot and restore\",\n routes: [\"/snapshots\"],\n headers: [CONTROL_HEADERS.restore, CONTROL_HEADERS.snapshot],\n },\n {\n page: \"clock\",\n title: \"Clock\",\n routes: [\"/clock\"],\n headers: [CONTROL_HEADERS.time, CONTROL_HEADERS.advance],\n },\n {\n page: \"checkpoints-and-branches\",\n title: \"Checkpoints and branches\",\n routes: [\"/timeline\", \"/checkpoints\", \"/branches\"],\n headers: [CONTROL_HEADERS.branch, CONTROL_HEADERS.at],\n },\n { page: \"faults\", title: \"Faults\", routes: [\"/faults\"], headers: [CONTROL_HEADERS.fault] },\n {\n page: \"latency-and-timeouts\",\n title: \"Latency and timeouts\",\n routes: [\"/latency\"],\n headers: [CONTROL_HEADERS.delay, CONTROL_HEADERS.timeout, CONTROL_HEADERS.virtualTime],\n },\n {\n page: \"seed-and-determinism\",\n title: \"Seed and determinism\",\n routes: [],\n headers: [CONTROL_HEADERS.seed],\n },\n { page: \"control-document\", title: \"The control document\", routes: [\"/controls\"], headers: [] },\n { page: \"boot\", title: \"Boot\", routes: [], headers: [] },\n { page: \"request-headers\", title: \"Request headers\", routes: [], headers: [] },\n {\n page: \"journal-and-state\",\n title: \"Journal, metrics and state\",\n routes: [\"/requests\", \"/metrics\", \"/state\", \"/ui\"],\n headers: [],\n },\n {\n page: \"reference\",\n title: \"Reference\",\n routes: [\"/\", \"/health\"],\n headers: [CONTROL_HEADERS.adminKey],\n },\n]\n\nconst pageUrl = (page: string): string => `${ADMIN_DOCS_URL}/${page}`\n\n/** The guide page that defines a shared route (`\"GET /snapshots/:id\"`), if it is one. */\nconst routeDocs = (route: string): string | undefined => {\n if (!Object.hasOwn(ADMIN_ROUTE_REFERENCE, route)) return undefined\n const path = route.slice(route.indexOf(\" \") + 1)\n const segment = `/${path.split(\"/\")[1] ?? \"\"}`\n const found = ADMIN_CONTROL_PAGES.find((each) => each.routes.includes(segment))\n return found && pageUrl(found.page)\n}\n\nconst headerDocs = (header: string): string | undefined => {\n const found = ADMIN_CONTROL_PAGES.find((each) => each.headers.includes(header))\n return found && pageUrl(found.page)\n}\n\nexport type AdminRequest = {\n request: Request\n url: URL\n /** `:param` segments of the matched route. */\n params: Record<string, string>\n /** Namespace the request targets: `?namespace=`, then the header, then the default. */\n namespace: string\n /** Parsed JSON body, or `undefined` when there is none. */\n body: unknown\n}\n\nexport type AdminRoute = (request: AdminRequest) => Response | Promise<Response>\n\n/**\n * Service-specific admin routes, keyed `METHOD /path` relative to `/__admin`, with\n * `:param` segments \u2014 e.g. `\"POST /orders/:id/transition\"`.\n */\nexport type AdminRoutes = Record<string, AdminRoute>\n\n/** What `GET /__admin/snapshots` lists for each snapshot. */\nexport type SnapshotInfo = {\n id: string\n namespace: string\n /** Stored rows in the snapshot. */\n records: number\n /** The namespace clock when it was taken, epoch ms. */\n at: number\n /** Whether `GET /snapshots/:id` can return it as a {@link SnapshotDocument}. */\n portable: boolean\n}\n\n/** Named snapshots of a namespace. Ids are unique within a namespace, never across them. */\nexport type SnapshotStore = {\n /** Capture the namespace now. Reusing an id replaces that snapshot. */\n create(namespace: string, id?: string): SnapshotInfo\n list(namespace: string): SnapshotInfo[]\n get(namespace: string, id: string): SnapshotInfo | undefined\n /** The snapshot as portable JSON; `undefined` when there is none or it cannot leave the process. */\n export(namespace: string, id: string): SnapshotDocument | undefined\n /** Store a document as a snapshot without restoring it. Throws {@link ControlError}. */\n import(namespace: string, id: string | undefined, document: SnapshotDocument): SnapshotInfo\n /** Replace the namespace with the snapshot. `false` when there is none. */\n restore(namespace: string, id: string): boolean\n remove(namespace: string, id: string): boolean\n /** Forget one namespace's snapshots, or every namespace's. */\n clear(namespace?: string): void\n}\n\nexport type ControlContext = {\n name: string\n startedAt: number\n wallNow: () => number\n clock: Clock\n namespaceClock?(namespace: string): Clock\n metrics: Metrics\n journal: Journal\n defaultNamespace: string\n namespaces(): string[]\n reset(namespace: string | \"*\"): Promise<void>\n timeTravel: {\n checkpoint(\n namespace: string,\n branch: string,\n ): { id: string; branch: string; parent: string | null; at: number; records?: number }\n branch(\n name: string,\n options: { namespace: string; at?: string },\n ): { id: string; branch: string; parent: string | null; at: number }\n checkout(checkpoint: string, options: { namespace: string; branch: string }): void\n retain(namespace: string, checkpoint: string): void\n release(namespace: string, checkpoint: string): boolean\n inspect(namespace: string): {\n branches: Readonly<Record<string, string>>\n checkpoints: readonly { id: string; branch: string; parent: string | null; at: number }[]\n }\n }\n /** Extra fields for `GET /__admin/health`, such as the loaded corpus version. */\n describe(): Record<string, unknown>\n routes: AdminRoutes\n adminPrefix?: string\n adminKey: string | undefined\n /** Reported by `GET /__admin`. */\n version?: string\n /**\n * Per-namespace seed, clock settings, latency and faults. Default: controls over this\n * context's clock, with the standard presets and no boot controls.\n */\n controls?: NamespaceControls\n /** Named snapshots. Default: pinned `timeTravel` checkpoints, which are not portable. */\n snapshots?: SnapshotStore\n /** Apply a control document, including its `snapshot`. Default: `controls.apply`. */\n applyControls?(namespace: string, plan: ControlPlan): void\n /** Reset a namespace and forget it. Default: reset. */\n dropNamespace?(namespace: string): Promise<void>\n}\n\nexport type ControlPlane = {\n /** The control-plane response for `request`, or `undefined` for a vendor request. */\n handle(request: Request): Promise<Response | undefined>\n /**\n * Namespace a vendor request targets, from {@link NAMESPACE_HEADER}. Only admin routes\n * also accept `?namespace=`, so a vendor query parameter of that name can never\n * silently reroute a request.\n */\n namespaceOf(request: Request): string\n /** The per-namespace controls behind the routes. */\n readonly controls: NamespaceControls\n readonly snapshots: SnapshotStore\n}\n\nconst json = (status: number, body: unknown): Response =>\n new Response(JSON.stringify(body), {\n status,\n headers: { \"content-type\": \"application/json; charset=utf-8\" },\n })\n\n/** Admin errors use one documented shape, distinct from any vendor's error body. */\nexport const adminError = (status: number, message: string): Response =>\n json(status, { error: { type: \"mockingbird_admin\", message } })\n\n/** Parameters before literals lose, so `/faults/presets` is never read as `/faults/:id`. */\nconst paramCount = (pattern: string): number => (pattern.match(/\\/:/g) ?? []).length\n\nconst matchRoute = (pattern: string, path: string): Record<string, string> | undefined => {\n const want = pattern.split(\"/\").filter(Boolean)\n const have = path.split(\"/\").filter(Boolean)\n if (want.length !== have.length) return undefined\n const params: Record<string, string> = {}\n for (let i = 0; i < want.length; i++) {\n const segment = want[i] as string\n const actual = have[i] as string\n if (segment.startsWith(\":\")) params[segment.slice(1)] = decodeURIComponent(actual)\n else if (segment !== actual) return undefined\n }\n return params\n}\n\nconst readJson = async (request: Request): Promise<unknown> => {\n const text = await request.text()\n if (text.trim() === \"\") return undefined\n return JSON.parse(text) as unknown\n}\n\n/** Snapshots as pinned Timeline checkpoints, for engines whose state is not rows of JSON. */\nconst timelineSnapshots = (timeTravel: ControlContext[\"timeTravel\"]): SnapshotStore => {\n const stored = new Map<string, Map<string, { checkpoint: string; info: SnapshotInfo }>>()\n const counters = new Map<string, number>()\n const of = (namespace: string) => {\n let found = stored.get(namespace)\n if (!found) {\n found = new Map()\n stored.set(namespace, found)\n }\n return found\n }\n const remove = (namespace: string, id: string): boolean => {\n const found = stored.get(namespace)?.get(id)\n if (!found) return false\n stored.get(namespace)?.delete(id)\n timeTravel.release(namespace, found.checkpoint)\n return true\n }\n return {\n create(namespace, given) {\n const point = timeTravel.checkpoint(namespace, \"main\")\n timeTravel.retain(namespace, point.id)\n let id = given\n if (id === undefined) {\n let next = counters.get(namespace) ?? 0\n do id = `snap_${++next}`\n while (of(namespace).has(id))\n counters.set(namespace, next)\n } else remove(namespace, id)\n const info = { id, namespace, records: point.records ?? 0, at: point.at, portable: false }\n of(namespace).set(id, { checkpoint: point.id, info })\n return info\n },\n list: (namespace) => [...(stored.get(namespace)?.values() ?? [])].map((each) => each.info),\n get: (namespace, id) => stored.get(namespace)?.get(id)?.info,\n export: () => undefined,\n import() {\n throw new ControlError(\"this emulator's snapshots cannot be imported or exported\")\n },\n restore(namespace, id) {\n const found = stored.get(namespace)?.get(id)\n if (!found) return false\n timeTravel.checkout(found.checkpoint, { namespace, branch: \"main\" })\n return true\n },\n remove,\n clear(namespace) {\n for (const [name, snapshots] of stored) {\n if (namespace !== undefined && name !== namespace) continue\n for (const id of [...snapshots.keys()]) {\n try {\n remove(name, id)\n } catch {\n // The checkpoint went with the history a reset discarded.\n snapshots.delete(id)\n }\n }\n stored.delete(name)\n counters.delete(name)\n }\n },\n }\n}\n\nexport const createControlPlane = (context: ControlContext): ControlPlane => {\n const adminPrefix = resolveAdminPrefix(context.adminPrefix)\n const controls =\n context.controls ??\n createNamespaceControls({\n seed: 0,\n clock: (namespace) => context.namespaceClock?.(namespace) ?? context.clock,\n })\n const { faults } = controls\n const snapshots = context.snapshots ?? timelineSnapshots(context.timeTravel)\n /** A store the runtime owns is cleared by the runtime's own reset. */\n const forgetSnapshots = (namespace?: string) => {\n if (!context.snapshots) snapshots.clear(namespace)\n }\n const applyControls =\n context.applyControls ??\n ((namespace: string, plan: ControlPlan) => {\n if (plan.snapshot !== undefined)\n throw new ControlError(\"this emulator cannot start from a snapshot document\")\n controls.apply(namespace, plan)\n })\n\n const headerNamespace = (request: Request): string =>\n request.headers.get(NAMESPACE_HEADER) ?? context.defaultNamespace\n const adminNamespace = (request: Request, url: URL): string =>\n url.searchParams.get(\"namespace\") ?? headerNamespace(request)\n /** Whether the caller named a namespace, as opposed to landing on the default one. */\n const explicitNamespace = (request: Request, url: URL): boolean =>\n url.searchParams.has(\"namespace\") || request.headers.has(NAMESPACE_HEADER)\n\n const health = (): Response => {\n return json(200, {\n ...context.describe(),\n status: \"ok\",\n service: context.name,\n uptimeMs: context.wallNow() - context.startedAt,\n clock: context.clock.state(),\n namespaces: context.namespaces().length,\n adminPrefix,\n adminUi: `${adminPrefix}/ui`,\n })\n }\n\n const describe = (namespace: string) => ({\n ...controls.describe(namespace),\n snapshots: snapshots.list(namespace),\n })\n\n /** Run a control change, answering `400` for a {@link ControlError}. */\n const guard = (run: () => Response): Response => {\n try {\n return run()\n } catch (error) {\n if (error instanceof ControlError) return adminError(400, error.message)\n throw error\n }\n }\n\n const presetList = (): FaultPresetList => ({\n presets: Object.entries(controls.presets).map(([name, preset]) => ({ name, ...preset })),\n })\n\n const removeFault = (id: string, namespace: string, everyNamespace: boolean): Response =>\n faults.remove(id, everyNamespace ? undefined : namespace)\n ? json(200, { status: \"ok\" })\n : adminError(404, `no fault ${id}`)\n\n const builtin: AdminRoutes = {\n \"GET /health\": health,\n \"GET /\": ({ namespace }) => {\n const routes = [...Object.keys(builtin), ...Object.keys(context.routes)].sort()\n const reference: Record<string, string> = ADMIN_ROUTE_REFERENCE\n return json(200, {\n service: context.name,\n ...(context.version !== undefined ? { version: context.version } : {}),\n namespace,\n adminPrefix,\n docs: ADMIN_DOCS_URL,\n guide: ADMIN_CONTROL_PAGES.map((each) => ({ title: each.title, docs: pageUrl(each.page) })),\n routes,\n reference: routes.map((route) => {\n const docs = routeDocs(route)\n return {\n route,\n summary: reference[route] ?? `Specific to ${context.name}.`,\n ...(docs !== undefined ? { docs } : {}),\n }\n }),\n headers: CONTROL_HEADER_REFERENCE.map((each) => ({\n ...each,\n docs: headerDocs(each.header) ?? ADMIN_DOCS_URL,\n })),\n })\n },\n\n \"GET /controls\": ({ namespace }) => json(200, describe(namespace)),\n \"PUT /controls\": ({ body, namespace }) =>\n guard(() => {\n applyControls(namespace, normalizeControls(body ?? {}, \"controls\"))\n return json(200, describe(namespace))\n }),\n \"DELETE /controls\": ({ namespace }) => {\n controls.reboot(namespace, \"controls\")\n return json(200, describe(namespace))\n },\n\n \"POST /reset\": async ({ url, namespace }) => {\n const target = url.searchParams.get(\"all\") === \"1\" ? \"*\" : namespace\n await context.reset(target)\n forgetSnapshots(target === \"*\" ? undefined : target)\n return json(200, { status: \"ok\", reset: target === \"*\" ? context.namespaces() : [target] })\n },\n\n \"GET /namespaces\": () =>\n json(200, { default: context.defaultNamespace, namespaces: context.namespaces() }),\n \"DELETE /namespaces/:name\": async ({ params }) => {\n const name = params.name as string\n if (!KEY_PATTERN.test(name)) return adminError(400, \"invalid namespace\")\n if (context.dropNamespace) await context.dropNamespace(name)\n else await context.reset(name)\n forgetSnapshots(name)\n return json(200, { status: \"ok\", namespaces: context.namespaces() })\n },\n\n \"GET /clock\": ({ namespace }) => json(200, controls.clock(namespace)),\n \"POST /clock\": ({ body, namespace }) =>\n guard(() => {\n if (!isRecord(body)) return adminError(400, \"expected a JSON object\")\n const { advance, reset, ...rest } = body\n if (reset !== undefined && typeof reset !== \"boolean\")\n return adminError(400, \"reset: expected a boolean\")\n return json(\n 200,\n controls.changeClock(namespace, {\n ...normalizeClock(rest),\n ...(advance !== undefined ? { advanceMs: durationMs(advance, \"advance\", true) } : {}),\n ...(reset === true ? { reset: true } : {}),\n }),\n )\n }),\n\n \"GET /latency\": ({ namespace }) => {\n controls.ensure(namespace)\n return json(200, controls.latency.get(namespace))\n },\n \"PUT /latency\": ({ body, namespace }) =>\n guard(() => {\n controls.ensure(namespace)\n return json(200, controls.latency.set(namespace, normalizeLatency(body ?? {})))\n }),\n \"DELETE /latency\": ({ namespace }) => {\n controls.ensure(namespace)\n controls.latency.clear(namespace)\n return json(200, controls.latency.get(namespace))\n },\n\n \"GET /faults\": ({ url, namespace }) => {\n controls.ensure(namespace)\n return json(200, {\n faults: faults.list(url.searchParams.get(\"all\") === \"1\" ? undefined : namespace),\n })\n },\n \"POST /faults\": ({ body, namespace }) =>\n guard(() => {\n const preset = isRecord(body) && typeof body.preset === \"string\" ? body.preset : undefined\n if (preset !== undefined && !controls.presets[preset])\n return adminError(\n 404,\n `no fault preset ${JSON.stringify(preset)}; GET ${adminPrefix}/faults/presets`,\n )\n const added = controls.addFault(namespace, body)\n return preset !== undefined ? json(201, { preset, rules: added }) : json(201, added[0])\n }),\n \"PUT /faults\": ({ body, namespace }) =>\n guard(() => {\n const list = isRecord(body) ? body.faults : undefined\n if (!Array.isArray(list)) return adminError(400, 'expected {\"faults\": [...]}')\n controls.apply(namespace, normalizeControls({ faults: list }))\n return json(200, { faults: faults.list(namespace) })\n }),\n \"DELETE /faults\": ({ url, namespace }) => {\n controls.ensure(namespace)\n const everyNamespace = url.searchParams.get(\"all\") === \"1\"\n const id = url.searchParams.get(\"id\")\n if (id !== null) return removeFault(id, namespace, everyNamespace)\n faults.clear(everyNamespace ? undefined : namespace)\n return json(200, { status: \"ok\" })\n },\n \"GET /faults/presets\": () => json(200, presetList()),\n \"POST /faults/presets/:name\": ({ params, body, namespace }) =>\n guard(() => {\n const name = params.name as string\n if (!controls.presets[name])\n return adminError(404, `no fault preset ${name}; GET ${adminPrefix}/faults/presets`)\n return json(201, {\n preset: name,\n rules: controls.addFault(namespace, { ...(isRecord(body) ? body : {}), preset: name }),\n })\n }),\n \"GET /faults/:id\": ({ params, namespace }) => {\n controls.ensure(namespace)\n const found = faults.get(params.id as string, namespace)\n return found ? json(200, found) : adminError(404, `no fault ${params.id}`)\n },\n \"DELETE /faults/:id\": ({ params, url, namespace }) => {\n controls.ensure(namespace)\n return removeFault(params.id as string, namespace, url.searchParams.get(\"all\") === \"1\")\n },\n\n \"GET /snapshots\": ({ namespace }) => json(200, { snapshots: snapshots.list(namespace) }),\n \"POST /snapshots\": ({ body, namespace }) =>\n guard(() => {\n const id = isRecord(body) ? body.name : undefined\n if (id !== undefined && (typeof id !== \"string\" || !KEY_PATTERN.test(id)))\n return adminError(400, `name: must match ${KEY_PATTERN}`)\n return json(201, snapshots.create(namespace, id))\n }),\n \"GET /snapshots/:id\": ({ params, namespace }) => {\n const id = params.id as string\n const info = snapshots.get(namespace, id)\n if (!info) return adminError(404, `no snapshot ${id} in namespace ${namespace}`)\n return json(200, snapshots.export(namespace, id) ?? info)\n },\n \"PUT /snapshots/:id\": ({ params, body, namespace }) =>\n guard(() => {\n const id = params.id as string\n if (!KEY_PATTERN.test(id)) return adminError(400, `id: must match ${KEY_PATTERN}`)\n return json(200, snapshots.import(namespace, id, assertSnapshotDocument(body)))\n }),\n \"POST /snapshots/:id/restore\": ({ params, namespace }) =>\n guard(() => {\n const id = params.id as string\n if (!snapshots.restore(namespace, id))\n return adminError(404, `no snapshot ${id} in namespace ${namespace}`)\n return json(200, { status: \"ok\", id, namespace })\n }),\n \"DELETE /snapshots/:id\": ({ params, namespace }) => {\n const id = params.id as string\n return snapshots.remove(namespace, id)\n ? json(200, { status: \"ok\" })\n : adminError(404, `no snapshot ${id} in namespace ${namespace}`)\n },\n\n \"GET /timeline\": ({ namespace }) => json(200, context.timeTravel.inspect(namespace)),\n \"POST /checkpoints\": ({ body, namespace }) => {\n const branch = isRecord(body) && typeof body.branch === \"string\" ? body.branch : \"main\"\n try {\n return json(201, context.timeTravel.checkpoint(namespace, branch))\n } catch (error) {\n return adminError(409, error instanceof Error ? error.message : String(error))\n }\n },\n \"POST /branches/:name\": ({ params, body, namespace }) => {\n const at = isRecord(body) && typeof body.at === \"string\" ? body.at : undefined\n try {\n return json(\n 201,\n context.timeTravel.branch(params.name as string, {\n namespace,\n ...(at !== undefined ? { at } : {}),\n }),\n )\n } catch (error) {\n return adminError(409, error instanceof Error ? error.message : String(error))\n }\n },\n \"POST /branches/:name/checkout\": ({ params, body, namespace }) => {\n if (!isRecord(body) || typeof body.checkpoint !== \"string\") {\n return adminError(400, 'expected {\"checkpoint\":\"cp_...\"}')\n }\n try {\n context.timeTravel.checkout(body.checkpoint, {\n namespace,\n branch: params.name as string,\n })\n return json(200, { status: \"ok\", branch: params.name, checkpoint: body.checkpoint })\n } catch (error) {\n return adminError(409, error instanceof Error ? error.message : String(error))\n }\n },\n\n \"GET /requests\": ({ url, namespace }) => {\n const status = url.searchParams.get(\"status\")\n const since = url.searchParams.get(\"since\")\n const limit = url.searchParams.get(\"limit\")\n const sinceMs = since === null ? undefined : parseInstant(since)\n if (since !== null && sinceMs === undefined) {\n return adminError(400, \"since: expected epoch ms or ISO-8601\")\n }\n // `0` is a status here: it is how the journal records a dropped connection.\n if (status !== null && !/^(0|\\d{3})$/.test(status))\n return adminError(400, \"status: expected an HTTP status, or 0 for a dropped connection\")\n if (limit !== null && !/^\\d+$/.test(limit)) return adminError(400, \"limit: expected a count\")\n const operationId = url.searchParams.get(\"operationId\")\n const method = url.searchParams.get(\"method\")\n const path = url.searchParams.get(\"path\")\n const faultId = url.searchParams.get(\"faultId\")\n const everyNamespace = url.searchParams.get(\"all\") === \"1\"\n return json(200, {\n size: context.journal.size,\n requests: context.journal.list({\n ...(everyNamespace ? {} : { namespace }),\n ...(operationId !== null ? { operationId } : {}),\n ...(method !== null ? { method } : {}),\n ...(path !== null ? { path } : {}),\n ...(faultId !== null ? { faultId } : {}),\n ...(status !== null ? { status: Number(status) } : {}),\n ...(sinceMs !== undefined ? { since: sinceMs } : {}),\n ...(limit !== null ? { limit: Number(limit) } : {}),\n }),\n })\n },\n \"DELETE /requests\": ({ url, namespace }) => {\n context.journal.clear(url.searchParams.get(\"all\") === \"1\" ? undefined : namespace)\n return json(200, { status: \"ok\" })\n },\n\n // Totals across every namespace, unless the caller names one.\n \"GET /metrics\": ({ request, url, namespace }) =>\n json(200, context.metrics.report(explicitNamespace(request, url) ? namespace : undefined)),\n \"DELETE /metrics\": ({ request, url, namespace }) => {\n context.metrics.reset(explicitNamespace(request, url) ? namespace : undefined)\n return json(200, { status: \"ok\" })\n },\n }\n\n for (const key of Object.keys(context.routes)) {\n if (Object.hasOwn(builtin, key)) throw new Error(`admin route ${key} overrides a shared route`)\n const path = key.slice(key.indexOf(\" \") + 1)\n if (isAdminPath(path, \"/ns\") || isAdminPath(path, \"/blobs\"))\n throw new Error(`admin route ${key} overlaps an internal transport`)\n }\n const routes = [...Object.entries(builtin), ...Object.entries(context.routes)]\n .map(([key, handler]) => {\n const space = key.indexOf(\" \")\n return { method: key.slice(0, space), pattern: key.slice(space + 1), handler }\n })\n // Stable: among equally specific routes the shared ones still come first.\n .sort((a, b) => paramCount(a.pattern) - paramCount(b.pattern))\n\n return {\n namespaceOf: headerNamespace,\n controls,\n snapshots,\n async handle(request) {\n const url = new URL(request.url)\n if (url.pathname === `${adminPrefix}/health` && request.method === \"GET\") {\n return health()\n }\n if (!isAdminPath(url.pathname, adminPrefix)) {\n return undefined\n }\n const path = url.pathname.slice(adminPrefix.length) || \"/\"\n // The shell and its vendor chip have no data. Panel markup stays on GET /ui/manifest,\n // which is locked.\n const shell =\n request.method === \"GET\" &&\n (path === \"/ui\" || path === \"/ui/\" || path === ADMIN_BRANDS_PATH)\n if (\n !shell &&\n context.adminKey !== undefined &&\n !hasAdminKey(request.headers, context.adminKey)\n ) {\n return adminError(401, `missing or wrong ${ADMIN_KEY_HEADER}`)\n }\n for (const route of routes) {\n if (route.method !== request.method) continue\n let params: Record<string, string> | undefined\n try {\n params = matchRoute(route.pattern, path)\n } catch {\n return adminError(400, \"invalid path encoding\")\n }\n if (!params) continue\n let body: unknown\n try {\n body = await readJson(request)\n } catch {\n return adminError(400, \"request body is not valid JSON\")\n }\n const namespace = adminNamespace(request, url)\n if (!KEY_PATTERN.test(namespace)) return adminError(400, \"invalid namespace\")\n return route.handler({\n request,\n url,\n params,\n namespace,\n body,\n })\n }\n return adminError(\n 404,\n `no admin route ${request.method} ${path}; GET ${adminPrefix} lists them`,\n )\n },\n }\n}\n", "/**\n * Reading the vendor credential a request carries.\n *\n * Several vendor SDKs (Stripe, AWS, PostHog, Twilio) cannot add a namespace header, so a\n * runtime can also pick a request's namespace from its credential: a suite maps each\n * worker's API key, token or account SID to a namespace through `PUT /__admin/credentials`.\n * These helpers pull the credential out of the usual carriers.\n */\n\n/** The token after `Bearer `, or `undefined`. */\nexport const bearerToken = (request: Request): string | undefined => {\n const header = request.headers.get(\"authorization\")\n if (!header) return undefined\n const match = /^Bearer\\s+(.+)$/i.exec(header.trim())\n return match?.[1]?.trim() || undefined\n}\n\nexport type BasicCredentials = { username: string; password: string }\n\n/** `{ username, password }` from `Authorization: Basic \u2026`, or `undefined`. */\nexport const basicAuth = (request: Request): BasicCredentials | undefined => {\n const header = request.headers.get(\"authorization\")\n if (!header) return undefined\n const match = /^Basic\\s+(.+)$/i.exec(header.trim())\n if (!match?.[1]) return undefined\n let decoded: string\n try {\n decoded = atob(match[1].trim())\n } catch {\n return undefined\n }\n const colon = decoded.indexOf(\":\")\n if (colon < 0) return { username: decoded, password: \"\" }\n return { username: decoded.slice(0, colon), password: decoded.slice(colon + 1) }\n}\n\n/**\n * The access key id of an AWS SigV4-signed request (`Credential=AKID/date/region/service/\u2026`),\n * from the `Authorization` header or a presigned `X-Amz-Credential` query parameter.\n */\nexport const sigV4AccessKeyId = (request: Request): string | undefined => {\n const header = request.headers.get(\"authorization\")\n const fromHeader = header ? /Credential=([^/,\\s]+)\\//.exec(header)?.[1] : undefined\n if (fromHeader) return fromHeader\n const query = new URL(request.url).searchParams.get(\"X-Amz-Credential\")\n return query ? (query.split(\"/\")[0] ?? undefined) : undefined\n}\n\n/** The credential in any of the common carriers: Bearer, Basic username, SigV4, or `x-api-key`. */\nexport const anyCredential = (request: Request): string | undefined =>\n bearerToken(request) ??\n basicAuth(request)?.username ??\n sigV4AccessKeyId(request) ??\n request.headers.get(\"x-api-key\") ??\n undefined\n\n/** Credential \u2192 namespace mapping behind `PUT /__admin/credentials`. */\nexport type CredentialRegistry = {\n set(credential: string, namespace: string): void\n get(credential: string): string | undefined\n remove(credential: string): boolean\n clear(): void\n entries(): { credential: string; namespace: string }[]\n}\n\nexport const createCredentialRegistry = (): CredentialRegistry => {\n const map = new Map<string, string>()\n return {\n set: (credential, namespace) => {\n map.set(credential, namespace)\n },\n get: (credential) => map.get(credential),\n remove: (credential) => map.delete(credential),\n clear: () => map.clear(),\n entries: () =>\n [...map]\n .map(([credential, namespace]) => ({ credential, namespace }))\n .sort((a, b) => a.credential.localeCompare(b.credential)),\n }\n}\n\n/** A credential shown in admin output: enough to recognise it, never the whole secret. */\nexport const maskCredential = (credential: string): string =>\n credential.length <= 8\n ? `${credential.slice(0, 2)}\u2026`\n : `${credential.slice(0, 6)}\u2026${credential.slice(-2)}`\n", "import type { BodyIssue } from \"./validation.js\"\n\n/**\n * What the mock received from a request it rejected, so a 4xx can be attributed after the\n * fact (an empty body, a missing `content-type`, a schema violation) without logging the body.\n */\nexport type RejectedRequest = {\n /** The raw `content-type` header, or `null` when the request sent none. */\n contentType: string | null\n /** Bytes of body received from `content-length` (`0` for none), or `null` when the client sent no length (a streamed / chunked body). */\n bodyBytes: number | null\n /** The raw `transfer-encoding` header (`chunked`), or `null`. */\n transferEncoding: string | null\n}\n\n/** One handled request, as the structured log sees it. */\nexport type RequestLog = {\n service: string\n namespace: string\n operationId: string | undefined\n method: string\n path: string\n status: number\n durationMs: number\n /** True when the path matched no operation in the contract. */\n unmatched: boolean\n /** Set when a fault rule produced the response. */\n faultId?: string\n /** Milliseconds of injected wait: latency, fault delays and timeouts. Absent when none. */\n delayMs?: number\n /** Resource ids the handler touched (`userId`, `orderId`, \u2026), when the service reports them. */\n ids?: Record<string, string>\n /** Set when the service created a resource the request referred to but that did not exist. */\n adopted?: boolean\n /** Explicit durable acceptance, independent of response delivery. */\n accepted?: boolean\n /** Checkpoint captured at explicit acceptance. */\n checkpoint?: string\n /** Set on a rejection (status \u2265 400) the mock produced itself, never on a scripted fault. */\n request?: RejectedRequest\n /** The validation issues behind a rejection, when the service found any. */\n issues?: BodyIssue[]\n}\n\nexport type MetricsReport = {\n requests: number\n /** Counts keyed `<operationId> <status>`. */\n byOperation: Record<string, number>\n /**\n * Paths that matched no operation, most frequent first.\n *\n * This is the early-warning signal: a consumer calling something the mock does\n * not implement shows up here as a count, before it fails a suite as a 404.\n */\n unmatched: { method: string; path: string; count: number }[]\n faults: number\n totalDurationMs: number\n}\n\nexport type Metrics = {\n record(entry: RequestLog): void\n report(namespace?: string): MetricsReport\n reset(namespace?: string): void\n}\n\nexport const createMetrics = (partition = true): Metrics => {\n const namespaces = new Map<string, Metrics>()\n let requests = 0\n let faults = 0\n let totalDurationMs = 0\n const byOperation = new Map<string, number>()\n const unmatched = new Map<string, number>()\n return {\n record(entry) {\n if (partition) {\n let scoped = namespaces.get(entry.namespace)\n if (!scoped) {\n scoped = createMetrics(false)\n namespaces.set(entry.namespace, scoped)\n }\n scoped.record(entry)\n }\n requests++\n totalDurationMs += entry.durationMs\n if (entry.faultId !== undefined) faults++\n const key = `${entry.operationId ?? \"(unmatched)\"} ${entry.status}`\n byOperation.set(key, (byOperation.get(key) ?? 0) + 1)\n if (entry.unmatched) {\n const route = `${entry.method} ${entry.path}`\n unmatched.set(route, (unmatched.get(route) ?? 0) + 1)\n }\n },\n report: (namespace) =>\n namespace !== undefined\n ? (namespaces.get(namespace) ?? createMetrics(false)).report()\n : {\n requests,\n byOperation: Object.fromEntries(\n [...byOperation].sort(([a], [b]) => a.localeCompare(b)),\n ),\n unmatched: [...unmatched]\n .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))\n .map(([route, count]) => {\n const space = route.indexOf(\" \")\n return { method: route.slice(0, space), path: route.slice(space + 1), count }\n }),\n faults,\n totalDurationMs,\n },\n reset(namespace) {\n if (namespace !== undefined) {\n namespaces.delete(namespace)\n return\n }\n namespaces.clear()\n requests = 0\n faults = 0\n totalDurationMs = 0\n byOperation.clear()\n unmatched.clear()\n },\n }\n}\n", "/** Policy only for runtime-owned HTTP sends; it does not sandbox DNS or arbitrary sockets. */\nexport type OutboundPolicy = {\n mode: \"offline\" | \"allowlist\"\n origins?: string[]\n maxRedirects?: number\n maxBodyBytes?: number\n onReject?(event: { namespace: string; policy: string; reason: string }): void\n}\nexport type OwnedTransport = (\n request: Request,\n namespace: string,\n send: typeof fetch,\n) => Promise<Response>\nexport function ownedTransport(policy: OutboundPolicy): OwnedTransport {\n if (\n ![\"offline\", \"allowlist\"].includes(policy.mode) ||\n policy.origins?.some((origin) => {\n try {\n return new URL(origin).origin !== origin\n } catch {\n return true\n }\n })\n )\n throw new Error(\"invalid outbound transport policy\")\n const reject = (namespace: string, reason: string): never => {\n try {\n policy.onReject?.({ namespace, policy: policy.mode, reason })\n } catch {}\n throw new Error(`outbound policy ${policy.mode}: ${reason}`)\n }\n return async (request, namespace, send) => {\n if (policy.mode === \"offline\") return reject(namespace, \"delivery disabled\")\n const allowed = (url: URL) =>\n [\"http:\", \"https:\"].includes(url.protocol) &&\n !url.username &&\n !url.password &&\n (policy.origins ?? []).includes(url.origin)\n let url = new URL(request.url)\n if (!allowed(url)) return reject(namespace, \"destination not allowed\")\n const max = policy.maxBodyBytes ?? 1024 * 1024\n const chunks: Uint8Array[] = []\n let size = 0\n const reader = request.body?.getReader()\n if (reader)\n try {\n for (;;) {\n const item = await reader.read()\n if (item.done) break\n size += item.value.length\n if (size > max) return reject(namespace, \"body limit exceeded\")\n chunks.push(item.value)\n }\n } finally {\n void reader.cancel().catch(() => {})\n reader.releaseLock()\n }\n const body = new Uint8Array(size)\n let offset = 0\n for (const chunk of chunks) {\n body.set(chunk, offset)\n offset += chunk.length\n }\n let method = request.method,\n headers = new Headers(request.headers)\n for (let redirects = 0; ; redirects++) {\n if (!allowed(url)) return reject(namespace, \"redirect destination not allowed\")\n const response = await send(\n new Request(url, {\n method,\n headers,\n ...(method !== \"GET\" && method !== \"HEAD\" ? { body } : {}),\n redirect: \"manual\",\n signal: request.signal,\n }),\n )\n if (![301, 302, 303, 307, 308].includes(response.status)) return response\n const location = response.headers.get(\"location\")\n if (!location) return response\n await response.body?.cancel()\n if (redirects >= (policy.maxRedirects ?? 5))\n return reject(namespace, \"redirect limit exceeded\")\n const next = new URL(location, url)\n if (next.origin !== url.origin) {\n headers = new Headers(headers)\n for (const key of [\"authorization\", \"cookie\", \"proxy-authorization\"]) headers.delete(key)\n }\n if (\n response.status === 303 ||\n ((response.status === 301 || response.status === 302) && method === \"POST\")\n ) {\n method = \"GET\"\n headers.delete(\"content-length\")\n headers.delete(\"content-type\")\n }\n url = next\n }\n }\n}\n", "/**\n * The shared admin is a prebuilt React + Ant Design bundle (about 1.3 MB as a string). The\n * runtime loads it lazily, on the first request for an admin page, through a dynamic `import()`\n * with a literal specifier: Node, Bun and every bundler resolve it, a bundler that splits code\n * keeps it in a chunk of its own, and an app that never serves `/__admin/ui` never parses it.\n * `scripts/bundle-service.ts` emits it as `dist/admin-ui.js` beside each service's entries.\n * Service imports stay DOM-free and nothing here imports the bundle statically.\n */\nexport type { AdminConfig as AdminBootConfig } from \"@crvouga/mockingbird-admin-ui\"\n\nexport type AdminClient = typeof import(\"@crvouga/mockingbird-admin-ui/document\")\n\nlet loading: Promise<AdminClient> | undefined\n\n/** The browser client, imported once per process on first use. A failed import is retried. */\nexport const loadAdminClient = (): Promise<AdminClient> => {\n loading ??= import(\"@crvouga/mockingbird-admin-ui/document\").catch((error: unknown) => {\n loading = undefined\n throw error\n })\n return loading\n}\n", "import { requestBaseUrl } from \"@crvouga/mockingbird-core\"\nimport { type AdminClient, loadAdminClient } from \"./admin-client.js\"\nimport type { AdminRoutes } from \"./control.js\"\nimport { ADMIN_BRANDS_PATH, ADMIN_KEY_HEADER, ADMIN_PREFIX } from \"./control.js\"\nimport type { AdminExtension, AdminUi } from \"./surface.js\"\nimport { STANDARD_ADMIN_ROUTES } from \"./surface.js\"\n\nconst escapeHtml = (value: string): string =>\n value.replace(/[&<>\"']/g, (char) => {\n switch (char) {\n case \"&\":\n return \"&amp;\"\n case \"<\":\n return \"&lt;\"\n case \">\":\n return \"&gt;\"\n case '\"':\n return \"&quot;\"\n default:\n return \"&#39;\"\n }\n })\n\n/** One service's vendor chip: what `GET <adminPrefix>/ui/brands.json` returns under its name. */\nexport type AdminBrand = {\n vendor: string\n website: string\n /** Vendor API reference, when there is one. */\n docs: string | null\n /** The service's page on the docs site. A link only; the admin never fetches it. */\n guide: string\n /** A `data:image/\u2026;base64,` URI, so the chip loads nothing from the network; \"\" for none. */\n logo: string\n color: string | null\n description: string | null\n}\n\n/**\n * The brand record of the package this runtime was bundled into. `scripts/bundle-service.ts`\n * defines it from `sites/docs/src/data/brands.json` and the logo file; unbundled (tests,\n * source checkouts) it is absent and the admin shows no chip.\n */\ndeclare const __MOCKINGBIRD_ADMIN_BRAND__: AdminBrand | undefined\nconst EMBEDDED_BRAND: AdminBrand | undefined =\n typeof __MOCKINGBIRD_ADMIN_BRAND__ === \"object\" ? __MOCKINGBIRD_ADMIN_BRAND__ : undefined\n\n/**\n * The catalog the shared client reads: `{ [service]: brand }`, or `{}` without one. It ships\n * inside the package and is served by the emulator, so opening the admin makes no request to\n * any other host (no CORS failure, works offline).\n */\nexport const adminBrandCatalog = (\n service: string,\n brand: AdminBrand | undefined = EMBEDDED_BRAND,\n): Record<string, AdminBrand> => (brand ? { [service]: brand } : {})\n\n/**\n * The default admin document. It talks only to `/__admin/*`, so every mock can serve it.\n * Bespoke panels arrive later from `GET /ui/manifest`, which stays behind the admin key.\n * The header chip is filled from `GET <adminPrefix>/ui/brands.json` on the same emulator.\n */\nexport const renderAdminDocument = async (\n service: string,\n adminPrefix = ADMIN_PREFIX,\n): Promise<string> => adminDocument(await loadAdminClient(), service, adminPrefix)\n\nconst adminDocument = (client: AdminClient, service: string, adminPrefix: string): string => {\n const name = escapeHtml(service)\n const script = client.adminClientSource({\n standardRoutes: STANDARD_ADMIN_ROUTES,\n adminPrefix,\n adminKeyHeader: ADMIN_KEY_HEADER,\n brandsUrl: `${adminPrefix}${ADMIN_BRANDS_PATH}`,\n service,\n })\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<meta name=\"color-scheme\" content=\"light dark\">\n<title>${name} admin</title>\n<style>html,body{margin:0;min-height:100%}#admin-root{min-height:100%}</style>\n</head>\n<body>\n<main id=\"admin-root\" data-mockingbird-admin data-admin-ui-library=\"antd\" data-service=\"${name}\">\n<noscript>Enable JavaScript to use administration.</noscript>\n</main>\n${script}\n</body>\n</html>`\n}\n\nconst htmlResponse = (body: string): Response =>\n new Response(body, {\n status: 200,\n headers: {\n \"content-type\": \"text/html; charset=utf-8\",\n \"cache-control\": \"no-store\",\n },\n })\n\nconst json = (body: unknown): Response =>\n new Response(JSON.stringify(body), {\n status: 200,\n headers: { \"content-type\": \"application/json; charset=utf-8\" },\n })\n\nconst describeExtension = (extension: AdminExtension): Record<string, unknown> => {\n if (extension.kind === \"route\") return { ...extension }\n if (extension.kind === \"sql\") {\n return {\n kind: \"sql\",\n id: extension.id ?? \"sql\",\n title: extension.title ?? \"SQL\",\n ...(extension.description !== undefined ? { description: extension.description } : {}),\n }\n }\n return {\n kind: \"panel\",\n id: extension.id,\n title: extension.title,\n ...(extension.description !== undefined ? { description: extension.description } : {}),\n html: extension.html,\n ...(extension.script !== undefined ? { script: extension.script } : {}),\n }\n}\n\n/** `GET /__admin/ui` plus the manifest a bespoke panel list is read from. */\nexport const adminUiRoutes = (\n service: string,\n ui: AdminUi | undefined,\n adminPrefix = ADMIN_PREFIX,\n): AdminRoutes => {\n // The client bundle is loaded here, on the first page request, not when the runtime is built;\n // `render` and `defaultHtml()` stay synchronous for bespoke documents.\n const page = async ({ request }: { request: Request }): Promise<Response> => {\n let client: AdminClient\n try {\n client = await loadAdminClient()\n } catch (error) {\n // An app bundle may leave the client out (`--external:./admin-ui.js`) and never serve it.\n return new Response(\n `The admin page is not available: its browser client (admin-ui.js) could not be loaded. ${error instanceof Error ? error.message : String(error)}`,\n { status: 503, headers: { \"content-type\": \"text/plain; charset=utf-8\" } },\n )\n }\n const mountPrefix = new URL(requestBaseUrl(request)).pathname.replace(/\\/$/, \"\")\n const shell = () => adminDocument(client, service, `${mountPrefix}${adminPrefix}`)\n return htmlResponse(ui?.render ? ui.render({ service, defaultHtml: shell }) : shell())\n }\n return {\n \"GET /ui\": page,\n \"GET /ui/\": page,\n [`GET ${ADMIN_BRANDS_PATH}`]: () => json(adminBrandCatalog(service)),\n \"GET /ui/manifest\": () =>\n json({\n service,\n standardRoutes: STANDARD_ADMIN_ROUTES,\n panels: (ui?.panels ?? []).map((panel) => ({\n id: panel.id,\n title: panel.title,\n ...(panel.description !== undefined ? { description: panel.description } : {}),\n html: panel.html,\n ...(panel.script !== undefined ? { script: panel.script } : {}),\n })),\n extensions: (ui?.extensions ?? []).map(describeExtension),\n }),\n }\n}\n", "import { Timeline } from \"@crvouga/mockingbird-core\"\nimport type { SqliteClient } from \"@crvouga/mockingbird-sqlite\"\n\n/**\n * A point-in-time copy of everything a service namespace holds.\n *\n * All service state lives in the two core tables keyed by namespace, so a snapshot\n * is generic: any service gets per-test rollback without knowing its own schema.\n * Restoring is much cheaper than rebuilding a namespace from a corpus.\n */\nexport type NamespaceSnapshot = {\n namespace: string\n records: { collection: string; id: string; seq: number; value: string }[]\n sequences: { name: string; kind: string; value: number }[]\n}\n\n/**\n * @deprecated Low-level Timeline payload capture retained for API compatibility. Provider code\n * must use the runtime Timeline or `withNamespaceRollback`.\n */\nexport const snapshotNamespace = (sqlite: SqliteClient, namespace: string): NamespaceSnapshot => ({\n namespace,\n records: sqlite\n .prepare(\n \"SELECT collection, id, seq, value FROM mockingbird_records WHERE namespace = ? ORDER BY collection, seq\",\n )\n .all<{ collection: string; id: string; seq: number; value: string }>(namespace),\n sequences: sqlite\n .prepare(\n \"SELECT name, kind, value FROM mockingbird_sequences WHERE namespace = ? ORDER BY name, kind\",\n )\n .all<{ name: string; kind: string; value: number }>(namespace),\n})\n\n/**\n * Replace a namespace's contents with `snapshot`. The namespace is emptied first,\n * so restoring is an assignment, not a merge \u2014 records created since the snapshot\n * are gone afterwards.\n *\n * @deprecated Low-level Timeline payload restore retained for API compatibility. Provider code\n * must use the runtime Timeline or `withNamespaceRollback`.\n */\nexport const restoreNamespace = (\n sqlite: SqliteClient,\n namespace: string,\n snapshot: NamespaceSnapshot,\n): void => {\n sqlite.transaction(() => {\n sqlite.prepare(\"DELETE FROM mockingbird_records WHERE namespace = ?\").run(namespace)\n sqlite.prepare(\"DELETE FROM mockingbird_sequences WHERE namespace = ?\").run(namespace)\n const record = sqlite.prepare(\n \"INSERT INTO mockingbird_records (namespace, collection, id, seq, value) VALUES (?, ?, ?, ?, ?)\",\n )\n for (const row of snapshot.records) {\n record.run(namespace, row.collection, row.id, row.seq, row.value)\n }\n const sequence = sqlite.prepare(\n \"INSERT INTO mockingbird_sequences (namespace, name, kind, value) VALUES (?, ?, ?, ?)\",\n )\n for (const row of snapshot.sequences) {\n sequence.run(namespace, row.name, row.kind, row.value)\n }\n })\n}\n\n/**\n * Execute asynchronous service work atomically using the canonical Timeline rollback primitive.\n * This is the prescribed escape hatch when the SQLite adapter cannot hold a transaction across\n * `await`; service code should not coordinate raw namespace snapshots itself.\n */\nexport const withNamespaceRollback = async <T>(\n sqlite: SqliteClient,\n namespace: string,\n run: () => Promise<T>,\n): Promise<T> => {\n const rollback = new Timeline<NamespaceSnapshot>({ maxCheckpoints: 1 })\n const before = rollback.commit(snapshotNamespace(sqlite, namespace))\n try {\n return await run()\n } catch (error) {\n restoreNamespace(sqlite, namespace, before.value)\n throw error\n }\n}\n", "import type { SqliteClient } from \"@crvouga/mockingbird-sqlite\"\nimport { Collection } from \"./collection.js\"\nimport type { AdminRoutes } from \"./control.js\"\n\nexport const STATE_FIELD_KINDS = [\n \"string\",\n \"number\",\n \"boolean\",\n \"null\",\n \"object\",\n \"array\",\n \"unknown\",\n] as const\n\nexport type StateFieldKind = (typeof STATE_FIELD_KINDS)[number]\n\n/** JSON-safe annotations a bespoke admin UI may read. The default UI shows them as text. */\nexport type StateMeta = Readonly<Record<string, string | number | boolean | null>>\n\nexport type StateField = {\n name: string\n kind: StateFieldKind\n optional: boolean\n description?: string\n /** One level of nested object fields. */\n fields?: StateField[]\n meta?: StateMeta\n}\n\n/**\n * What a service knows about a collection before any row exists.\n * Stored rows still appear, including fields this declaration does not mention.\n */\nexport type StateDeclaration = {\n name: string\n label?: string\n description?: string\n fields?: readonly StateField[]\n meta?: StateMeta\n}\n\nexport type StateCollectionView = {\n name: string\n label: string\n description?: string\n count: number\n /** `mixed` when a declaration and stored rows both contribute fields. */\n source: \"declared\" | \"inferred\" | \"mixed\"\n fields: StateField[]\n meta?: StateMeta\n}\n\n/** The shape of one namespace, for an admin UI that has never seen the service before. */\nexport type StateView = {\n namespace: string\n storageNamespace: string\n collections: StateCollectionView[]\n}\n\nexport type StateRecord = {\n id: string\n seq: number\n value: unknown\n}\n\nexport type StatePage = {\n collection: string\n count: number\n records: StateRecord[]\n next: number | null\n}\n\nexport type StateFailure = { ok: false; status: number; message: string }\nexport type StateResult<T> = { ok: true; value: T } | StateFailure\n\nconst COLLECTION_NAME = /^[A-Za-z0-9_.@:-]{1,200}$/\nconst RECORD_ID = /^[^\\s/]{1,256}$/\nconst SAMPLE = 25\nconst WALK_LIMIT = 10_000\nconst SKIP_CTORS = new Set([\"Hono\", \"HonoRequest\", \"Router\"])\n\nconst fail = (status: number, message: string): StateFailure => ({ ok: false, status, message })\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n\nconst kindOf = (value: unknown): StateFieldKind => {\n if (value === null) return \"null\"\n if (Array.isArray(value)) return \"array\"\n switch (typeof value) {\n case \"string\":\n return \"string\"\n case \"number\":\n return Number.isFinite(value) ? \"number\" : \"unknown\"\n case \"boolean\":\n return \"boolean\"\n case \"object\":\n return \"object\"\n default:\n return \"unknown\"\n }\n}\n\nconst humanize = (name: string): string => {\n const words = name.replace(/[@:_-]+/g, \" \").trim()\n if (words === \"\") return name\n return words.charAt(0).toUpperCase() + words.slice(1)\n}\n\n/** Drop values that cannot ride in a JSON admin response. */\nexport const jsonValue = (value: unknown): StateResult<unknown> => {\n if (value === undefined) return fail(400, \"value is required\")\n try {\n return { ok: true, value: JSON.parse(JSON.stringify(value)) as unknown }\n } catch {\n return fail(400, \"value must be JSON\")\n }\n}\n\nconst ctorName = (value: object): string => {\n const ctor = (value as { constructor?: { name?: string } }).constructor\n return typeof ctor?.name === \"string\" ? ctor.name : \"\"\n}\n\nconst isSqlite = (value: object): boolean =>\n \"prepare\" in value &&\n typeof (value as { prepare?: unknown }).prepare === \"function\" &&\n \"transaction\" in value\n\n/** Every Collection hanging off `root`, including ones stored in maps. */\nexport const discoverCollections = (root: unknown): Collection<unknown>[] => {\n const found: Collection<unknown>[] = []\n const seen = new Set<object>()\n const visit = (value: unknown, depth: number): void => {\n if (found.length + seen.size > WALK_LIMIT) return\n if (value === null || typeof value !== \"object\") return\n if (seen.has(value)) return\n seen.add(value)\n if (value instanceof Collection) {\n found.push(value as Collection<unknown>)\n return\n }\n if (value instanceof Map) {\n for (const child of value.values()) visit(child, depth + 1)\n return\n }\n if (value instanceof Set) {\n for (const child of value.values()) visit(child, depth + 1)\n return\n }\n if (depth > 6 || isSqlite(value) || SKIP_CTORS.has(ctorName(value))) return\n if (Array.isArray(value)) {\n const cap = Math.min(value.length, 32)\n for (let i = 0; i < cap; i++) visit(value[i], depth + 1)\n return\n }\n let children: unknown[]\n try {\n children = Object.values(value)\n } catch {\n return\n }\n for (const child of children) visit(child, depth + 1)\n }\n visit(root, 0)\n return found\n}\n\nconst storedNames = (sqlite: SqliteClient, namespace: string): string[] => {\n const records = sqlite\n .prepare(\"SELECT DISTINCT collection AS name FROM mockingbird_records WHERE namespace = ?\")\n .all<{ name: string }>(namespace)\n const sequences = sqlite\n .prepare(\n \"SELECT DISTINCT name FROM mockingbird_sequences WHERE namespace = ? AND kind = 'collection'\",\n )\n .all<{ name: string }>(namespace)\n return [...records, ...sequences].map((row) => row.name)\n}\n\ntype FieldAccum = {\n name: string\n kinds: Set<StateFieldKind>\n present: number\n nested: Map<string, FieldAccum>\n}\n\nconst blankAccum = (name: string): FieldAccum => ({\n name,\n kinds: new Set(),\n present: 0,\n nested: new Map(),\n})\n\nconst absorb = (accum: FieldAccum, value: unknown): void => {\n const kind = kindOf(value)\n accum.kinds.add(kind)\n accum.present++\n if (!isRecord(value)) return\n for (const [key, child] of Object.entries(value)) {\n const nested = accum.nested.get(key) ?? blankAccum(key)\n absorb(nested, child)\n accum.nested.set(key, nested)\n }\n}\n\nconst finishField = (accum: FieldAccum, samples: number): StateField => {\n const kinds = [...accum.kinds]\n const kind = kinds.length === 1 ? (kinds[0] as StateFieldKind) : \"unknown\"\n const field: StateField = {\n name: accum.name,\n kind,\n optional: accum.present < samples || kinds.includes(\"null\"),\n }\n if (accum.nested.size > 0) {\n field.fields = [...accum.nested.values()]\n .sort((a, b) => a.name.localeCompare(b.name))\n .map((child) => finishField(child, accum.present))\n }\n return field\n}\n\nconst inferFields = (records: StateRecord[]): StateField[] => {\n if (records.length === 0) return []\n const sample = records.slice(0, SAMPLE)\n const objects = sample.filter((record) => isRecord(record.value))\n if (objects.length === 0) {\n const kinds = new Set(sample.map((record) => kindOf(record.value)))\n const list = [...kinds]\n return [\n {\n name: \"(value)\",\n kind: list.length === 1 ? (list[0] as StateFieldKind) : \"unknown\",\n optional: false,\n },\n ]\n }\n const root = new Map<string, FieldAccum>()\n for (const record of objects) {\n for (const [key, value] of Object.entries(record.value as Record<string, unknown>)) {\n const accum = root.get(key) ?? blankAccum(key)\n absorb(accum, value)\n root.set(key, accum)\n }\n }\n return [...root.values()]\n .sort((a, b) => a.name.localeCompare(b.name))\n .map((accum) => finishField(accum, objects.length))\n}\n\nconst mergeFields = (\n declared: readonly StateField[] | undefined,\n inferred: StateField[],\n): StateField[] => {\n const byName = new Map<string, StateField>()\n for (const field of inferred) byName.set(field.name, field)\n const ordered: StateField[] = []\n const seen = new Set<string>()\n for (const field of declared ?? []) {\n const found = byName.get(field.name)\n seen.add(field.name)\n if (!found) {\n ordered.push({ ...field, optional: field.optional })\n continue\n }\n ordered.push({\n ...found,\n kind: field.kind === \"unknown\" ? found.kind : field.kind,\n optional: field.optional || found.optional,\n ...(field.description !== undefined ? { description: field.description } : {}),\n ...(field.meta !== undefined ? { meta: field.meta } : {}),\n ...(field.fields !== undefined\n ? { fields: mergeFields(field.fields, found.fields ?? []) }\n : {}),\n })\n }\n for (const field of inferred) {\n if (!seen.has(field.name)) ordered.push(field)\n }\n return ordered\n}\n\nconst collectionOf = (sqlite: SqliteClient, namespace: string, name: string) =>\n new Collection<unknown>(sqlite, namespace, name)\n\nconst readRecord = (collection: Collection<unknown>, id: string): StateRecord | undefined => {\n const rows = collection.list({ where: (_value, _seq) => true, order: \"oldest\" })\n const row = rows.find((entry) => entry.id === id)\n return row ? { id: row.id, seq: row.seq, value: row.value } : undefined\n}\n\nexport type StateScope = {\n sqlite: SqliteClient\n /** Public namespace name a request selects. */\n namespace: string\n /** Namespace key used in `mockingbird_records`. */\n storageNamespace: string\n /** Service instance, walked for Collection fields. */\n root: unknown\n declarations?: readonly StateDeclaration[]\n}\n\n/** Describe every collection in a namespace. Empty declared collections are included. */\nexport const inspectState = (scope: StateScope): StateView => {\n const declared = new Map<string, StateDeclaration>()\n for (const declaration of scope.declarations ?? []) {\n if (COLLECTION_NAME.test(declaration.name)) declared.set(declaration.name, declaration)\n }\n const names = new Set<string>(declared.keys())\n for (const name of storedNames(scope.sqlite, scope.storageNamespace)) names.add(name)\n for (const collection of discoverCollections(scope.root)) {\n if (collection.namespace === scope.storageNamespace) names.add(collection.collectionName)\n }\n const collections: StateCollectionView[] = []\n for (const name of names) {\n if (!COLLECTION_NAME.test(name)) continue\n const declaration = declared.get(name)\n const collection = collectionOf(scope.sqlite, scope.storageNamespace, name)\n const records = collection\n .list({ order: \"newest\" })\n .slice(0, SAMPLE)\n .map((row) => ({ id: row.id, seq: row.seq, value: row.value }))\n const inferred = inferFields(records)\n const fields = mergeFields(declaration?.fields, inferred)\n const source =\n declaration && records.length > 0 ? \"mixed\" : declaration ? \"declared\" : \"inferred\"\n collections.push({\n name,\n label: declaration?.label ?? humanize(name),\n ...(declaration?.description !== undefined ? { description: declaration.description } : {}),\n count: collection.count(),\n source,\n fields,\n ...(declaration?.meta !== undefined ? { meta: declaration.meta } : {}),\n })\n }\n const order = new Map<string, number>()\n for (const [index, item] of (scope.declarations ?? []).entries()) order.set(item.name, index)\n collections.sort((a, b) => {\n const left = order.get(a.name)\n const right = order.get(b.name)\n if (left !== undefined && right !== undefined) return left - right\n if (left !== undefined) return -1\n if (right !== undefined) return 1\n return a.name.localeCompare(b.name)\n })\n return {\n namespace: scope.namespace,\n storageNamespace: scope.storageNamespace,\n collections,\n }\n}\n\nexport type StateQuery = {\n limit?: number\n after?: number\n order?: \"newest\" | \"oldest\"\n}\n\nconst pageOf = (\n sqlite: SqliteClient,\n storageNamespace: string,\n name: string,\n query: StateQuery,\n): StateResult<StatePage> => {\n if (!COLLECTION_NAME.test(name)) return fail(400, \"collection name is not allowed\")\n const limit = query.limit ?? 50\n if (!Number.isInteger(limit) || limit < 1 || limit > 200) {\n return fail(400, \"limit must be an integer from 1 to 200\")\n }\n const order = query.order ?? \"newest\"\n if (order !== \"newest\" && order !== \"oldest\")\n return fail(400, 'order must be \"newest\" or \"oldest\"')\n const collection = collectionOf(sqlite, storageNamespace, name)\n const rows = collection.list({ order }).filter((row) => {\n if (query.after === undefined) return true\n return order === \"newest\" ? row.seq < query.after : row.seq > query.after\n })\n const slice = rows.slice(0, limit)\n const last = slice.at(-1)\n return {\n ok: true,\n value: {\n collection: name,\n count: collection.count(),\n records: slice.map((row) => ({ id: row.id, seq: row.seq, value: row.value })),\n next: rows.length > limit && last ? last.seq : null,\n },\n }\n}\n\nexport const readStatePage = (\n scope: Pick<StateScope, \"sqlite\" | \"storageNamespace\">,\n name: string,\n query: StateQuery = {},\n): StateResult<StatePage> => pageOf(scope.sqlite, scope.storageNamespace, name, query)\n\nexport const readStateRecord = (\n scope: Pick<StateScope, \"sqlite\" | \"storageNamespace\">,\n name: string,\n id: string,\n): StateResult<StateRecord> => {\n if (!COLLECTION_NAME.test(name)) return fail(400, \"collection name is not allowed\")\n if (!RECORD_ID.test(id)) return fail(400, \"record id is not allowed\")\n const record = readRecord(collectionOf(scope.sqlite, scope.storageNamespace, name), id)\n return record ? { ok: true, value: record } : fail(404, `no record ${id} in ${name}`)\n}\n\nconst requireId = (id: string): StateResult<string> =>\n RECORD_ID.test(id) ? { ok: true, value: id } : fail(400, \"id must be a single path segment\")\n\nexport const createStateRecord = (\n scope: Pick<StateScope, \"sqlite\" | \"storageNamespace\">,\n name: string,\n input: { id?: string; value: unknown },\n): StateResult<StateRecord> => {\n if (!COLLECTION_NAME.test(name)) return fail(400, \"collection name is not allowed\")\n const parsed = jsonValue(input.value)\n if (!parsed.ok) return parsed\n const collection = collectionOf(scope.sqlite, scope.storageNamespace, name)\n const id = input.id ?? `${name}_${collection.nextSequence()}`\n const checked = requireId(id)\n if (!checked.ok) return checked\n if (collection.has(checked.value)) return fail(409, `record ${checked.value} already exists`)\n const stored = collection.insert(checked.value, parsed.value)\n return { ok: true, value: { id: checked.value, seq: stored.seq, value: stored.value } }\n}\n\nexport const replaceStateRecord = (\n scope: Pick<StateScope, \"sqlite\" | \"storageNamespace\">,\n name: string,\n id: string,\n value: unknown,\n): StateResult<StateRecord> => {\n if (!COLLECTION_NAME.test(name)) return fail(400, \"collection name is not allowed\")\n const checked = requireId(id)\n if (!checked.ok) return checked\n const parsed = jsonValue(value)\n if (!parsed.ok) return parsed\n const collection = collectionOf(scope.sqlite, scope.storageNamespace, name)\n if (!collection.has(checked.value)) return fail(404, `no record ${checked.value} in ${name}`)\n const stored = collection.update(checked.value, parsed.value)\n if (!stored) return fail(404, `no record ${checked.value} in ${name}`)\n return { ok: true, value: { id: checked.value, seq: stored.seq, value: stored.value } }\n}\n\nexport const patchStateRecord = (\n scope: Pick<StateScope, \"sqlite\" | \"storageNamespace\">,\n name: string,\n id: string,\n value: unknown,\n): StateResult<StateRecord> => {\n const current = readStateRecord(scope, name, id)\n if (!current.ok) return current\n const parsed = jsonValue(value)\n if (!parsed.ok) return parsed\n const next =\n isRecord(current.value.value) && isRecord(parsed.value)\n ? { ...current.value.value, ...parsed.value }\n : parsed.value\n return replaceStateRecord(scope, name, id, next)\n}\n\nexport const deleteStateRecord = (\n scope: Pick<StateScope, \"sqlite\" | \"storageNamespace\">,\n name: string,\n id: string,\n): StateResult<{ id: string }> => {\n if (!COLLECTION_NAME.test(name)) return fail(400, \"collection name is not allowed\")\n const checked = requireId(id)\n if (!checked.ok) return checked\n const collection = collectionOf(scope.sqlite, scope.storageNamespace, name)\n return collection.delete(checked.value)\n ? { ok: true, value: { id: checked.value } }\n : fail(404, `no record ${checked.value} in ${name}`)\n}\n\nconst json = (status: number, body: unknown): Response =>\n new Response(JSON.stringify(body), {\n status,\n headers: { \"content-type\": \"application/json; charset=utf-8\" },\n })\n\nconst adminError = (status: number, message: string): Response =>\n json(status, { error: { type: \"mockingbird_admin\", message } })\n\nconst fromResult = <T>(result: StateResult<T>, status: number): Response =>\n result.ok ? json(status, result.value) : adminError(result.status, result.message)\n\nconst integerParam = (value: string | null): number | undefined | \"bad\" => {\n if (value === null) return undefined\n if (!/^-?\\d+$/.test(value)) return \"bad\"\n return Number(value)\n}\n\nexport type StateRoutes = {\n /** Open the public namespace and return the scope the state routes read. */\n open(namespace: string): StateScope\n /** Called after a successful write so Timeline records the new rows. */\n afterWrite?(namespace: string): void\n}\n\n/** The shared `/__admin/state*` routes. Registered after service routes so this key always wins. */\nexport const stateAdminRoutes = (routes: StateRoutes): AdminRoutes => {\n const open = (namespace: string): StateResult<StateScope> => {\n try {\n return { ok: true, value: routes.open(namespace) }\n } catch (error) {\n return fail(400, error instanceof Error ? error.message : String(error))\n }\n }\n const wrote = (namespace: string) => {\n routes.afterWrite?.(namespace)\n }\n return {\n \"GET /state\": ({ namespace }) => {\n const scope = open(namespace)\n return fromResult(scope.ok ? { ok: true, value: inspectState(scope.value) } : scope, 200)\n },\n \"GET /state/:collection\": ({ namespace, params, url }) => {\n const scope = open(namespace)\n if (!scope.ok) return fromResult(scope, 200)\n const limit = integerParam(url.searchParams.get(\"limit\"))\n const after = integerParam(url.searchParams.get(\"after\"))\n if (limit === \"bad\") return adminError(400, \"limit: expected an integer\")\n if (after === \"bad\") return adminError(400, \"after: expected a sequence number\")\n const order = url.searchParams.get(\"order\")\n return fromResult(\n readStatePage(scope.value, params.collection ?? \"\", {\n ...(limit !== undefined ? { limit } : {}),\n ...(after !== undefined ? { after } : {}),\n ...(order === \"newest\" || order === \"oldest\" ? { order } : {}),\n }),\n 200,\n )\n },\n \"GET /state/:collection/:id\": ({ namespace, params }) => {\n const scope = open(namespace)\n if (!scope.ok) return fromResult(scope, 200)\n return fromResult(readStateRecord(scope.value, params.collection ?? \"\", params.id ?? \"\"), 200)\n },\n \"POST /state/:collection\": ({ namespace, params, body }) => {\n const scope = open(namespace)\n if (!scope.ok) return fromResult(scope, 201)\n if (!isRecord(body) || !(\"value\" in body)) {\n return adminError(400, 'expected {\"id?\": \"<id>\", \"value\": <json>}')\n }\n const id = body.id\n if (id !== undefined && typeof id !== \"string\") return adminError(400, \"id must be a string\")\n const created = createStateRecord(scope.value, params.collection ?? \"\", {\n ...(typeof id === \"string\" ? { id } : {}),\n value: body.value,\n })\n if (created.ok) wrote(namespace)\n return fromResult(created, 201)\n },\n \"PUT /state/:collection/:id\": ({ namespace, params, body }) => {\n const scope = open(namespace)\n if (!scope.ok) return fromResult(scope, 200)\n if (!isRecord(body) || !(\"value\" in body))\n return adminError(400, 'expected {\"value\": <json>}')\n const replaced = replaceStateRecord(\n scope.value,\n params.collection ?? \"\",\n params.id ?? \"\",\n body.value,\n )\n if (replaced.ok) wrote(namespace)\n return fromResult(replaced, 200)\n },\n \"PATCH /state/:collection/:id\": ({ namespace, params, body }) => {\n const scope = open(namespace)\n if (!scope.ok) return fromResult(scope, 200)\n if (!isRecord(body) || !(\"value\" in body))\n return adminError(400, 'expected {\"value\": <json>}')\n const patched = patchStateRecord(\n scope.value,\n params.collection ?? \"\",\n params.id ?? \"\",\n body.value,\n )\n if (patched.ok) wrote(namespace)\n return fromResult(patched, 200)\n },\n \"DELETE /state/:collection/:id\": ({ namespace, params }) => {\n const scope = open(namespace)\n if (!scope.ok) return fromResult(scope, 200)\n const removed = deleteStateRecord(scope.value, params.collection ?? \"\", params.id ?? \"\")\n if (removed.ok) wrote(namespace)\n return fromResult(removed, 200)\n },\n }\n}\n", "/**\n * Set by `scripts/bundle-service.ts` when a service is bundled, and rewritten to the\n * released version when it is published. Undefined when running from source.\n */\ndeclare const __MOCKINGBIRD_PACKAGE_VERSION__: string | undefined\n\n/** Placeholder a bundle carries until `release:publish` writes the real version over it. */\nexport const UNRELEASED_VERSION = \"0.0.0-development\"\n\n/** The published version of the service package this code is bundled into. */\nexport const PACKAGE_VERSION: string =\n typeof __MOCKINGBIRD_PACKAGE_VERSION__ === \"string\"\n ? __MOCKINGBIRD_PACKAGE_VERSION__\n : UNRELEASED_VERSION\n", "import type { AdminRoutes } from \"./control.js\"\nimport type { OwnedTransport } from \"./outbound.js\"\nimport { signSvix, signTimestamped, signTwilio } from \"./signing.js\"\n\n/**\n * Outbound webhooks, shared by every service that has them.\n *\n * A service publishes a message (the exact bytes the vendor would send); the hub fans it out\n * to every matching endpoint, signs each delivery with the vendor's scheme, retries on the\n * vendor's schedule, and keeps a record a suite can read, replay or flush through\n * `/__admin/webhooks*`. Signature timestamps use the wall clock unless a service injects\n * `now`: receivers check them against their own time, and an advanced mock clock would\n * otherwise fail every delivery. A service whose caller injected the clock (Stripe) passes it,\n * so a virtual-time receiver verifies at the mock's time.\n */\n\n/** What a signer sees for one delivery attempt. */\nexport type SignInput = {\n messageId: string\n /** Exact bytes about to be sent. */\n body: string\n /** Unix seconds of this attempt: wall clock, or the hub's injected `now`. */\n timestampSeconds: number\n /** Where the delivery is posted. */\n url: string\n /** The endpoint's secret, if it has one. */\n secret: string | undefined\n /** The endpoint's `signUrl` (the public URL the receiver verifies against), else `url`. */\n signUrl: string\n /** Form parameters, when the body is form-encoded (Twilio signs these, not the body). */\n form: Record<string, string> | undefined\n /** Stable event type and metadata captured with the message; avoids signer side-channel state. */\n type: string\n tags: Readonly<Record<string, string>>\n}\n\n/** Headers to add to one delivery. */\nexport type WebhookSigner = (\n input: SignInput,\n) => Record<string, string> | Promise<Record<string, string>>\n\n/** Named signers for the vendor schemes the catalog needs. */\nexport const signers = {\n /** No signature. */\n none: (): WebhookSigner => () => ({}),\n /** Svix (`svix-id`, `svix-timestamp`, `svix-signature: v1,<b64>`): Junction, Flex, Resend. */\n svix:\n (options: { prefix?: \"svix\" | \"webhook\" } = {}): WebhookSigner =>\n async ({ messageId, body, timestampSeconds, secret }) => {\n if (!secret) return {}\n const prefix = options.prefix ?? \"svix\"\n return {\n [`${prefix}-id`]: messageId,\n [`${prefix}-timestamp`]: String(timestampSeconds),\n [`${prefix}-signature`]: await signSvix(secret, messageId, timestampSeconds, body),\n }\n },\n /** `<header>: t=<unix>,v1=<hex HMAC-SHA256(secret, \"t.body\")>`: Stripe, Persona, Fullscript. */\n timestamped:\n (header = \"Stripe-Signature\"): WebhookSigner =>\n async ({ body, timestampSeconds, secret }) =>\n secret ? { [header]: await signTimestamped(secret, timestampSeconds, body) } : {},\n /** `X-Twilio-Signature` over the public URL plus the sorted form parameters. */\n twilio:\n (): WebhookSigner =>\n async ({ signUrl, form, secret }) =>\n secret ? { \"X-Twilio-Signature\": await signTwilio(secret, signUrl, form ?? {}) } : {},\n /** The secret itself in a header (optionally templated): RxVortex, Pharmetika, AHA `Token <s>`. */\n header:\n (header: string, format: (secret: string) => string = (s) => s): WebhookSigner =>\n ({ secret }) =>\n secret ? { [header]: format(secret) } : {},\n /** Anything else: the service computes the headers itself. */\n custom: (sign: WebhookSigner): WebhookSigner => sign,\n}\n\nexport type WebhookEndpoint = {\n /** Stable id; generated when omitted. */\n id?: string\n url: string\n secret?: string\n /** Event types to deliver; omit or include `\"*\"` for every type. */\n events?: string[]\n /** Deliver only messages whose tags include all of these (e.g. `{ account: \"mso\" }`). */\n tags?: Record<string, string>\n /** The public URL the receiver verifies signatures against (Twilio), when it differs. */\n signUrl?: string\n headers?: Record<string, string>\n}\n\nexport type WebhookMessage = {\n id: string\n namespace: string\n type: string\n body: string\n contentType: string\n tags: Record<string, string>\n headers?: Record<string, string>\n /** Wall-clock ISO-8601 time of publication. */\n publishedAt: string\n}\n\nexport type WebhookAttempt = {\n attempt: number\n at: string\n status: number | null\n error: string | null\n durationMs: number\n /** Exact receiver response body, when one was returned. */\n responseBody?: string | null\n}\n\nexport type WebhookDelivery = {\n id: string\n messageId: string\n namespace: string\n type: string\n endpointId: string\n url: string\n state: \"pending\" | \"delivered\" | \"failed\" | \"dropped\"\n attempts: WebhookAttempt[]\n}\n\n/** A delivery-level fault: what happens to the next `count` messages in a namespace. */\nexport type WebhookFault = {\n mode: \"duplicate\" | \"reorder\" | \"drop\"\n /** Messages affected; default 1. */\n count?: number\n}\n\nexport type PublishInput = {\n namespace: string\n type: string\n /** Exact body; objects are JSON-encoded. */\n body: string | Record<string, unknown> | unknown[]\n /** Default `application/json`, or form-encoded when `form` is given. */\n contentType?: string\n /** Form parameters, when the vendor posts `application/x-www-form-urlencoded`. */\n form?: Record<string, string>\n tags?: Record<string, string>\n /** Message-specific delivery headers, captured as part of durable message state. */\n headers?: Record<string, string>\n /** Message id; generated when omitted. */\n id?: string\n}\n\nexport type WebhookHubOptions = {\n signer: WebhookSigner\n /**\n * Delay before each attempt, in ms; the first entry delays the first attempt. Default:\n * immediately, then 5 s, 5 min, 30 min, 2 h.\n */\n retryDelaysMs?: readonly number[]\n /** Abort an attempt after this long. Default 15 s. */\n timeoutMs?: number\n /** Which receiver statuses count as delivered. Default 2xx. */\n delivered?: (status: number) => boolean\n /** Endpoints every namespace delivers to (from `--webhook-url`). */\n endpoints?: WebhookEndpoint[]\n fetch?: (request: Request) => Promise<Response>\n /** Called in-process for every published message, delivered or not. */\n onMessage?: (message: WebhookMessage) => void\n /** Messages kept per namespace for `GET /__admin/webhooks/events`. Default 500. */\n keep?: number\n /** Injectable clock (default wall clock) for signatures and attempt records. */\n now?: () => number\n /** Injectable deterministic identifier source. Receives `\"msg_\"` or `\"dlv_\"`. */\n id?: (prefix: string) => string\n /** Injectable scheduler used by timeouts and retries. */\n schedule?: (callback: () => void, delayMs: number) => unknown\n cancel?: (handle: unknown) => void\n}\n\nexport type WebhookHub = {\n observeDeliveries(\n listener: (event: { namespace: string; state: string; deliveryId: string }) => void,\n ): () => void\n setTransportPolicy(policy: OwnedTransport): void\n pending(namespace: string): number\n snapshot(namespace: string): unknown\n exportSnapshot(handle: unknown): unknown\n importSnapshot(namespace: string, document: unknown): unknown\n restore(namespace: string, snapshot: unknown): void\n publish(input: PublishInput): WebhookMessage\n /** Replace a namespace's own endpoints (`PUT /__admin/webhook-endpoints`). */\n setEndpoints(namespace: string, endpoints: WebhookEndpoint[]): WebhookEndpoint[]\n /** The endpoints a namespace delivers to: its own, plus the global ones. */\n endpoints(namespace: string): WebhookEndpoint[]\n messages(namespace?: string): WebhookMessage[]\n deliveries(namespace?: string): WebhookDelivery[]\n replay(deliveryId: string): Promise<WebhookDelivery | undefined>\n /** Run every pending retry (and release held reordered messages) now, and every retry those attempts schedule, until nothing is pending. */\n flush(): Promise<void>\n /** Resolve once nothing is in flight. */\n idle(namespace?: string): Promise<void>\n fault(namespace: string, fault: WebhookFault): void\n clear(namespace?: string): void\n}\n\nconst DEFAULT_DELAYS = [0, 5_000, 300_000, 1_800_000, 7_200_000] as const\n\nconst unref = (timer: unknown) => {\n ;(timer as { unref?: () => void }).unref?.()\n}\n\nconst randomId = (prefix: string) =>\n `${prefix}${crypto.randomUUID().replace(/-/g, \"\").slice(0, 24)}`\n\nconst matchesEndpoint = (endpoint: WebhookEndpoint, message: WebhookMessage): boolean => {\n const events = endpoint.events ?? [\"*\"]\n if (!events.includes(\"*\") && !events.includes(message.type)) return false\n for (const [key, value] of Object.entries(endpoint.tags ?? {})) {\n if (message.tags[key] !== value) return false\n }\n return true\n}\n\nexport const createWebhookHub = (options: WebhookHubOptions): WebhookHub => {\n const delays = options.retryDelaysMs ?? DEFAULT_DELAYS\n const timeoutMs = options.timeoutMs ?? 15_000\n const delivered = options.delivered ?? ((status: number) => status >= 200 && status < 300)\n const send = options.fetch ?? ((request: Request) => fetch(request))\n const keep = options.keep ?? 500\n const now = options.now ?? Date.now\n const id = options.id ?? randomId\n const scheduleTimer =\n options.schedule ?? ((callback: () => void, delayMs: number) => setTimeout(callback, delayMs))\n const cancel =\n options.cancel ?? ((handle: unknown) => clearTimeout(handle as ReturnType<typeof setTimeout>))\n const global = (options.endpoints ?? []).map((e, i) => ({ ...e, id: e.id ?? `we_global_${i}` }))\n const own = new Map<string, WebhookEndpoint[]>()\n const messages: WebhookMessage[] = []\n const deliveries = new Map<string, WebhookDelivery>()\n const pending = new Map<string, unknown | undefined>()\n const payloads = new Map<string, { message: WebhookMessage; endpoint: WebhookEndpoint }>()\n const faults = new Map<string, { mode: WebhookFault[\"mode\"]; remaining: number }[]>()\n const held = new Map<string, WebhookMessage[]>()\n const deliveryObservers = new Set<\n (event: { namespace: string; state: string; deliveryId: string }) => void\n >()\n const notify = (delivery: WebhookDelivery) => {\n for (const listener of deliveryObservers)\n try {\n listener({ namespace: delivery.namespace, state: delivery.state, deliveryId: delivery.id })\n } catch {}\n }\n let transport: OwnedTransport | undefined\n const inFlight = new Set<Promise<void>>()\n const workNamespace = new Map<Promise<void>, string>()\n const activeDeliveries = new Map<string, { namespace: string; count: number }>()\n const controllers = new Map<string, AbortController>()\n // Immediate (delay 0) attempts chain onto this so two deliveries scheduled in the same tick\n // (e.g. a reorder fault's swap) hit the receiver in schedule order, not fetch-race order.\n let immediate: Promise<unknown> = Promise.resolve()\n const snapshots = new WeakMap<\n object,\n {\n namespace: string\n endpoints: WebhookEndpoint[]\n messages: WebhookMessage[]\n deliveries: [string, WebhookDelivery][]\n payloads: [string, { message: WebhookMessage; endpoint: WebhookEndpoint }][]\n faults: { mode: WebhookFault[\"mode\"]; remaining: number }[]\n }\n >()\n\n const track = (work: Promise<void>, delivery: WebhookDelivery) => {\n inFlight.add(work)\n workNamespace.set(work, delivery.namespace)\n const active = activeDeliveries.get(delivery.id) ?? { namespace: delivery.namespace, count: 0 }\n active.count++\n activeDeliveries.set(delivery.id, active)\n const finish = () => {\n inFlight.delete(work)\n workNamespace.delete(work)\n active.count--\n if (active.count === 0) activeDeliveries.delete(delivery.id)\n }\n void work.then(finish, finish)\n }\n\n const attempt = async (delivery: WebhookDelivery): Promise<boolean> => {\n const entry = payloads.get(delivery.id)\n if (!entry) return false\n const { message, endpoint } = entry\n const timestampSeconds = Math.floor(now() / 1000)\n const started = now()\n const record: WebhookAttempt = {\n attempt: delivery.attempts.length + 1,\n at: new Date(started).toISOString(),\n status: null,\n error: null,\n durationMs: 0,\n responseBody: null,\n }\n const controller = new AbortController()\n controllers.set(delivery.id, controller)\n const timer = scheduleTimer(() => controller.abort(), timeoutMs)\n try {\n const signed = await options.signer({\n messageId: message.id,\n body: message.body,\n timestampSeconds,\n url: endpoint.url,\n secret: endpoint.secret,\n signUrl: endpoint.signUrl ?? endpoint.url,\n form: message.contentType.startsWith(\"application/x-www-form-urlencoded\")\n ? Object.fromEntries(new URLSearchParams(message.body))\n : undefined,\n type: message.type,\n tags: message.tags,\n })\n const ownedSend = (request: Request) =>\n transport ? transport(request, message.namespace, send as typeof fetch) : send(request)\n const response = await ownedSend(\n new Request(endpoint.url, {\n method: \"POST\",\n headers: {\n \"content-type\": message.contentType,\n ...endpoint.headers,\n ...message.headers,\n ...signed,\n },\n body: message.body,\n signal: controller.signal,\n }),\n )\n record.status = response.status\n record.responseBody = await response.text()\n } catch (error) {\n record.error = controller.signal.aborted\n ? `timed out after ${timeoutMs}ms`\n : error instanceof Error\n ? error.message\n : String(error)\n } finally {\n controllers.delete(delivery.id)\n cancel(timer)\n record.durationMs = now() - started\n delivery.attempts.push(record)\n }\n return record.status !== null && delivered(record.status)\n }\n\n const schedule = (delivery: WebhookDelivery) => {\n const index = delivery.attempts.length\n if (index >= delays.length) {\n delivery.state = \"failed\"\n notify(delivery)\n pending.delete(delivery.id)\n return\n }\n const settle = async () => {\n // `clear` can drop a delivery queued behind an earlier immediate attempt. Its attempt would\n // record nothing and reschedule at the same index forever, starving the event loop.\n if (!payloads.has(delivery.id)) return\n await attempt(delivery).then((ok) => {\n if (!payloads.has(delivery.id)) return\n if (ok) {\n delivery.state = \"delivered\"\n notify(delivery)\n } else schedule(delivery)\n })\n }\n const delay = delays[index] ?? 0\n if (delay <= 0) {\n const task = immediate.then(settle)\n immediate = task.catch(() => {})\n track(task, delivery)\n return\n }\n const timer = scheduleTimer(() => {\n pending.delete(delivery.id)\n track(settle(), delivery)\n }, delay)\n unref(timer)\n pending.set(delivery.id, timer)\n }\n\n const endpointsFor = (namespace: string) => [...(own.get(namespace) ?? []), ...global]\n\n const fanOut = (message: WebhookMessage, state: WebhookDelivery[\"state\"] = \"pending\") => {\n for (const endpoint of endpointsFor(message.namespace)) {\n if (!matchesEndpoint(endpoint, message)) continue\n const delivery: WebhookDelivery = {\n id: id(\"dlv_\"),\n messageId: message.id,\n namespace: message.namespace,\n type: message.type,\n endpointId: endpoint.id ?? \"we_unknown\",\n url: endpoint.url,\n state,\n attempts: [],\n }\n deliveries.set(delivery.id, delivery)\n payloads.set(delivery.id, { message, endpoint })\n if (state === \"pending\") schedule(delivery)\n else notify(delivery)\n }\n }\n\n const takeFault = (namespace: string): WebhookFault[\"mode\"] | undefined => {\n const queue = faults.get(namespace)\n const head = queue?.[0]\n if (!queue || !head) return undefined\n head.remaining--\n if (head.remaining <= 0) queue.shift()\n return head.mode\n }\n\n const releaseHeld = (namespace: string) => {\n const waiting = held.get(namespace)\n if (!waiting) return\n held.delete(namespace)\n for (const message of waiting) fanOut(message)\n }\n\n const hub: WebhookHub = {\n observeDeliveries(listener) {\n deliveryObservers.add(listener)\n return () => deliveryObservers.delete(listener)\n },\n setTransportPolicy(policy) {\n transport = policy\n },\n pending(namespace) {\n const ids = new Set(\n [...deliveries.values()]\n .filter((d) => d.namespace === namespace && d.state === \"pending\")\n .map((d) => d.id),\n )\n for (const [id, active] of activeDeliveries) if (active.namespace === namespace) ids.add(id)\n return ids.size + (held.get(namespace)?.length ?? 0)\n },\n snapshot(namespace) {\n if (hub.pending(namespace) > 0) throw new Error(\"webhooks are not quiescent\")\n const handle = {}\n snapshots.set(\n handle,\n structuredClone({\n namespace,\n endpoints: own.get(namespace) ?? [],\n messages: messages.filter((m) => m.namespace === namespace),\n deliveries: [...deliveries].filter(([, d]) => d.namespace === namespace),\n payloads: [...payloads].filter(([, p]) => p.message.namespace === namespace),\n faults: faults.get(namespace) ?? [],\n }),\n )\n return handle\n },\n exportSnapshot(handle) {\n const point =\n typeof handle === \"object\" && handle !== null ? snapshots.get(handle) : undefined\n if (!point) throw new Error(\"invalid webhook snapshot\")\n const { namespace: _namespace, ...document } = point\n return structuredClone(document)\n },\n importSnapshot(namespace, document) {\n if (\n !isRecord(document) ||\n !Array.isArray(document.endpoints) ||\n !Array.isArray(document.messages) ||\n !Array.isArray(document.deliveries) ||\n !Array.isArray(document.payloads) ||\n !Array.isArray(document.faults)\n )\n throw new Error(\"invalid portable webhook snapshot\")\n for (const endpoint of document.endpoints)\n if (typeof parseEndpoint(endpoint) === \"string\")\n throw new Error(\"invalid portable webhook endpoint\")\n for (const message of document.messages)\n if (\n !isRecord(message) ||\n typeof message.id !== \"string\" ||\n typeof message.body !== \"string\"\n )\n throw new Error(\"invalid portable webhook message\")\n for (const pair of [...document.deliveries, ...document.payloads])\n if (\n !Array.isArray(pair) ||\n pair.length !== 2 ||\n typeof pair[0] !== \"string\" ||\n !isRecord(pair[1])\n )\n throw new Error(\"invalid portable webhook entry\")\n const handle = {}\n const point = structuredClone(document) as Omit<\n NonNullable<ReturnType<typeof snapshots.get>>,\n \"namespace\"\n >\n for (const message of point.messages) message.namespace = namespace\n for (const [, delivery] of point.deliveries) delivery.namespace = namespace\n for (const [, payload] of point.payloads) payload.message.namespace = namespace\n snapshots.set(handle, { ...point, namespace })\n return handle\n },\n restore(namespace, handle) {\n const point =\n typeof handle === \"object\" && handle !== null ? snapshots.get(handle) : undefined\n if (!point || point.namespace !== namespace || hub.pending(namespace) > 0)\n throw new Error(\"invalid webhook restore\")\n hub.clear(namespace)\n const copied = structuredClone(point)\n own.set(namespace, copied.endpoints)\n messages.push(...copied.messages)\n for (const [id, delivery] of copied.deliveries) deliveries.set(id, delivery)\n for (const [id, payload] of copied.payloads) payloads.set(id, payload)\n faults.set(namespace, copied.faults)\n },\n publish(input) {\n const contentType =\n input.contentType ?? (input.form ? \"application/x-www-form-urlencoded\" : \"application/json\")\n const body =\n typeof input.body === \"string\"\n ? input.body\n : input.form\n ? new URLSearchParams(input.form).toString()\n : JSON.stringify(input.body)\n const message: WebhookMessage = {\n id: input.id ?? id(\"msg_\"),\n namespace: input.namespace,\n type: input.type,\n body,\n contentType,\n tags: input.tags ?? {},\n headers: input.headers ?? {},\n publishedAt: new Date(now()).toISOString(),\n }\n messages.push(message)\n const ofNamespace = messages.filter((m) => m.namespace === message.namespace)\n const oldest = ofNamespace[0]\n if (ofNamespace.length > keep && oldest) messages.splice(messages.indexOf(oldest), 1)\n options.onMessage?.(message)\n const fault = takeFault(message.namespace)\n if (fault === \"drop\") {\n fanOut(message, \"dropped\")\n return message\n }\n if (fault === \"reorder\") {\n // Held until the next message goes out, so the receiver sees them swapped.\n held.set(message.namespace, [...(held.get(message.namespace) ?? []), message])\n return message\n }\n fanOut(message)\n if (fault === \"duplicate\") fanOut(message)\n releaseHeld(message.namespace)\n return message\n },\n setEndpoints(namespace, endpoints) {\n const withIds = endpoints.map((e, i) => ({ ...e, id: e.id ?? `we_${namespace}_${i}` }))\n own.set(namespace, withIds)\n return withIds\n },\n endpoints: endpointsFor,\n messages: (namespace) =>\n namespace === undefined ? [...messages] : messages.filter((m) => m.namespace === namespace),\n deliveries: (namespace) =>\n [...deliveries.values()].filter((d) => namespace === undefined || d.namespace === namespace),\n async replay(id) {\n const delivery = deliveries.get(id)\n if (!delivery) return undefined\n const work = (async () => {\n const ok = await attempt(delivery)\n if (ok) delivery.state = \"delivered\"\n notify({ ...delivery, state: ok ? \"delivered\" : \"failed\" })\n })()\n track(work, delivery)\n await work\n return delivery\n },\n async flush() {\n // Drains until nothing is held or scheduled: a retry that an attempt failing during this\n // flush schedules runs too, so a caller asserting after `flush` never catches a delivery\n // between attempts. Bounded, as every pass moves each delivery an attempt closer to\n // `delivered` or `failed`.\n for (;;) {\n for (const namespace of [...held.keys()]) releaseHeld(namespace)\n const waiting = [...pending.entries()]\n for (const [id, timer] of waiting) {\n if (timer === undefined) continue\n cancel(timer)\n pending.delete(id)\n const delivery = deliveries.get(id)\n if (!delivery) continue\n track(\n attempt(delivery).then((ok) => {\n if (ok) {\n delivery.state = \"delivered\"\n notify(delivery)\n } else schedule(delivery)\n }),\n delivery,\n )\n }\n await hub.idle()\n const scheduled = [...pending.values()].some((timer) => timer !== undefined)\n if (held.size === 0 && !scheduled) return\n }\n },\n async idle(namespace) {\n for (;;) {\n const selected = [...inFlight].filter(\n (work) => namespace === undefined || workNamespace.get(work) === namespace,\n )\n if (!selected.length) return\n await Promise.allSettled(selected)\n }\n },\n fault(namespace, fault) {\n const queue = faults.get(namespace) ?? []\n queue.push({ mode: fault.mode, remaining: Math.max(1, fault.count ?? 1) })\n faults.set(namespace, queue)\n },\n clear(namespace) {\n for (const [id, delivery] of deliveries) {\n if (namespace !== undefined && delivery.namespace !== namespace) continue\n controllers.get(id)?.abort()\n const timer = pending.get(id)\n if (timer !== undefined) cancel(timer)\n pending.delete(id)\n deliveries.delete(id)\n payloads.delete(id)\n }\n for (let i = messages.length - 1; i >= 0; i--) {\n if (namespace === undefined || messages[i]?.namespace === namespace) messages.splice(i, 1)\n }\n if (namespace === undefined) {\n held.clear()\n faults.clear()\n own.clear()\n } else {\n held.delete(namespace)\n faults.delete(namespace)\n own.delete(namespace)\n }\n },\n }\n return hub\n}\n\nconst json = (status: number, body: unknown): Response =>\n new Response(JSON.stringify(body), {\n status,\n headers: { \"content-type\": \"application/json; charset=utf-8\" },\n })\n\nconst adminError = (status: number, message: string): Response =>\n json(status, { error: { type: \"mockingbird_admin\", message } })\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n\nconst parseEndpoint = (value: unknown): WebhookEndpoint | string => {\n if (!isRecord(value) || typeof value.url !== \"string\") return \"each endpoint needs a url\"\n try {\n new URL(value.url)\n } catch {\n return `not a URL: ${value.url}`\n }\n const endpoint: WebhookEndpoint = { url: value.url }\n if (typeof value.id === \"string\") endpoint.id = value.id\n if (typeof value.secret === \"string\") endpoint.secret = value.secret\n if (typeof value.signUrl === \"string\") endpoint.signUrl = value.signUrl\n const events = value.events ?? value.enabledEvents\n if (Array.isArray(events)) endpoint.events = events.map(String)\n if (isRecord(value.tags)) {\n endpoint.tags = Object.fromEntries(Object.entries(value.tags).map(([k, v]) => [k, String(v)]))\n }\n if (typeof value.account === \"string\")\n endpoint.tags = { ...endpoint.tags, account: value.account }\n if (isRecord(value.headers)) {\n endpoint.headers = Object.fromEntries(\n Object.entries(value.headers).map(([k, v]) => [k, String(v)]),\n )\n }\n return endpoint\n}\n\n/**\n * The standard webhook admin routes, for a runtime that owns `hub`:\n *\n * - `GET /webhooks` deliveries, `GET /webhooks/events` published messages (with bodies:\n * they are the mock's own output), `POST /webhooks/:id/replay`, `POST /webhooks/flush`\n * - `GET|PUT|DELETE /webhook-endpoints` per namespace\n * - `POST /webhooks/faults {mode: duplicate|reorder|drop, count?}`\n */\nexport const webhookAdminRoutes = (hub: WebhookHub): AdminRoutes => ({\n \"GET /webhooks\": ({ url, namespace }) =>\n json(200, {\n deliveries: hub\n .deliveries(url.searchParams.get(\"all\") === \"1\" ? undefined : namespace)\n .filter((d) => {\n const type = url.searchParams.get(\"type\")\n return type === null || d.type === type\n }),\n }),\n \"GET /webhooks/events\": ({ url, namespace }) => {\n const type = url.searchParams.get(\"type\")\n return json(200, {\n events: hub\n .messages(url.searchParams.get(\"all\") === \"1\" ? undefined : namespace)\n .filter((m) => type === null || m.type === type)\n .map((m) => ({ ...m, payload: parsePayload(m) })),\n })\n },\n \"POST /webhooks/:id/replay\": async ({ params }) => {\n const replayed = await hub.replay(params.id as string)\n return replayed ? json(200, replayed) : adminError(404, `no delivery ${params.id}`)\n },\n \"POST /webhooks/flush\": async () => {\n await hub.flush()\n return json(200, { status: \"ok\" })\n },\n \"POST /webhooks/faults\": ({ body, namespace }) => {\n if (!isRecord(body) || ![\"duplicate\", \"reorder\", \"drop\"].includes(String(body.mode))) {\n return adminError(400, \"mode must be duplicate, reorder or drop\")\n }\n const fault: WebhookFault = { mode: body.mode as WebhookFault[\"mode\"] }\n if (typeof body.count === \"number\") fault.count = body.count\n hub.fault(namespace, fault)\n return json(201, { namespace, ...fault })\n },\n \"GET /webhook-endpoints\": ({ namespace }) =>\n json(200, {\n endpoints: hub.endpoints(namespace).map(({ secret, ...rest }) => ({\n ...rest,\n secret: secret ? \"(set)\" : null,\n })),\n }),\n \"PUT /webhook-endpoints\": ({ body, namespace }) => {\n const list = Array.isArray(body) ? body : isRecord(body) ? body.endpoints : undefined\n if (!Array.isArray(list)) return adminError(400, \"expected [{url, secret?, events?}]\")\n const parsed: WebhookEndpoint[] = []\n for (const each of list) {\n const endpoint = parseEndpoint(each)\n if (typeof endpoint === \"string\") return adminError(400, endpoint)\n parsed.push(endpoint)\n }\n const set = hub.setEndpoints(namespace, parsed)\n return json(200, { endpoints: set.map((e) => ({ ...e, secret: e.secret ? \"(set)\" : null })) })\n },\n \"DELETE /webhook-endpoints\": ({ namespace }) => {\n hub.setEndpoints(namespace, [])\n return json(200, { status: \"ok\" })\n },\n})\n\nconst parsePayload = (message: WebhookMessage): unknown => {\n if (message.contentType.startsWith(\"application/json\")) {\n try {\n return JSON.parse(message.body)\n } catch {\n return message.body\n }\n }\n if (message.contentType.startsWith(\"application/x-www-form-urlencoded\")) {\n return Object.fromEntries(new URLSearchParams(message.body))\n }\n return message.body\n}\n", "import {\n type Checkpoint,\n type FetchAPI,\n forwardMountContext,\n type MountedAPI,\n mount,\n Timeline,\n} from \"@crvouga/mockingbird-core\"\nimport { listOperations, type OpenAPIDocument } from \"@crvouga/mockingbird-openapi\"\nimport { clearNamespace, type SqliteClient } from \"@crvouga/mockingbird-sqlite\"\nimport { adminUiRoutes } from \"./admin-ui.js\"\nimport {\n type Clock,\n type ClockState,\n createClock,\n type DerivedClock,\n deriveClock,\n restoreClock,\n} from \"./clock.js\"\nimport {\n ADMIN_KEY_HEADER,\n ADMIN_PREFIX,\n type AdminRoutes,\n assertAdminPrefixAvailable,\n createControlPlane,\n hasAdminKey,\n isAdminPath,\n matchNamespacePath,\n NAMESPACE_HEADER,\n resolveAdminPrefix,\n type SnapshotInfo,\n type SnapshotStore,\n} from \"./control.js\"\nimport {\n assertSnapshotDocument,\n CONTROL_HEADERS,\n ControlError,\n type ControlHeaderInput,\n type ControlPlan,\n controlHeaders,\n isRecord,\n KEY_PATTERN,\n type MockControls,\n type NamespaceControls as NamespaceControlsInput,\n normalizeBootControls,\n normalizeClock,\n normalizeControls,\n normalizeLatency,\n normalizeSeed,\n parseControlHeaders,\n type RequestControls,\n SNAPSHOT_FORMAT,\n type SnapshotDocument,\n} from \"./controls.js\"\nimport { type CredentialRegistry, createCredentialRegistry, maskCredential } from \"./credentials.js\"\nimport {\n type FaultHit,\n type FaultPreset,\n type FaultRegistry,\n type FaultRule,\n normalizeFault,\n} from \"./faults.js\"\nimport { type IdBase, normalizeIdBase, setIdBase } from \"./ids.js\"\nimport {\n createJournal,\n DEFAULT_JOURNAL_SIZE,\n type Journal,\n type ResponseNotes,\n responseNotes,\n} from \"./journal.js\"\nimport type { LatencyRegistry } from \"./latency.js\"\nimport { createMetrics, type Metrics, type RejectedRequest, type RequestLog } from \"./metrics.js\"\nimport {\n type BootScope,\n type ControlSettings,\n type ControlState,\n type ControlsSnapshot,\n createNamespaceControls,\n} from \"./namespace-controls.js\"\nimport { operationPath } from \"./path.js\"\nimport { createRng, type Rng, seedFrom } from \"./rng.js\"\nimport { bootSqlite } from \"./service.js\"\nimport { type NamespaceSnapshot, restoreNamespace, snapshotNamespace } from \"./snapshot.js\"\nimport {\n inspectState,\n type StateDeclaration,\n type StateView,\n stateAdminRoutes,\n} from \"./state-view.js\"\nimport { type AdminUi, assertAdminUi, defineMock, type MockSurface } from \"./surface.js\"\nimport { PACKAGE_VERSION } from \"./version.js\"\nimport { type WebhookHub, webhookAdminRoutes } from \"./webhooks.js\"\n\n/**\n * Stamped on every response the runtime returns \u2014 vendor, fault, admin and health alike \u2014\n * as `<service>@<version>; ns=<namespace>`, so a consumer can tell the mock from the vendor.\n */\nexport const MOCKINGBIRD_HEADER = \"x-mockingbird\"\n/** Selects a named copy-on-write history branch. `main` is the compatibility default. */\nexport const BRANCH_HEADER = CONTROL_HEADERS.branch\n/** Reads a historical checkpoint. With a branch header, initializes that branch from it. */\nexport const AT_HEADER = CONTROL_HEADERS.at\n/** Identifies the resulting checkpoint on successful mutations. */\nexport const CHECKPOINT_HEADER = \"x-mockingbird-checkpoint\"\n/** On a response a fault rule answered or shaped: that rule's id. */\nexport const FAULT_HEADER = CONTROL_HEADERS.fault\n/** On a response to a request that asked for a snapshot: the snapshot's id. */\nexport const SNAPSHOT_HEADER = CONTROL_HEADERS.snapshot\n\n/** What the runtime needs from a service: a Fetch handler it can reset. */\nexport type ServiceInstance = FetchAPI & { reset(): Promise<void> }\n\n/** Everything an instance shares with the runtime that owns it. */\nexport type InstanceContext = {\n /** Storage namespace for this instance's records. */\n namespace: string\n /** The public namespace name a request selects it by. */\n adminPrefix: string\n publicNamespace: string\n sqlite: SqliteClient\n clock: Clock\n rng: Rng\n}\n\nexport type RuntimeOptions<T extends ServiceInstance> = {\n /** Service name, e.g. `\"junction\"`. Also the default namespace's storage key. */\n name: string\n /** Build the instance backing one namespace. Called once per namespace, on first use. */\n create: (context: InstanceContext) => T\n /** The vendor contract, used to name each request's operation in logs, metrics and faults. */\n document?: OpenAPIDocument\n /** Shared by every namespace. Defaults to a fresh `@crvouga/mockingbird-service-sqlite`. */\n sqlite?: SqliteClient\n /** Defaults to a live clock over `Date.now`. */\n clock?: Clock\n /**\n * Where this boot's generated ids start. Counters restart at 0 on every boot, so by default\n * every boot reissues the previous boot's ids; a different base gives an unrelated run of ids\n * (a reset returns to the same run). A non-negative integer, or `\"boot\"` for one derived from\n * the wall clock when the runtime is created. Default `0`: the same ids on every boot.\n */\n idBase?: IdBase\n /** Seeds every random choice the runtime makes (fault rates, jitter). Default `0`. */\n seed?: number | string\n /**\n * Admin controls to boot with: clock, latency, faults, a starting snapshot, credential\n * mappings and per-namespace overrides. `reset` returns a namespace to exactly this.\n */\n adminControls?: MockControls\n /** Extra `GET /__admin/health` fields, such as the loaded corpus version. */\n describe?: () => Record<string, unknown>\n /** Service-specific admin routes, given the runtime so they can reach any namespace. */\n admin?: (runtime: ServiceRuntime<T>) => AdminRoutes\n /** Reserved tree for every internal HTTP endpoint, UI and namespace carrier. Default /__admin. */\n adminPrefix?: string\n /**\n * A namespace's clock was moved \u2014 by `/__admin/clock`, a header, a restore, a reset, or a\n * wait spent in virtual time. Run whatever the service schedules by that clock, so what\n * came due is seen at once and not on the next request. Moving the base clock in process\n * (`runtime.clock`) is the caller's own doing and is not reported here.\n */\n onClockChange?: (namespace: string) => void\n /** Invalidate transient handles before replacing an existing instance's stored state. */\n beforeRestore?: (instance: T) => void\n /** Require this value in `x-mockingbird-admin-key` on admin data routes. */\n adminKey?: string\n /** Structured request log sink, called once per request. */\n onLog?: (entry: RequestLog) => void\n /** Requests each namespace's journal keeps (`GET /__admin/requests`). Default 1000; 0 turns it off. */\n journalSize?: number\n /** Reported in the `x-mockingbird` header. Default: the bundled package's version. */\n version?: string\n /**\n * The vendor credential a request carries (API key, token, account SID, AWS access key\n * id), for SDKs that cannot send `x-mockingbird-namespace`: a suite maps credentials to\n * namespaces with `PUT /__admin/credentials`. See `bearerToken`, `basicAuth`,\n * `sigV4AccessKeyId`.\n */\n credential?: (request: Request) => string | undefined\n /**\n * Named faults, switched on with `POST /__admin/faults {\"preset\": \"<name>\"}`. They join the\n * standard presets every mock has; one with a standard name replaces it.\n */\n presets?: Record<string, FaultPreset>\n /** Outbound webhooks; adds the `/__admin/webhooks*` routes and clears on reset. */\n webhooks?: WebhookHub\n /** Retained time-travel checkpoints per namespace. Default 1,000. */\n maxCheckpoints?: number\n /** Injectable process IO used for observability and delays; logical service time uses `clock`. */\n io?: Partial<RuntimeIO>\n /**\n * Collections the admin UI should show even before any row exists.\n * Stored collections are always included, whether or not they are declared.\n * A function may describe collections that depend on the live instance.\n */\n state?: readonly StateDeclaration[] | ((api: T, namespace: string) => readonly StateDeclaration[])\n /**\n * Panels added to the default admin UI, or a function that replaces the document.\n * `render` receives `defaultHtml()` so a bespoke UI can wrap the shared shell.\n */\n adminUi?: AdminUi\n}\n\nexport type RuntimeIO = {\n wallNow(): number\n monotonicNow(): number\n /** Wait on the wall clock. Rejects with the signal's reason when it aborts first. */\n sleep(ms: number, signal?: AbortSignal): Promise<void>\n}\n\nexport type ServiceTimelineState = Readonly<{\n snapshot: NamespaceSnapshot\n /** `pinned`: the namespace's clock was frozen itself, not just following a frozen base. */\n clock: Readonly<ClockState & { pinned?: boolean }>\n rngState: number\n}>\n\nexport type ServiceCheckpoint = Checkpoint<ServiceTimelineState>\n\nexport type ServiceRuntime<T extends ServiceInstance> = FetchAPI & {\n /** Stop package-owned lifecycle timers when a supervisor closes the runtime. */\n stop?(): void\n readonly name: string\n /** Same-origin Fetch handler and App Router method exports, sharing this runtime. */\n mount(prefix: string): MountedAPI\n readonly sqlite: SqliteClient\n readonly clock: Clock\n /**\n * Change the id base ({@link RuntimeOptions.idBase}) for ids generated from now on, and\n * return the number it resolved to. Set it before the first request so a boot's ids stay\n * one run.\n */\n setIdBase(base: IdBase): number\n readonly faults: FaultRegistry\n /** Baseline response time per namespace. */\n readonly latency: LatencyRegistry\n readonly metrics: Metrics\n readonly journal: Journal\n readonly rng: Rng\n readonly credentials: CredentialRegistry\n /** The webhook hub, when the service has outbound webhooks. */\n readonly webhooks: WebhookHub | undefined\n /**\n * A namespace's clock. Each follows the base clock, {@link ServiceRuntime.clock}, with an\n * offset and a freeze of its own, so moving one never moves another.\n */\n namespaceClock(namespace?: string): Clock\n namespaceOf(request: Request): string\n /** Opaque in-process checkpoint including records, controls and webhook history. */\n fleetSnapshot(namespace: string): object\n fleetRestore(snapshot: unknown, namespace: string): void\n fleetExport(snapshot: unknown): SnapshotDocument\n fleetImport(namespace: string, document: unknown): object\n /** Expand a named preset into fault rules (and webhook faults) for `namespace`. */\n applyPreset(name: string, namespace?: string, overrides?: Partial<FaultRule>): FaultRule[]\n /** The instance behind `namespace` (the default one when omitted), created on first use. */\n instance(namespace?: string): T\n /** Public names of every namespace created so far. */\n namespaces(): string[]\n /** Return one namespace to its boot state, or every namespace with `\"*\"`. */\n reset(namespace?: string): Promise<void>\n /** Reset a namespace and forget it, releasing everything it held. */\n dropNamespace(namespace: string): Promise<void>\n /** A namespace's controls: seed, clock, virtual time, latency, faults and snapshots. */\n controls(namespace?: string): ControlState & { snapshots: SnapshotInfo[] }\n /** Apply a control document to a namespace. A given key replaces that control. */\n configure(\n controls: NamespaceControlsInput,\n namespace?: string,\n ): ControlState & { snapshots: SnapshotInfo[] }\n /** Named snapshots of a namespace: records, clock, random streams, faults and latency. */\n readonly snapshots: {\n /** Capture the namespace now. Reusing a name replaces that snapshot. */\n create(options?: { name?: string; namespace?: string }): SnapshotInfo\n list(namespace?: string): SnapshotInfo[]\n /** The snapshot as portable JSON, to commit beside a suite or boot another mock from. */\n export(id: string, namespace?: string): SnapshotDocument\n /** Store a document as a snapshot without restoring it. */\n import(\n document: SnapshotDocument,\n options?: { name?: string; namespace?: string },\n ): SnapshotInfo\n restore(id: string, namespace?: string): void\n delete(id: string, namespace?: string): boolean\n }\n /** Request headers that carry controls, checked: spread them into a `fetch` or an SDK's defaults. */\n headers(input: ControlHeaderInput): Record<string, string>\n snapshot(namespace?: string): NamespaceSnapshot\n restore(snapshot: NamespaceSnapshot, namespace?: string): void\n /** Capture the current branch. Mutating HTTP calls do this automatically. */\n checkpoint(namespace?: string, branch?: string): ServiceCheckpoint\n /** Create an isolated branch, optionally from a historical checkpoint. */\n branch(name: string, options?: { namespace?: string; at?: string }): ServiceCheckpoint\n /** Restore a branch, clock, and PRNG to a checkpoint. */\n checkout(checkpoint: string, options?: { namespace?: string; branch?: string }): void\n /** Inspect the retained history for a namespace. */\n timeline(namespace?: string): Timeline<ServiceTimelineState>\n /** Collections in one namespace: declared shape plus what the rows actually hold. */\n state(namespace?: string): StateView\n}\n\ntype _MockSurfaceProof = ServiceRuntime<ServiceInstance> extends MockSurface ? true : never\nconst mockSurfaceProof: _MockSurfaceProof = true\nvoid mockSurfaceProof\n\n/** The namespace used when a request names none. */\nexport const DEFAULT_NAMESPACE = \"default\"\n\nconst MUTATING_METHODS = new Set([\"POST\", \"PUT\", \"PATCH\", \"DELETE\"])\n\nconst effects = new WeakMap<Request, FaultHit[\"effect\"][]>()\n\nconst acceptance = new WeakMap<Request, (notes: ResponseNotes) => void>()\n\n/** Notify only after a durable mutation commits. No-op outside an active runtime request. */\nexport const markMutationAccepted = (request: Request, notes: ResponseNotes = {}): void => {\n acceptance.get(request)?.(notes)\n}\n\n/** Preserve request-bound effects and acceptance when a provider must rebuild a Request. */\nexport const forwardRequestContext = (source: Request, target: Request): Request => {\n const fired = effects.get(source)\n const accepted = acceptance.get(source)\n if (fired) effects.set(target, fired)\n if (accepted) acceptance.set(target, accepted)\n return forwardMountContext(source, target)\n}\n\n/**\n * Merge two sorted snapshot row arrays, retaining byte-identical old objects. Unlike the previous\n * Map/string-key implementation this is allocation-free apart from the result array and O(n).\n */\nconst reuseSorted = <T>(\n fresh: T[],\n previous: T[] | undefined,\n compare: (left: T, right: T) => number,\n equal: (left: T, right: T) => boolean,\n): T[] => {\n if (!previous || previous.length === 0) return fresh.map((row) => Object.freeze(row))\n const result = new Array<T>(fresh.length)\n let unchanged = fresh.length === previous.length\n let oldIndex = 0\n for (let index = 0; index < fresh.length; index++) {\n const row = fresh[index] as T\n while (oldIndex < previous.length && compare(previous[oldIndex] as T, row) < 0) {\n oldIndex++\n }\n const old = previous[oldIndex]\n result[index] =\n old !== undefined && compare(old, row) === 0 && equal(old, row) ? old : Object.freeze(row)\n if (result[index] !== previous[index]) unchanged = false\n }\n return unchanged ? previous : result\n}\n\n/**\n * The fault effects (`{\"effect\": \"created_but_500\"}` rules) that fired for this request, in\n * rule order. Handlers read this to switch on a named vendor misbehaviour.\n */\nexport const faultEffects = (\n request: Request,\n): { name: string; params: Record<string, unknown> }[] =>\n (effects.get(request) ?? []).filter((e): e is NonNullable<typeof e> => e !== undefined)\n\n/** Whether the named effect fired for this request; its params when it did. */\nexport const faultEffect = (request: Request, name: string): Record<string, unknown> | undefined =>\n faultEffects(request).find((e) => e.name === name)?.params\n\n/**\n * Thrown by an in-process `runtime.fetch` when a `drop` fault fires: the same thing a real\n * `fetch` does when the connection dies mid-request. A served mock destroys the socket.\n */\nexport class DroppedConnectionError extends TypeError {\n readonly code = \"MOCKINGBIRD_DROP\"\n /** Why the connection died: a `drop`, a `timeout` that ran out, or a `truncate`d body. */\n readonly reason: \"drop\" | \"timeout\" | \"truncate\"\n constructor(reason: \"drop\" | \"timeout\" | \"truncate\" = \"drop\") {\n super(\n reason === \"timeout\"\n ? \"fetch failed: request timed out by Mockingbird fault\"\n : reason === \"truncate\"\n ? \"fetch failed: response truncated by Mockingbird fault\"\n : \"fetch failed: connection dropped by Mockingbird fault\",\n )\n this.name = \"TypeError\"\n this.reason = reason\n }\n}\n\nconst realSleep = (ms: number, signal?: AbortSignal): Promise<void> =>\n new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason)\n return\n }\n const abort = () => {\n clearTimeout(timer)\n reject(signal?.reason)\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", abort)\n resolve()\n }, ms)\n signal?.addEventListener(\"abort\", abort, { once: true })\n })\n\nconst NULL_BODY_STATUS = new Set([101, 204, 205, 304])\n\n/** Let `bytes` of the body through, then fail the stream the way a dying connection does. */\nconst truncateResponse = (response: Response, bytes: number): Response => {\n if (NULL_BODY_STATUS.has(response.status)) return response\n const reader = response.body?.getReader()\n let sent = 0\n const body = new ReadableStream<Uint8Array>({\n async pull(controller) {\n const chunk = sent < bytes && reader ? await reader.read() : undefined\n if (!chunk || chunk.done) {\n await reader?.cancel().catch(() => {})\n controller.error(new DroppedConnectionError(\"truncate\"))\n return\n }\n const part = chunk.value.subarray(0, bytes - sent)\n sent += part.length\n controller.enqueue(part)\n },\n cancel: (reason) => reader?.cancel(reason),\n })\n const headers = new Headers(response.headers)\n headers.delete(\"content-length\")\n return new Response(body, { status: response.status, statusText: response.statusText, headers })\n}\n\n/** What a snapshot holds for one namespace. Only `records` is always there. */\ntype Kept = {\n records: NamespaceSnapshot\n clock?: { now: number; frozen: boolean; pinned?: boolean }\n /** Where the service's own random stream stands. */\n rngState?: number\n controls: ControlsSnapshot\n webhooks?: unknown\n}\ntype Stored = Kept & { info: SnapshotInfo }\n\ntype Matcher = { operationId: string; method: string; pattern: RegExp; params: number }\n\n/** Resolve a request to its operationId: static segments beat parameters, as in routing. */\nconst operationMatcher = (document: OpenAPIDocument) => {\n const matchers: Matcher[] = listOperations(document)\n .map((operation) => ({\n operationId: operation.operationId,\n method: operation.method.toUpperCase(),\n pattern: operationPath(operation).pattern,\n params: (operation.path.match(/\\{/g) ?? []).length,\n }))\n .sort((a, b) => a.params - b.params)\n return (request: Request, path: string): string | undefined =>\n matchers.find((m) => m.method === request.method && m.pattern.test(path))?.operationId\n}\n\n/**\n * Wrap a service in the shared Mockingbird contract: an unauthenticated `/__admin/health`,\n * the `/__admin/*` control plane, per-request namespaces, a controllable clock,\n * fault injection, and request metrics.\n *\n * Namespaces isolate parallel workers inside one process: each gets its own\n * instance over the same SQLite database, so rows are partitioned by namespace\n * and a worker's reset or restore never touches another worker's data.\n */\nexport const createRuntime = <T extends ServiceInstance>(\n options: RuntimeOptions<T>,\n): ServiceRuntime<T> => {\n const adminPrefix = resolveAdminPrefix(options.adminPrefix)\n const internalPaths = Object.entries(options.document?.paths ?? {})\n .filter(([, item]) => item[\"x-mockingbird-internal\"] === true)\n .map(([path]) => path)\n for (const path of internalPaths) {\n if (!path.startsWith(`${ADMIN_PREFIX}/blobs/`))\n throw new Error(`internal transport ${path} must live under ${ADMIN_PREFIX}/blobs/`)\n }\n assertAdminPrefixAvailable(\n adminPrefix,\n Object.keys(options.document?.paths ?? {}).filter((path) => !internalPaths.includes(path)),\n )\n const internalMatch = (path: string): string | undefined => {\n for (const pattern of internalPaths) {\n const actual = path.split(\"/\")\n const expected = pattern.split(\"/\")\n if (\n actual.length === expected.length &&\n expected.every((part, i) => part.startsWith(\"{\") || part === actual[i])\n )\n return pattern\n }\n return undefined\n }\n assertAdminUi(options.adminUi)\n const boot = normalizeBootControls(options.adminControls, \"adminControls\")\n const seed = normalizeSeed(options.seed ?? boot.shared.seed ?? 0)\n // Named outright, the seed is a boot control like any other: it wins over a boot snapshot's.\n if (options.seed !== undefined) boot.shared.seed = seed\n const sqlite = bootSqlite(options.sqlite)\n if (options.idBase !== undefined)\n setIdBase(sqlite, normalizeIdBase(options.idBase, \"idBase\", options.io?.wallNow))\n const clock = options.clock ?? createClock()\n // The shared boot clock is the base clock, which every namespace follows. What a namespace\n // keeps of it for itself is how far its own clock steps before each request.\n const { now: bootNow, frozen: bootFrozen, ...stepping } = boot.shared.clock ?? {}\n if (bootFrozen === true) clock.freeze()\n if (bootNow !== undefined) clock.set(bootNow)\n if (bootFrozen === false) clock.unfreeze()\n const bootClockGiven = bootNow !== undefined || bootFrozen !== undefined\n if (stepping.autoAdvanceMs !== undefined) boot.shared.clock = stepping\n else delete boot.shared.clock\n /** Where the base clock stood when the runtime was created: what a full reset returns it to. */\n const bootClock = clock.state()\n const rng = createRng(seed)\n const wallNow = options.io?.wallNow ?? Date.now\n const monotonicNow = options.io?.monotonicNow ?? (() => performance.now())\n const sleep = options.io?.sleep ?? realSleep\n const metrics = createMetrics()\n const journal = createJournal(options.journalSize ?? DEFAULT_JOURNAL_SIZE)\n const version = options.version ?? PACKAGE_VERSION\n const instances = new Map<string, T>()\n const publicNamespaces = new Set<string>()\n /** The service's own random stream, by storage key. `default` uses {@link rng}. */\n const rngs = new Map<string, Rng>()\n const namespaceClocks = new Map<string, DerivedClock>()\n const namespaceForStorage = new Map<string, string>()\n /**\n * Every namespace has a clock of its own that follows the base clock. Moving one never\n * moves another; moving the base (`runtime.clock`) moves every namespace that is not frozen.\n */\n const namespaceClock = (name = DEFAULT_NAMESPACE): DerivedClock => {\n let found = namespaceClocks.get(name)\n if (!found) {\n found = deriveClock(clock, () => options.onClockChange?.(name))\n namespaceClocks.set(name, found)\n }\n return found\n }\n const fleetPoints = new WeakMap<object, { namespace: string } & Kept>()\n const timelines = new Map<string, Timeline<ServiceTimelineState>>()\n const branchStorage = new Map<string, string>()\n const captured = new Map<string, NamespaceSnapshot>()\n const credentials = createCredentialRegistry()\n for (const [credential, target] of Object.entries(boot.credentials))\n credentials.set(credential, target)\n const operationIdFor = options.document ? operationMatcher(options.document) : () => undefined\n\n const controls = createNamespaceControls({\n seed,\n clock: namespaceClock,\n boot,\n ...(options.presets ? { presets: options.presets } : {}),\n sleep: (ms) => sleep(ms),\n onReseed: (namespace, next) => {\n rngFor(namespace).reseed(next)\n for (const [mapping, storage] of branchStorage)\n if (mapping.startsWith(`${namespace}\\0`)) rngs.get(storage)?.reseed(next)\n },\n onPreset: (preset, namespace, overrides) => {\n if (preset.webhook)\n options.webhooks?.fault(namespace, {\n ...preset.webhook,\n ...(overrides.count !== undefined ? { count: overrides.count } : {}),\n })\n },\n restoreDocument: (namespace, document, scope) => {\n const { clock: carried, ...point } = fromDocument(namespace, document)\n // A boot clock named outright is the base clock's; the snapshot's does not override it.\n restoreAll(\n namespace,\n bootClockGiven || !carried ? point : { ...point, clock: carried },\n scope,\n )\n },\n })\n const { faults, latency } = controls\n\n /** The random stream behind a storage key, created at its namespace's seed. */\n const rngFor = (storage: string): Rng => {\n if (storage === DEFAULT_NAMESPACE) return rng\n let found = rngs.get(storage)\n if (!found) {\n found = createRng(seed)\n rngs.set(storage, found)\n }\n return found\n }\n const seedOf = (namespace: string): number | string => controls.settings(namespace).seed\n\n const storageNamespace = (name: string) =>\n name === DEFAULT_NAMESPACE ? options.name : `${options.name}:${name}`\n\n const instanceFor = (key: string, publicNamespace = key, isolatedRng?: Rng): T => {\n const existing = instances.get(key)\n if (existing) return existing\n if (!KEY_PATTERN.test(key) || !KEY_PATTERN.test(publicNamespace)) {\n throw new RangeError(\n `namespace must match ${KEY_PATTERN}: ${JSON.stringify(publicNamespace)}`,\n )\n }\n if (isolatedRng) rngs.set(key, isolatedRng)\n const created = options.create({\n namespace: storageNamespace(key),\n publicNamespace,\n adminPrefix,\n sqlite,\n clock: namespaceClock(publicNamespace),\n rng: rngFor(key),\n })\n instances.set(key, created)\n namespaceForStorage.set(key, publicNamespace)\n publicNamespaces.add(publicNamespace)\n // A namespace starts from its boot controls and, when one is given, its boot snapshot.\n if (key === publicNamespace) controls.ensure(key)\n return created\n }\n\n const instance = (name: string = DEFAULT_NAMESPACE): T => instanceFor(name)\n\n /** A namespace's clock as a checkpoint keeps it, and how one is put back. */\n const clockOf = (namespace: string): ServiceTimelineState[\"clock\"] => {\n const own = namespaceClock(namespace)\n return Object.freeze({ ...own.state(), pinned: own.pinned() })\n }\n const placeClock = (\n namespace: string,\n state: { now: number; frozen: boolean; pinned?: boolean },\n ): void =>\n // A document only says frozen or not; frozen there means frozen at that instant.\n namespaceClock(namespace).place({ now: state.now, pinned: state.pinned ?? state.frozen })\n\n const capture = (storage: string): ServiceTimelineState => {\n const fresh = snapshotNamespace(sqlite, storageNamespace(storage))\n const previous = captured.get(storage)\n const snapshot: NamespaceSnapshot = {\n namespace: fresh.namespace,\n records: reuseSorted(\n fresh.records,\n previous?.records,\n (left, right) =>\n left.collection < right.collection\n ? -1\n : left.collection > right.collection\n ? 1\n : left.seq - right.seq,\n (left, right) => left.id === right.id && left.value === right.value,\n ),\n sequences: reuseSorted(\n fresh.sequences,\n previous?.sequences,\n (left, right) =>\n left.name < right.name\n ? -1\n : left.name > right.name\n ? 1\n : left.kind < right.kind\n ? -1\n : left.kind > right.kind\n ? 1\n : 0,\n (left, right) => left.value === right.value,\n ),\n }\n Object.freeze(snapshot.records)\n Object.freeze(snapshot.sequences)\n Object.freeze(snapshot)\n captured.set(storage, snapshot)\n return Object.freeze({\n snapshot,\n clock: clockOf(namespaceForStorage.get(storage) ?? storage),\n rngState: rngFor(storage).state(),\n })\n }\n\n const timeline = (name: string = DEFAULT_NAMESPACE): Timeline<ServiceTimelineState> => {\n let found = timelines.get(name)\n if (found) return found\n instance(name)\n found = new Timeline<ServiceTimelineState>({\n now: namespaceClock(name).now,\n ...(options.maxCheckpoints !== undefined ? { maxCheckpoints: options.maxCheckpoints } : {}),\n })\n found.commit(capture(name))\n timelines.set(name, found)\n return found\n }\n\n const restoreStorage = (storage: string, snapshot: NamespaceSnapshot): void => {\n const current = instances.get(storage)\n if (current) options.beforeRestore?.(current)\n restoreNamespace(sqlite, storageNamespace(storage), snapshot)\n }\n\n const physicalBranch = (namespace: string, branch: string): string => {\n if (branch === \"main\") return namespace\n const mapKey = `${namespace}\\0${branch}`\n const existing = branchStorage.get(mapKey)\n if (existing) return existing\n // The hash keeps the internal instance key inside the 64-character namespace contract.\n const key = `branch_${seedFrom(`${options.name}\\0${namespace}\\0${branch}`).toString(36)}`\n branchStorage.set(mapKey, key)\n return key\n }\n\n const ensureBranch = (namespace: string, branch: string, at?: string): string => {\n if (!KEY_PATTERN.test(branch)) throw new RangeError(`branch must match ${KEY_PATTERN}`)\n const history = timeline(namespace)\n if (branch === \"main\") {\n if (at !== undefined) {\n const point = history.checkout(\"main\", at)\n restoreStorage(namespace, point.value.snapshot)\n captured.set(namespace, point.value.snapshot)\n rngFor(namespace).setState(point.value.rngState)\n placeClock(namespace, point.value.clock)\n }\n return namespace\n }\n const storage = physicalBranch(namespace, branch)\n if (!history.hasBranch(branch)) {\n // Capture unobserved background work before branching from the current main head.\n if (at === undefined) history.commit(capture(namespace))\n const point = history.fork(branch, at === undefined ? {} : { from: at })\n const branchRng = createRng(seedOf(namespace))\n if (point) branchRng.setState(point.value.rngState)\n instanceFor(storage, namespace, branchRng)\n if (point) restoreStorage(storage, point.value.snapshot)\n if (point) captured.set(storage, point.value.snapshot)\n } else if (at !== undefined && history.head(branch)?.id !== at) {\n const point = history.checkout(branch, at)\n if (!instances.has(storage)) {\n const branchRng = createRng(seedOf(namespace))\n branchRng.setState(point.value.rngState)\n instanceFor(storage, namespace, branchRng)\n }\n rngFor(storage).setState(point.value.rngState)\n restoreStorage(storage, point.value.snapshot)\n captured.set(storage, point.value.snapshot)\n } else {\n if (!instances.has(storage)) {\n const point = history.head(branch)\n const branchRng = createRng(seedOf(namespace))\n if (point) branchRng.setState(point.value.rngState)\n instanceFor(storage, namespace, branchRng)\n }\n }\n return storage\n }\n\n const checkpoint = (namespace = DEFAULT_NAMESPACE, branch = \"main\"): ServiceCheckpoint => {\n const storage = ensureBranch(namespace, branch)\n return timeline(namespace).commit(capture(storage), { branch })\n }\n\n const branch = (\n name: string,\n branchOptions: { namespace?: string; at?: string } = {},\n ): ServiceCheckpoint => {\n const namespace = branchOptions.namespace ?? DEFAULT_NAMESPACE\n ensureBranch(namespace, name, branchOptions.at)\n const head = timeline(namespace).head(name)\n if (!head) throw new RangeError(`branch ${name} has no checkpoint`)\n return head\n }\n\n const checkout = (\n checkpointId: string,\n checkoutOptions: { namespace?: string; branch?: string } = {},\n ): void => {\n const namespace = checkoutOptions.namespace ?? DEFAULT_NAMESPACE\n const branchName = checkoutOptions.branch ?? \"main\"\n const history = timeline(namespace)\n const point = history.checkout(branchName, checkpointId)\n const storage = ensureBranch(namespace, branchName)\n restoreStorage(storage, point.value.snapshot)\n captured.set(storage, point.value.snapshot)\n placeClock(namespace, point.value.clock)\n rngFor(storage).setState(point.value.rngState)\n }\n\n const reset = async (name: string = DEFAULT_NAMESPACE): Promise<void> => {\n if (name === \"*\") {\n options.webhooks?.clear()\n for (const each of instances.values()) await each.reset()\n timelines.clear()\n for (const storage of branchStorage.values()) {\n instances.delete(storage)\n rngs.delete(storage)\n namespaceForStorage.delete(storage)\n }\n branchStorage.clear()\n captured.clear()\n snapshotStore.clear()\n journal.clear()\n metrics.reset()\n // The base clock goes back to where the runtime found it; a live one keeps running.\n if (bootClock.frozen) restoreClock(clock, bootClock)\n else {\n clock.reset()\n clock.advance(bootClock.offsetMs)\n }\n controls.rebootAll()\n for (const each of new Set([DEFAULT_NAMESPACE, ...publicNamespaces])) controls.ensure(each)\n return\n }\n options.webhooks?.clear(name)\n const target = instances.get(name)\n if (target) await target.reset()\n else clearNamespace(sqlite, storageNamespace(name))\n for (const [mapping, storage] of branchStorage) {\n if (!mapping.startsWith(`${name}\\0`)) continue\n const branchInstance = instances.get(storage)\n if (branchInstance) await branchInstance.reset()\n else clearNamespace(sqlite, storageNamespace(storage))\n branchStorage.delete(mapping)\n instances.delete(storage)\n namespaceForStorage.delete(storage)\n rngs.delete(storage)\n captured.delete(storage)\n }\n timelines.delete(name)\n captured.delete(name)\n snapshotStore.clear(name)\n journal.clear(name)\n metrics.reset(name)\n // Seed, clock, faults, latency and every stream, then the boot snapshot and controls again.\n controls.reboot(name)\n }\n\n const dropNamespace = async (name: string): Promise<void> => {\n await reset(name)\n if (name === DEFAULT_NAMESPACE) return\n instances.delete(name)\n namespaceForStorage.delete(name)\n publicNamespaces.delete(name)\n rngs.delete(name)\n namespaceClocks.delete(name)\n controls.forget(name)\n }\n\n /** Everything a namespace is: records, clock, random streams, faults, latency, webhooks. */\n const captureAll = (namespace: string): Kept => {\n instance(namespace)\n const state = capture(namespace)\n return {\n records: state.snapshot,\n clock: state.clock,\n rngState: state.rngState,\n controls: controls.snapshot(namespace),\n webhooks: options.webhooks?.snapshot(namespace),\n }\n }\n\n /** Put back what `point` holds. What it does not hold stays as it is. */\n const restoreAll = (namespace: string, point: Kept, scope: BootScope = \"all\"): void => {\n instance(namespace)\n if (scope === \"all\") {\n restoreStorage(namespace, point.records)\n captured.set(namespace, point.records)\n }\n if (point.clock) placeClock(namespace, point.clock)\n // Controls before the service's stream: a restored seed restarts it, then it is placed.\n controls.restore(namespace, point.controls)\n if (point.rngState !== undefined) rngFor(namespace).setState(point.rngState)\n if (scope !== \"all\") return\n if (point.webhooks !== undefined) options.webhooks?.restore(namespace, point.webhooks)\n // History continues from the restored state instead of being rewritten.\n timelines.get(namespace)?.commit(capture(namespace), { branch: \"main\" })\n }\n\n const toDocument = (point: Kept): SnapshotDocument => {\n const { settings, streams, faults: rules, latency: waits } = point.controls\n return {\n format: SNAPSHOT_FORMAT,\n service: options.name,\n records: point.records.records.map((row) => {\n // A Collection row is stored as `{seq, value}`; anything else travels as its raw text.\n let parsed: unknown\n try {\n parsed = JSON.parse(row.value)\n } catch {\n parsed = undefined\n }\n const base = { collection: row.collection, id: row.id, seq: row.seq }\n return isRecord(parsed) &&\n \"value\" in parsed &&\n JSON.stringify({ seq: row.seq, value: parsed.value }) === row.value\n ? { ...base, value: parsed.value }\n : { ...base, raw: row.value }\n }),\n sequences: point.records.sequences.map((row) => ({ ...row })),\n ...(point.clock\n ? {\n clock: {\n now: point.clock.now,\n frozen: point.clock.frozen,\n ...(settings?.autoAdvanceMs !== undefined\n ? { autoAdvanceMs: settings.autoAdvanceMs }\n : {}),\n },\n }\n : {}),\n ...(settings?.seed !== undefined ? { seed: settings.seed } : {}),\n ...(point.rngState !== undefined ? { rng: { state: point.rngState, ...streams } } : {}),\n ...(rules ? { faults: rules } : {}),\n ...(waits ? { latency: waits } : {}),\n ...(settings?.virtualTime !== undefined ? { virtualTime: settings.virtualTime } : {}),\n ...(point.webhooks !== undefined\n ? { webhooks: options.webhooks?.exportSnapshot(point.webhooks) }\n : {}),\n }\n }\n\n const position = (value: unknown, label: string): number => {\n if (\n typeof value !== \"number\" ||\n !Number.isSafeInteger(value) ||\n value < 0 ||\n value > 0xffffffff\n )\n throw new ControlError(`${label}: expected an unsigned 32-bit integer`)\n return value\n }\n\n /** A document as restorable state. Checks all of it; touches nothing. */\n const fromDocument = (namespace: string, document: SnapshotDocument): Kept => {\n if (document.service !== undefined && document.service !== options.name)\n throw new ControlError(`snapshot was taken from ${document.service}, not ${options.name}`)\n const highest = new Map<string, number>()\n const seen = new Set<string>()\n const records = document.records.map((row) => {\n const key = `${row.collection}\\0${row.id}`\n if (seen.has(key))\n throw new ControlError(`snapshot.records: duplicate ${row.collection}/${row.id}`)\n seen.add(key)\n const seq = row.seq ?? (highest.get(row.collection) ?? 0) + 1\n highest.set(row.collection, Math.max(highest.get(row.collection) ?? 0, seq))\n return Object.freeze({\n collection: row.collection,\n id: row.id,\n seq,\n value: typeof row.raw === \"string\" ? row.raw : JSON.stringify({ seq, value: row.value }),\n })\n })\n records.sort((left, right) =>\n left.collection < right.collection\n ? -1\n : left.collection > right.collection\n ? 1\n : left.seq - right.seq,\n )\n const sequences = new Map<string, { name: string; kind: string; value: number }>()\n for (const row of document.sequences ?? [])\n sequences.set(`${row.name}\\0${row.kind}`, { ...row })\n // A collection's counter never trails its rows, so the next insert cannot reuse a seq.\n for (const [collection, seq] of highest) {\n const key = `${collection}\\0collection`\n if ((sequences.get(key)?.value ?? 0) < seq)\n sequences.set(key, { name: collection, kind: \"collection\", value: seq })\n }\n const stored: NamespaceSnapshot = Object.freeze({\n namespace: storageNamespace(namespace),\n records: Object.freeze(records) as NamespaceSnapshot[\"records\"],\n sequences: Object.freeze(\n [...sequences.values()]\n .sort((left, right) =>\n left.name < right.name\n ? -1\n : left.name > right.name\n ? 1\n : left.kind < right.kind\n ? -1\n : left.kind > right.kind\n ? 1\n : 0,\n )\n .map((row) => Object.freeze(row)),\n ) as NamespaceSnapshot[\"sequences\"],\n })\n\n const settings: Partial<ControlSettings> = {}\n if (document.seed !== undefined) settings.seed = normalizeSeed(document.seed, \"snapshot.seed\")\n if (document.virtualTime !== undefined) {\n if (typeof document.virtualTime !== \"boolean\")\n throw new ControlError(\"snapshot.virtualTime: expected a boolean\")\n settings.virtualTime = document.virtualTime\n }\n const stepping =\n document.clock?.autoAdvanceMs !== undefined\n ? normalizeClock({ autoAdvance: document.clock.autoAdvanceMs }, \"snapshot.clock\")\n .autoAdvanceMs\n : undefined\n if (stepping !== undefined) settings.autoAdvanceMs = stepping\n const held: ControlsSnapshot = {}\n if (Object.keys(settings).length > 0) held.settings = settings\n if (document.rng?.faults !== undefined || document.rng?.latency !== undefined)\n held.streams = {\n ...(document.rng.faults !== undefined\n ? { faults: position(document.rng.faults, \"snapshot.rng.faults\") }\n : {}),\n ...(document.rng.latency !== undefined\n ? { latency: position(document.rng.latency, \"snapshot.rng.latency\") }\n : {}),\n }\n if (document.faults !== undefined) {\n const given = document.faults\n if (!isRecord(given) || !Array.isArray(given.rules))\n throw new ControlError(\"snapshot.faults: expected {rules: [...]}\")\n held.faults = {\n rules: given.rules.map((each: unknown) => {\n const rule = normalizeFault(each)\n const kept = each as Record<string, unknown>\n return {\n ...rule,\n remaining: typeof kept.remaining === \"number\" ? kept.remaining : (rule.count ?? null),\n hits: typeof kept.hits === \"number\" ? kept.hits : 0,\n seen: typeof kept.seen === \"number\" ? kept.seen : 0,\n ...(typeof kept.position === \"number\" ? { position: kept.position } : {}),\n }\n }),\n nextId: typeof given.nextId === \"number\" ? given.nextId : 0,\n }\n }\n if (document.latency !== undefined)\n held.latency = normalizeLatency(document.latency, \"snapshot.latency\")\n return {\n records: stored,\n ...(document.clock\n ? { clock: { now: document.clock.now, frozen: document.clock.frozen } }\n : {}),\n ...(document.rng?.state !== undefined\n ? { rngState: position(document.rng.state, \"snapshot.rng.state\") }\n : {}),\n controls: held,\n ...(document.webhooks !== undefined\n ? { webhooks: options.webhooks?.importSnapshot(namespace, document.webhooks) }\n : {}),\n }\n }\n\n const kept = new Map<string, Map<string, Stored>>()\n const snapshotCounters = new Map<string, number>()\n const keep = (namespace: string, given: string | undefined, point: Kept): SnapshotInfo => {\n let store = kept.get(namespace)\n if (!store) {\n store = new Map()\n kept.set(namespace, store)\n }\n let id = given\n if (id === undefined) {\n let next = snapshotCounters.get(namespace) ?? 0\n do id = `snap_${++next}`\n while (store.has(id))\n snapshotCounters.set(namespace, next)\n }\n const info: SnapshotInfo = {\n id,\n namespace,\n records: point.records.records.length,\n at: point.clock?.now ?? namespaceClock(namespace).now(),\n portable: true,\n }\n store.set(id, { ...point, info })\n return info\n }\n /** Named snapshots, kept per namespace so two workers never see each other's ids. */\n const snapshotStore: SnapshotStore = {\n create: (namespace, id) => keep(namespace, id, captureAll(namespace)),\n list: (namespace) => [...(kept.get(namespace)?.values() ?? [])].map((each) => each.info),\n get: (namespace, id) => kept.get(namespace)?.get(id)?.info,\n export(namespace, id) {\n const found = kept.get(namespace)?.get(id)\n return found ? toDocument(found) : undefined\n },\n import: (namespace, id, document) => keep(namespace, id, fromDocument(namespace, document)),\n restore(namespace, id) {\n const found = kept.get(namespace)?.get(id)\n if (!found) return false\n restoreAll(namespace, found)\n return true\n },\n remove: (namespace, id) => kept.get(namespace)?.delete(id) ?? false,\n clear(namespace) {\n if (namespace === undefined) {\n kept.clear()\n snapshotCounters.clear()\n return\n }\n kept.delete(namespace)\n snapshotCounters.delete(namespace)\n },\n }\n\n const applyControls = (namespace: string, plan: ControlPlan): void => {\n const { snapshot: document, ...rest } = plan\n // Everything is checked before anything is touched: a rejected document changes nothing.\n controls.check(rest)\n const point = document ? fromDocument(namespace, document) : undefined\n // The snapshot first, so a control given beside it wins over the one it carries.\n if (point) restoreAll(namespace, point)\n controls.apply(namespace, rest)\n }\n\n const describeControls = (namespace: string) => ({\n ...controls.describe(namespace),\n snapshots: snapshotStore.list(namespace),\n })\n\n const snapshot = (name: string = DEFAULT_NAMESPACE): NamespaceSnapshot => {\n return checkpoint(name, \"main\").value.snapshot\n }\n\n const restore = (from: NamespaceSnapshot, name: string = DEFAULT_NAMESPACE): void => {\n instance(name)\n restoreStorage(name, from)\n captured.set(name, from)\n // Import legacy snapshots into the canonical history instead of creating a second rollback\n // mechanism. The compatibility method stays synchronous and keeps its original return type.\n const history = timelines.get(name)\n if (history) history.commit(capture(name), { branch: \"main\" })\n else timeline(name)\n }\n\n const declarationsFor = (namespace: string): readonly StateDeclaration[] => {\n const declared = options.state\n if (!declared) return []\n return typeof declared === \"function\" ? declared(instance(namespace), namespace) : declared\n }\n\n const stateScope = (namespace: string) => ({\n sqlite,\n namespace,\n storageNamespace: storageNamespace(namespace),\n root: instance(namespace),\n declarations: declarationsFor(namespace),\n })\n\n const runtime: ServiceRuntime<T> = {\n name: options.name,\n mount: (prefix) =>\n mount(runtime, prefix, (request) => {\n const namespace = runtime.namespaceOf(request)\n return namespace === DEFAULT_NAMESPACE\n ? \"\"\n : `${adminPrefix}/ns/${encodeURIComponent(namespace)}`\n }),\n sqlite,\n clock,\n setIdBase(base) {\n const resolved = normalizeIdBase(base, \"idBase\", options.io?.wallNow)\n setIdBase(sqlite, resolved)\n return resolved\n },\n faults,\n latency,\n metrics,\n journal,\n rng,\n credentials,\n webhooks: options.webhooks,\n namespaceClock,\n namespaceOf(request) {\n const url = new URL(request.url)\n const prefixed = matchNamespacePath(url.pathname, adminPrefix)\n const selected =\n request.headers.get(NAMESPACE_HEADER) ??\n (prefixed ? decodeURIComponent(prefixed[1] as string) : undefined)\n const path = prefixed ? (prefixed[2] ?? \"/\") : url.pathname\n if (isAdminPath(path, adminPrefix))\n return url.searchParams.get(\"namespace\") ?? selected ?? DEFAULT_NAMESPACE\n if (selected !== undefined) return selected\n const credential = options.credential?.(request)\n return (\n (credential !== undefined ? credentials.get(credential) : undefined) ?? DEFAULT_NAMESPACE\n )\n },\n fleetSnapshot(namespace) {\n const handle = {}\n fleetPoints.set(handle, { namespace, ...captureAll(namespace) })\n return handle\n },\n fleetRestore(handle, namespace) {\n const point =\n typeof handle === \"object\" && handle !== null ? fleetPoints.get(handle) : undefined\n if (!point || point.namespace !== namespace) throw new Error(\"invalid fleet checkpoint\")\n restoreAll(namespace, point)\n timelines.delete(namespace)\n },\n fleetExport(handle) {\n const point =\n typeof handle === \"object\" && handle !== null ? fleetPoints.get(handle) : undefined\n if (!point) throw new Error(\"invalid fleet checkpoint\")\n return toDocument(point)\n },\n fleetImport(namespace, document) {\n const handle = {}\n fleetPoints.set(handle, {\n namespace,\n ...fromDocument(namespace, assertSnapshotDocument(document)),\n })\n return handle\n },\n applyPreset: (name, namespace = DEFAULT_NAMESPACE, overrides = {}) =>\n controls.addFault(namespace, { ...overrides, preset: name }),\n instance,\n namespaces: () => [...publicNamespaces].sort(),\n reset,\n dropNamespace,\n controls: (namespace = DEFAULT_NAMESPACE) => describeControls(namespace),\n configure(document, namespace = DEFAULT_NAMESPACE) {\n applyControls(namespace, normalizeControls(document))\n return describeControls(namespace)\n },\n snapshots: {\n create: (given = {}) =>\n snapshotStore.create(given.namespace ?? DEFAULT_NAMESPACE, given.name),\n list: (namespace = DEFAULT_NAMESPACE) => snapshotStore.list(namespace),\n export(id, namespace = DEFAULT_NAMESPACE) {\n const document = snapshotStore.export(namespace, id)\n if (!document) throw new RangeError(`no snapshot ${id} in namespace ${namespace}`)\n return document\n },\n import: (document, given = {}) =>\n snapshotStore.import(given.namespace ?? DEFAULT_NAMESPACE, given.name, document),\n restore(id, namespace = DEFAULT_NAMESPACE) {\n if (!snapshotStore.restore(namespace, id))\n throw new RangeError(`no snapshot ${id} in namespace ${namespace}`)\n },\n delete: (id, namespace = DEFAULT_NAMESPACE) => snapshotStore.remove(namespace, id),\n },\n headers: controlHeaders,\n snapshot,\n restore,\n checkpoint,\n branch,\n checkout,\n timeline,\n state: (namespace = DEFAULT_NAMESPACE) => inspectState(stateScope(namespace)),\n fetch: async (incoming) => {\n let request = incoming\n // `/__admin/ns/<name>/\u2026` selects a namespace (and is stripped) for SDKs that cannot add headers.\n const prefixed = matchNamespacePath(new URL(request.url).pathname, adminPrefix)\n if (prefixed) {\n const url = new URL(request.url)\n url.pathname = prefixed[2] ?? \"/\"\n const headers = new Headers(request.headers)\n if (!headers.has(NAMESPACE_HEADER)) {\n headers.set(NAMESPACE_HEADER, decodeURIComponent(prefixed[1] as string))\n }\n const hasBody = request.method !== \"GET\" && request.method !== \"HEAD\"\n request = forwardRequestContext(\n request,\n new Request(url, {\n method: request.method,\n headers,\n ...(hasBody ? { body: await request.arrayBuffer() } : {}),\n signal: request.signal,\n }),\n )\n }\n const internalUrl = new URL(request.url)\n const internalPath = isAdminPath(internalUrl.pathname, adminPrefix)\n ? `${ADMIN_PREFIX}${internalUrl.pathname.slice(adminPrefix.length)}`\n : \"\"\n const internal = internalMatch(internalPath)\n const obsoleteInternalPath =\n adminPrefix !== ADMIN_PREFIX && internalMatch(internalUrl.pathname) && !internal\n if (internal) {\n internalUrl.pathname = internalPath\n request = forwardRequestContext(request, new Request(internalUrl, request))\n }\n let namespace = internal\n ? (internalUrl.searchParams.get(\"namespace\") ?? control.namespaceOf(request))\n : control.namespaceOf(request)\n if (!request.headers.has(NAMESPACE_HEADER) && options.credential) {\n const credential = options.credential(request)\n const mapped = credential !== undefined ? credentials.get(credential) : undefined\n if (mapped !== undefined) namespace = mapped\n }\n const selectedBranch = request.headers.get(BRANCH_HEADER) ?? \"main\"\n const at = request.headers.get(AT_HEADER) ?? undefined\n const stamp = (response: Response): Response => {\n // An invalid namespace is not echoed back.\n const value = KEY_PATTERN.test(namespace)\n ? `${options.name}@${version}; ns=${namespace}`\n : `${options.name}@${version}`\n try {\n response.headers.set(MOCKINGBIRD_HEADER, value)\n return response\n } catch {\n // Immutable headers (a response passed through from `fetch`): copy it.\n const copy = new Response(response.body, response)\n copy.headers.set(MOCKINGBIRD_HEADER, value)\n return copy\n }\n }\n if (obsoleteInternalPath)\n return stamp(adminFail(404, \"internal transport is only available under adminPrefix\"))\n const handled = internal ? undefined : await control.handle(request)\n if (handled) return stamp(handled)\n const started = monotonicNow()\n const url = new URL(request.url)\n const operationId = operationIdFor(request, url.pathname)\n let accepted: ServiceCheckpoint | undefined\n let acceptedNotes: ResponseNotes | undefined\n // Injected wait this request spent: latency, fault delays, a timeout.\n let waitedMs = 0\n // With virtual time the wait is the whole duration, so a journal replays byte for byte.\n let virtualTime = false\n let requestClock = clock\n // What a rejection records about the body. The runtime never reads the request stream \u2014\n // consuming it would break a streaming request (e.g. a bidirectional model stream) \u2014 so the\n // byte count comes from `content-length` when the client sent it, and is null otherwise.\n const contentLength = request.headers.get(\"content-length\")\n const received: RejectedRequest = {\n contentType: request.headers.get(\"content-type\"),\n bodyBytes:\n contentLength !== null && /^\\d+$/.test(contentLength) ? Number(contentLength) : null,\n transferEncoding: request.headers.get(\"transfer-encoding\"),\n }\n const log = (status: number, faultId?: string, response?: Response) => {\n const noted = { ...acceptedNotes, ...(response ? responseNotes(response) : {}) }\n const rejected = status >= 400 && faultId === undefined\n const entry: RequestLog = {\n service: options.name,\n namespace,\n operationId,\n method: request.method,\n path: url.pathname,\n status,\n durationMs: virtualTime ? waitedMs : Math.round((monotonicNow() - started) * 100) / 100,\n unmatched: options.document !== undefined && operationId === undefined,\n ...(faultId !== undefined ? { faultId } : {}),\n ...(waitedMs > 0 ? { delayMs: waitedMs } : {}),\n ...(noted?.ids && Object.keys(noted.ids).length > 0 ? { ids: noted.ids } : {}),\n ...(noted?.adopted ? { adopted: true } : {}),\n ...(accepted ? { accepted: true, checkpoint: accepted.id } : {}),\n ...(rejected ? { request: { ...received } } : {}),\n ...(rejected && noted?.issues && noted.issues.length > 0\n ? { issues: noted.issues.map((issue) => ({ ...issue })) }\n : {}),\n }\n metrics.record(entry)\n journal.record({ ...entry, at: new Date(requestClock.now()).toISOString() })\n options.onLog?.(entry)\n }\n if (!KEY_PATTERN.test(namespace)) {\n log(400)\n return stamp(\n new Response(\n JSON.stringify({\n error: {\n type: \"mockingbird_admin\",\n message: `${NAMESPACE_HEADER} must match ${KEY_PATTERN}`,\n },\n }),\n { status: 400, headers: { \"content-type\": \"application/json; charset=utf-8\" } },\n ),\n )\n }\n if (!KEY_PATTERN.test(selectedBranch)) {\n log(400)\n return stamp(adminFail(400, `${BRANCH_HEADER} must match ${KEY_PATTERN}`))\n }\n requestClock = namespaceClock(namespace)\n const refuse = (status: number, message: string): Response => {\n log(status)\n return stamp(adminFail(status, message))\n }\n // Controls carried by this request. Whatever could refuse the request is checked before\n // anything is applied, so a request that is refused has changed nothing.\n let requested: RequestControls | undefined\n let scripted: FaultRule[] = []\n try {\n requested = parseControlHeaders(request.headers)\n if (requested)\n scripted = controls.scriptFaults(namespace, {\n ...(requested.fault ? { fault: requested.fault } : {}),\n ...(requested.timeout !== undefined ? { timeoutMs: requested.timeout } : {}),\n })\n const lost = requested?.restore !== undefined ? CONTROL_HEADERS.restore : at && AT_HEADER\n if (requested?.reset && lost)\n throw new ControlError(\n `${CONTROL_HEADERS.reset}: a reset discards snapshots and history, so ${lost} cannot follow it`,\n )\n } catch (error) {\n if (error instanceof ControlError) return refuse(400, error.message)\n throw error\n }\n // A write that names a checkpoint on `main` first moves `main` back to it. That changes\n // the namespace, so it is guarded like the headers that say so outright.\n const rewinds =\n at !== undefined && selectedBranch === \"main\" && MUTATING_METHODS.has(request.method)\n if (\n (requested || rewinds) &&\n options.adminKey !== undefined &&\n !hasAdminKey(request.headers, options.adminKey)\n )\n return refuse(401, `control headers need ${ADMIN_KEY_HEADER}`)\n controls.ensure(namespace)\n if (requested?.restore !== undefined && !snapshotStore.get(namespace, requested.restore))\n return refuse(404, `no snapshot ${requested.restore} in namespace ${namespace}`)\n if (at !== undefined) {\n try {\n timeline(namespace).get(at)\n } catch (error) {\n return refuse(409, error instanceof Error ? error.message : String(error))\n }\n }\n if (requested) {\n // The order the guide lists them in: reset, restore, seed, time, advance, virtual time.\n if (requested.reset) await reset(namespace)\n if (requested.restore !== undefined) snapshotStore.restore(namespace, requested.restore)\n if (requested.seed !== undefined) controls.reseed(namespace, requested.seed)\n if (requested.time !== undefined)\n controls.changeClock(namespace, { frozen: true, now: requested.time })\n if (requested.advance !== undefined)\n controls.changeClock(namespace, { advanceMs: requested.advance })\n if (requested.virtualTime !== undefined)\n controls.apply(namespace, { virtualTime: requested.virtualTime })\n }\n let storage: string\n try {\n if (\n at !== undefined &&\n selectedBranch === \"main\" &&\n !MUTATING_METHODS.has(request.method)\n ) {\n const point = timeline(namespace).get(at)\n storage = physicalBranch(namespace, `at_${at}`)\n let viewRng = rngs.get(storage)\n if (!viewRng) {\n viewRng = createRng(seedOf(namespace))\n instanceFor(storage, namespace, viewRng)\n }\n viewRng.setState(point.value.rngState)\n restoreStorage(storage, point.value.snapshot)\n captured.set(storage, point.value.snapshot)\n } else {\n storage = ensureBranch(namespace, selectedBranch, at)\n }\n } catch (error) {\n log(409)\n return stamp(adminFail(409, error instanceof Error ? error.message : String(error)))\n }\n const settings = controls.settings(namespace)\n virtualTime = settings.virtualTime\n if (settings.autoAdvanceMs > 0) requestClock.advance(settings.autoAdvanceMs)\n const wait = async (ms: number): Promise<void> => {\n if (!(ms > 0)) return\n waitedMs += ms\n // Virtual: the mock clock pays for the wait and the request carries on at once.\n if (virtualTime) requestClock.advance(ms)\n else await sleepUnlessAborted(ms, request.signal)\n }\n const candidate = {\n operationId,\n method: request.method,\n path: url.pathname,\n namespace,\n headers: request.headers,\n query: url.searchParams,\n // Read from a copy, so the service still gets the body. Not JSON: nothing to match.\n readJson: async (): Promise<unknown> => {\n try {\n return JSON.parse(await request.clone().text())\n } catch {\n return undefined\n }\n },\n wait,\n }\n let hits: FaultHit[]\n try {\n await wait(latency.take(namespace, operationId) + (requested?.delay ?? 0))\n hits = scripted.length > 0 ? await faults.fire(scripted, candidate) : []\n if (!hits.some((hit) => hit.drop || hit.response))\n hits.push(...(await faults.take({ ...candidate, now: requestClock.now() })))\n } catch (error) {\n // The client gave up while the request was being held.\n log(0)\n throw error\n }\n const final = hits.find((hit) => hit.drop || hit.response)\n /** A response is done: cut it short if asked to, name the fault, take the snapshot. */\n const finish = (response: Response): Response => {\n let out = response\n const truncate = hits.find((hit) => hit.truncate !== undefined)?.truncate\n if (truncate !== undefined) out = truncateResponse(out, truncate)\n // The rule the journal names: the one that answered, or the first that shaped it.\n const shaped = final ?? hits[0]\n if (shaped) {\n out = mutableResponse(out)\n out.headers.set(FAULT_HEADER, shaped.id)\n }\n if (requested?.snapshot !== undefined) {\n out = mutableResponse(out)\n out.headers.set(SNAPSHOT_HEADER, snapshotStore.create(namespace, requested.snapshot).id)\n }\n return stamp(out)\n }\n if (final?.drop) {\n log(0, final.id)\n throw new DroppedConnectionError(final.timeout ? \"timeout\" : \"drop\")\n }\n if (final?.response) {\n log(final.response.status, final.id)\n return finish(final.response)\n }\n const fired = hits.filter((hit) => hit.effect !== undefined)\n if (fired.length > 0)\n effects.set(\n request,\n fired.map((hit) => hit.effect),\n )\n let active = true\n acceptance.set(request, (notes) => {\n if (!active || accepted || !MUTATING_METHODS.has(request.method)) return\n accepted = timeline(namespace).commit(capture(storage), { branch: selectedBranch })\n acceptedNotes = notes\n })\n let response: Response\n try {\n response = await instanceFor(storage, namespace).fetch(request)\n } catch (error) {\n log(error instanceof DroppedConnectionError ? 0 : 500, hits[0]?.id)\n throw error\n } finally {\n active = false\n acceptance.delete(request)\n }\n const wireStatus = responseNotes(response)?.wireStatus ?? response.status\n if (MUTATING_METHODS.has(request.method) && wireStatus >= 200 && wireStatus < 400) {\n const current = capture(storage)\n const unchanged =\n accepted &&\n timeline(namespace).head(selectedBranch)?.id === accepted.id &&\n current.snapshot.records === accepted.value.snapshot.records &&\n current.snapshot.sequences === accepted.value.snapshot.sequences &&\n current.rngState === accepted.value.rngState\n const point =\n unchanged && accepted\n ? accepted\n : timeline(namespace).commit(current, { branch: selectedBranch })\n response = mutableResponse(response)\n response.headers.set(CHECKPOINT_HEADER, point.id)\n }\n if (selectedBranch !== \"main\") {\n response = mutableResponse(response)\n response.headers.set(BRANCH_HEADER, selectedBranch)\n }\n if (at !== undefined) {\n response = mutableResponse(response)\n response.headers.set(AT_HEADER, at)\n }\n log(wireStatus, hits[0]?.id, response)\n return finish(response)\n },\n }\n\n /** Wait on the wall clock, giving up the moment the caller does. */\n const sleepUnlessAborted = async (ms: number, signal: AbortSignal | undefined): Promise<void> => {\n if (!signal) return sleep(ms)\n if (signal.aborted) throw signal.reason\n let stop = () => {}\n const aborted = new Promise<never>((_, reject) => {\n const abort = () => reject(signal.reason)\n signal.addEventListener(\"abort\", abort, { once: true })\n stop = () => signal.removeEventListener(\"abort\", abort)\n })\n try {\n await Promise.race([sleep(ms, signal), aborted])\n } finally {\n stop()\n }\n }\n\n const control = createControlPlane({\n name: options.name,\n version,\n startedAt: wallNow(),\n wallNow,\n clock,\n namespaceClock,\n metrics,\n journal,\n defaultNamespace: DEFAULT_NAMESPACE,\n namespaces: runtime.namespaces,\n reset,\n dropNamespace,\n controls,\n snapshots: snapshotStore,\n applyControls,\n timeTravel: {\n checkpoint: (name, branchName) => {\n const point = checkpoint(name, branchName)\n return {\n id: point.id,\n branch: point.branch,\n parent: point.parent,\n at: point.at,\n records: point.value.snapshot.records.length,\n }\n },\n branch: (branchName, branchOptions) => {\n const point = branch(branchName, branchOptions)\n return { id: point.id, branch: point.branch, parent: point.parent, at: point.at }\n },\n checkout: (checkpointId, checkoutOptions) => checkout(checkpointId, checkoutOptions),\n retain: (name, checkpointId) => {\n timeline(name).retain(checkpointId)\n },\n release: (name, checkpointId) => timeline(name).release(checkpointId),\n inspect: (name) => {\n const history = timeline(name)\n return {\n branches: history.branches(),\n checkpoints: history.checkpoints().map(({ id, branch: branchName, parent, at }) => ({\n id,\n branch: branchName,\n parent,\n at,\n })),\n }\n },\n },\n describe: options.describe ?? (() => ({})),\n routes: {\n ...credentialRoutes(credentials),\n ...(options.webhooks ? webhookAdminRoutes(options.webhooks) : {}),\n ...(options.admin?.(runtime) ?? {}),\n ...stateAdminRoutes({\n open: stateScope,\n afterWrite: (namespace) => {\n checkpoint(namespace, \"main\")\n },\n }),\n ...adminUiRoutes(options.name, options.adminUi, adminPrefix),\n },\n adminPrefix,\n adminKey: options.adminKey,\n })\n\n // The default namespace boots now, so its rules precede anything a caller adds later.\n controls.ensure(DEFAULT_NAMESPACE)\n return defineMock(runtime)\n}\n\nconst mutableResponse = (response: Response): Response => {\n try {\n response.headers.set(\"x-mockingbird-mutable-probe\", \"1\")\n response.headers.delete(\"x-mockingbird-mutable-probe\")\n return response\n } catch {\n return new Response(response.body, response)\n }\n}\n\nconst adminJson = (status: number, body: unknown): Response =>\n new Response(JSON.stringify(body), {\n status,\n headers: { \"content-type\": \"application/json; charset=utf-8\" },\n })\n\nconst adminFail = (status: number, message: string): Response =>\n adminJson(status, { error: { type: \"mockingbird_admin\", message } })\n\n/**\n * `PUT /__admin/credentials` accepts `{ credentials: { \"<credential>\": \"<namespace>\" } }`,\n * `[{ credential, namespace }]`, or `{ credentials: [\"<credential>\"] }` with `?namespace=`\n * (maps each to the calling namespace). `GET` lists them masked; `DELETE` removes one\n * (`?credential=`) or all.\n */\nconst credentialRoutes = (registry: CredentialRegistry): AdminRoutes => ({\n \"GET /credentials\": () =>\n adminJson(200, {\n credentials: registry.entries().map(({ credential, namespace }) => ({\n credential: maskCredential(credential),\n namespace,\n })),\n }),\n \"PUT /credentials\": ({ body, namespace }) => {\n const pairs: [string, string][] = []\n const list = Array.isArray(body) ? body : isRecord(body) ? body.credentials : undefined\n if (Array.isArray(list)) {\n for (const each of list) {\n if (typeof each === \"string\") pairs.push([each, namespace])\n else if (isRecord(each) && typeof each.credential === \"string\") {\n pairs.push([\n each.credential,\n typeof each.namespace === \"string\" ? each.namespace : namespace,\n ])\n } else return adminFail(400, \"each entry is a credential string or {credential, namespace}\")\n }\n } else if (isRecord(list)) {\n for (const [credential, target] of Object.entries(list)) {\n if (typeof target !== \"string\")\n return adminFail(400, `namespace for ${credential} must be a string`)\n pairs.push([credential, target])\n }\n } else if (isRecord(body) && typeof body.credential === \"string\") {\n pairs.push([body.credential, typeof body.namespace === \"string\" ? body.namespace : namespace])\n } else {\n return adminFail(400, 'expected {\"credentials\": {\"<credential>\": \"<namespace>\"}}')\n }\n for (const [credential, target] of pairs) {\n if (!KEY_PATTERN.test(target))\n return adminFail(400, `bad namespace ${JSON.stringify(target)}`)\n registry.set(credential, target)\n }\n return adminJson(200, { mapped: pairs.length })\n },\n \"DELETE /credentials\": ({ url }) => {\n const credential = url.searchParams.get(\"credential\")\n if (credential === null) registry.clear()\n else registry.remove(credential)\n return adminJson(200, { status: \"ok\" })\n },\n})\n", "// Generated by @crvouga/mockingbird-openapi-codegen from openapi.yaml. Do not edit.\n\nimport type { OpenAPIDocument } from \"@crvouga/mockingbird-openapi\"\n\nexport const document: OpenAPIDocument = JSON.parse(`{\"openapi\":\"3.1.0\",\"info\":{\"title\":\"Amazon Cloud Control API (Mockingbird subset)\",\"version\":\"1.0.0\",\"description\":\"AWS protocol transport; README lists the implemented AWS operations.\"},\"servers\":[{\"url\":\"https://cloudcontrol.us-east-1.amazonaws.com\"}],\"paths\":{\"/\":{\"post\":{\"operationId\":\"AwsRpc\",\"x-mockingbird\":{\"supported\":false,\"reason\":\"Vendor operations are not implemented in this scaffold.\",\"parity\":{\"enabled\":false,\"reason\":\"Use the stateful LocalStack scenario runner.\"}},\"responses\":{\"200\":{\"description\":\"AWS protocol response\"},\"400\":{\"description\":\"AWS protocol error\"}}},\"get\":{\"operationId\":\"AwsQuery\",\"x-mockingbird\":{\"supported\":false,\"reason\":\"Vendor operations are not implemented in this scaffold.\",\"parity\":{\"enabled\":false,\"reason\":\"Use the stateful LocalStack scenario runner.\"}},\"responses\":{\"200\":{\"description\":\"AWS query response\"}}}},\"/{path}\":{\"parameters\":[{\"name\":\"path\",\"in\":\"path\",\"required\":true,\"schema\":{\"type\":\"string\"}}],\"get\":{\"operationId\":\"AwsRestGet\",\"x-mockingbird\":{\"supported\":false,\"reason\":\"Vendor operations are not implemented in this scaffold.\",\"parity\":{\"enabled\":false,\"reason\":\"Use the stateful LocalStack scenario runner.\"}},\"responses\":{\"200\":{\"description\":\"AWS REST response\"}}},\"put\":{\"operationId\":\"AwsRestPut\",\"x-mockingbird\":{\"supported\":false,\"reason\":\"Vendor operations are not implemented in this scaffold.\",\"parity\":{\"enabled\":false,\"reason\":\"Use the stateful LocalStack scenario runner.\"}},\"responses\":{\"200\":{\"description\":\"AWS REST response\"}}},\"post\":{\"operationId\":\"AwsRestPost\",\"x-mockingbird\":{\"supported\":false,\"reason\":\"Vendor operations are not implemented in this scaffold.\",\"parity\":{\"enabled\":false,\"reason\":\"Use the stateful LocalStack scenario runner.\"}},\"responses\":{\"200\":{\"description\":\"AWS REST response\"}}},\"patch\":{\"operationId\":\"AwsRestPatch\",\"x-mockingbird\":{\"supported\":false,\"reason\":\"Vendor operations are not implemented in this scaffold.\",\"parity\":{\"enabled\":false,\"reason\":\"Use the stateful LocalStack scenario runner.\"}},\"responses\":{\"200\":{\"description\":\"AWS REST response\"}}},\"delete\":{\"operationId\":\"AwsRestDelete\",\"x-mockingbird\":{\"supported\":false,\"reason\":\"Vendor operations are not implemented in this scaffold.\",\"parity\":{\"enabled\":false,\"reason\":\"Use the stateful LocalStack scenario runner.\"}},\"responses\":{\"200\":{\"description\":\"AWS REST response\"}}}}}}`) as OpenAPIDocument\n\nexport type OperationId = \"AwsQuery\" | \"AwsRpc\" | \"AwsRestGet\" | \"AwsRestPut\" | \"AwsRestPost\" | \"AwsRestDelete\" | \"AwsRestPatch\"\nexport type SupportedOperationId = never\nexport const operationIds = [\"AwsQuery\",\"AwsRpc\",\"AwsRestGet\",\"AwsRestPut\",\"AwsRestPost\",\"AwsRestDelete\",\"AwsRestPatch\"] as const\nexport const supportedOperationIds = [] as const\n", "import {\n type Clock,\n type MockControls,\n type RequestLog,\n type ServiceRuntime,\n createRuntime as serviceRuntime,\n sigV4AccessKeyId,\n} from \"@crvouga/mockingbird-service\"\nimport type { SqliteClient } from \"@crvouga/mockingbird-sqlite\"\nimport { document } from \"./generated/openapi.js\"\nimport { CloudcontrolAPI } from \"./index.js\"\nexport type RuntimeOptions = {\n sqlite?: SqliteClient\n clock?: Clock\n seed?: number | string\n region?: string\n accountId?: string\n adminPrefix?: string\n adminKey?: string\n /** Admin controls to boot with: clock, latency, faults, seed, a starting snapshot. */\n adminControls?: MockControls\n onLog?: (entry: RequestLog) => void\n}\nexport type Runtime = ServiceRuntime<CloudcontrolAPI>\nexport const createRuntime = (options: RuntimeOptions = {}): Runtime =>\n serviceRuntime({\n name: \"cloudcontrol\",\n document,\n credential: sigV4AccessKeyId,\n ...(options.sqlite ? { sqlite: options.sqlite } : {}),\n ...(options.clock ? { clock: options.clock } : {}),\n ...(options.seed !== undefined ? { seed: options.seed } : {}),\n ...(options.adminPrefix !== undefined ? { adminPrefix: options.adminPrefix } : {}),\n ...(options.adminKey !== undefined ? { adminKey: options.adminKey } : {}),\n ...(options.adminControls !== undefined ? { adminControls: options.adminControls } : {}),\n ...(options.onLog ? { onLog: options.onLog } : {}),\n create: ({ sqlite, namespace, clock }) =>\n new CloudcontrolAPI({\n sqlite,\n namespace,\n now: clock.now,\n ...(options.region ? { region: options.region } : {}),\n ...(options.accountId ? { accountId: options.accountId } : {}),\n }),\n })\n", "import {\n type AwsOperation,\n AwsProtocolAPI,\n type AwsProtocolOptions,\n} from \"@crvouga/mockingbird-service\"\nimport { document, operationIds, supportedOperationIds } from \"./generated/openapi.js\"\n\nexport type { Runtime, RuntimeOptions } from \"./runtime.js\"\nexport { createRuntime } from \"./runtime.js\"\nexport { document, operationIds, supportedOperationIds }\nexport type APIOptions = AwsProtocolOptions\nexport class CloudcontrolAPI extends AwsProtocolAPI {\n constructor(options: APIOptions = {}) {\n super(\"cloudcontrol\", options)\n }\n dispatch({ operation }: AwsOperation): unknown {\n return this.unsupported(operation)\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["fetch", "_", "matches", "match", "name", "matches", "count", "match", "name", "name", "defaultOptions", "validateEntityName", "startIndex", "name", "d", "match", "lastSeg", "tag", "name", "sep", "name", "matches", "result", "name", "METADATA_SYMBOL", "document", "document", "key", "match", "keyIndex", "name", "name", "name", "name", "match", "isRecord", "name", "next", "isRecord", "name", "name", "isRecord", "name", "routes", "isRecord", "count", "url", "name", "json", "isRecord", "name", "field", "json", "adminError", "json", "adminError", "isRecord", "document", "name", "snapshot", "branch", "isRecord", "stepping", "kept", "url", "response", "copy", "notes", "createRuntime"]
7
+ }