@omniaura/scenario-sim 0.1.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.
- package/README.md +118 -0
- package/dist/browser.d.ts +81 -0
- package/dist/browser.js +303 -0
- package/dist/browser.js.map +1 -0
- package/dist/chunk-44ZHRYG6.js +959 -0
- package/dist/chunk-44ZHRYG6.js.map +1 -0
- package/dist/chunk-7FWVWBX6.js +380 -0
- package/dist/chunk-7FWVWBX6.js.map +1 -0
- package/dist/chunk-7HBAY3QY.js +133 -0
- package/dist/chunk-7HBAY3QY.js.map +1 -0
- package/dist/chunk-KU4W4SKO.js +1236 -0
- package/dist/chunk-KU4W4SKO.js.map +1 -0
- package/dist/cli.js +131 -0
- package/dist/cli.js.map +1 -0
- package/dist/engine-2w32ngB2.d.ts +897 -0
- package/dist/engine-HE7MEQHD.js +15 -0
- package/dist/engine-HE7MEQHD.js.map +1 -0
- package/dist/examples.d.ts +38 -0
- package/dist/examples.js +233 -0
- package/dist/examples.js.map +1 -0
- package/dist/index.d.ts +322 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/pulse.d.ts +40 -0
- package/dist/pulse.js +80 -0
- package/dist/pulse.js.map +1 -0
- package/dist/scenario--CvzkzX_.d.ts +637 -0
- package/dist/server.d.ts +29 -0
- package/dist/server.js +14 -0
- package/dist/server.js.map +1 -0
- package/dist/vite.d.ts +27 -0
- package/dist/vite.js +48 -0
- package/dist/vite.js.map +1 -0
- package/package.json +91 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/engine.ts"],"sourcesContent":["/**\n * The simulator: resolves a run per request, applies faults, routes HTTP/SSE/\n * WebSocket, and serves the control plane under `/__sim`. Runtime-neutral:\n * takes a Web `Request`, returns a Web `Response`. Adapters (Bun/Node server,\n * Vite middleware, in-browser) only translate transports and WebSocket\n * upgrades.\n *\n * Control plane (all also available as `sim.api.*` in-process):\n * GET /__sim/scenarios\n * GET /__sim/status?run=\n * POST /__sim/select {scenario, seed?, run?} bind a run to a scenario (fresh state)\n * POST /__sim/reset {run?, seed?} rebuild the run's scenario\n * POST /__sim/step {run?, ms} advance a manual clock\n * POST /__sim/clock {run?, mode?, speed?}\n * GET /__sim/state?run=&collection= inspect the store\n * GET /__sim/events?run=&since=&limit=&collection= store mutation log\n * GET /__sim/log?run=&since=&limit= run log (requests, streams, actions)\n * GET /__sim/streams?run=\n * POST /__sim/streams/disconnect {run?, id?|topic?|path?|all?, code?, reason?, drop?}\n * POST /__sim/streams/pause {run?, id, paused}\n * POST /__sim/publish {run?, topic, data} publish a stream event by hand\n * GET/POST/DELETE /__sim/overrides {run?, matcher, method?, status?, body?, times?, delayMs?, malformed?}\n * POST /__sim/faults {run?, latencyMs?, jitterMs?, failMode?, shellPaths?}\n * POST /__sim/action {run?, name, args?}\n * GET /__sim/runs · DELETE /__sim/runs?run=\n *\n * Run selection per request: `X-Sim-Run` header → `sim_run` cookie →\n * `?__run=` → \"default\". Scenario for a *new* run: `X-Sim-Scenario` → cookie\n * → `?__scenario=` → `?scenario=` → default scenario.\n */\n\nimport type { ScenarioDefinition } from \"./scenario.js\";\nimport { Run } from \"./scenario.js\";\nimport { json, problem, type RouteContext } from \"./router.js\";\nimport type { StreamContext, WsRoute } from \"./streams.js\";\nimport type { OverrideInput } from \"./faults.js\";\n\nexport interface SimulatorOptions {\n scenarios: ScenarioDefinition[];\n defaultScenario?: string;\n /** Control-plane prefix (default `/__sim`). */\n controlPath?: string;\n /** Default run id (default `default`). */\n defaultRun?: string;\n /** Add permissive CORS headers (default true — the mock is a dev tool). */\n cors?: boolean;\n log?: (line: string) => void;\n}\n\n/**\n * Marker for \"the adapter completed the WebSocket upgrade\". Node's undici\n * refuses `new Response(null, { status: 101 })`, so adapters return a 200 with\n * this header instead of a 101.\n */\nexport const UPGRADED_HEADER = \"x-sim-upgraded\";\nexport const upgradedResponse = () => new Response(null, { status: 200, headers: { [UPGRADED_HEADER]: \"1\" } });\nexport const isUpgraded = (response: Response) => response.headers.get(UPGRADED_HEADER) === \"1\";\n\n/** How an adapter completes a WebSocket upgrade for a matched route. */\nexport type UpgradeHook = (route: WsRoute, ctx: StreamContext, run: Run, protocol: string | null) => Response | Promise<Response>;\n\nexport interface HandleOptions {\n upgrade?: UpgradeHook;\n}\n\nexport class Simulator {\n readonly scenarios = new Map<string, ScenarioDefinition>();\n readonly runs = new Map<string, Run>();\n readonly controlPath: string;\n readonly defaultRun: string;\n readonly defaultScenario: string;\n private readonly cors: boolean;\n private readonly log: (line: string) => void;\n\n constructor(options: SimulatorOptions) {\n if (options.scenarios.length === 0) throw new Error(\"at least one scenario is required\");\n for (const s of options.scenarios) {\n if (this.scenarios.has(s.name)) throw new Error(`duplicate scenario ${s.name}`);\n this.scenarios.set(s.name, s);\n }\n this.defaultScenario = options.defaultScenario ?? options.scenarios[0]!.name;\n if (!this.scenarios.has(this.defaultScenario)) throw new Error(`unknown default scenario ${this.defaultScenario}`);\n this.controlPath = (options.controlPath ?? \"/__sim\").replace(/\\/$/, \"\");\n this.defaultRun = options.defaultRun ?? \"default\";\n this.cors = options.cors ?? true;\n this.log = options.log ?? (() => {});\n }\n\n // ── runs ─────────────────────────────────────────────────────────\n\n private cookie(request: Request, name: string): string | null {\n const header = request.headers.get(\"cookie\") ?? \"\";\n for (const part of header.split(\";\")) {\n const [k, ...rest] = part.trim().split(\"=\");\n if (k === name) return decodeURIComponent(rest.join(\"=\"));\n }\n return null;\n }\n\n runIdFor(request: Request, url: URL): string {\n return request.headers.get(\"x-sim-run\") ?? this.cookie(request, \"sim_run\") ?? url.searchParams.get(\"__run\") ?? this.defaultRun;\n }\n\n scenarioNameFor(request: Request, url: URL): string {\n return request.headers.get(\"x-sim-scenario\") ?? this.cookie(request, \"sim_scenario\") ?? url.searchParams.get(\"__scenario\") ?? url.searchParams.get(\"scenario\") ?? this.defaultScenario;\n }\n\n /** Get or lazily create the run for a request. */\n async runFor(request: Request, url: URL): Promise<Run> {\n const id = this.runIdFor(request, url);\n let run = this.runs.get(id);\n if (!run) {\n const name = this.scenarioNameFor(request, url);\n run = this.createRun(id, name);\n }\n await run.ready;\n return run;\n }\n\n createRun(id: string, scenarioName: string, seed?: string): Run {\n const scenario = this.scenarios.get(scenarioName);\n if (!scenario) throw new Error(`unknown scenario \"${scenarioName}\" (available: ${[...this.scenarios.keys()].join(\", \")})`);\n this.runs.get(id)?.dispose();\n const run = new Run(id, scenario, seed ?? scenario.seed ?? scenario.name, this.log);\n this.runs.set(id, run);\n return run;\n }\n\n getRun(id = this.defaultRun): Run | null {\n return this.runs.get(id) ?? null;\n }\n\n // ── request handling ─────────────────────────────────────────────\n\n async handle(request: Request, options: HandleOptions = {}): Promise<Response> {\n const url = new URL(request.url);\n try {\n if (request.method === \"OPTIONS\" && this.cors) return this.withCors(request, new Response(null, { status: 204 }));\n if (url.pathname === this.controlPath || url.pathname.startsWith(`${this.controlPath}/`)) {\n return this.withCors(request, await this.control(request, url));\n }\n const run = await this.runFor(request, url);\n run.requests++;\n const path = url.pathname;\n const method = request.method.toUpperCase();\n\n // Per-request fault overrides (compatible with console-style mocks):\n // `X-Sim-Latency: <ms>` and `X-Sim-Fail: off|data|all` apply to this\n // request only, on top of the run's configured faults.\n const latencyHeader = request.headers.get(\"x-sim-latency\");\n const failHeader = request.headers.get(\"x-sim-fail\");\n const extraLatency = latencyHeader !== null && latencyHeader !== \"\" && Number.isFinite(Number(latencyHeader)) ? Math.max(0, Number(latencyHeader)) : 0;\n const failOverride = failHeader === \"off\" || failHeader === \"data\" || failHeader === \"all\" ? failHeader : null;\n const failResponse = (p: string) => {\n if (failOverride === null) return run.faults.failResponse(p);\n if (failOverride === \"off\") return null;\n if (failOverride === \"data\" && run.faults.shellPaths.has(p)) return null;\n return problem(503, `scenario fail mode \"${failOverride}\" (X-Sim-Fail)`);\n };\n\n // Overrides first: a forced answer for any path, even unrouted ones.\n const override = run.faults.matchOverride(path, method);\n if (override) {\n run.log(`${method} ${path} → override ${override.id}`, { status: override.status ?? null, malformed: override.malformed ?? null });\n await run.clock.sleep(run.faults.delayFor(override.delayMs ?? 0), `override ${override.id}`);\n return this.withCors(request, run.faults.overrideResponse(override));\n }\n\n // WebSocket routes. `Upgrade`/`Sec-WebSocket-Protocol` are forbidden\n // request headers in browsers (silently dropped), so adapters also send\n // `x-sim-upgrade` / `x-sim-websocket-protocol` mirrors.\n const upgradeHeader = request.headers.get(\"upgrade\") ?? request.headers.get(\"x-sim-upgrade\");\n if (upgradeHeader?.toLowerCase() === \"websocket\") {\n for (const route of run.wsRoutes) {\n const params = matchPath(route.path, path);\n if (!params) continue;\n if (!options.upgrade) return this.withCors(request, problem(426, \"WebSocket upgrade requires a transport adapter\"));\n const requested = (request.headers.get(\"sec-websocket-protocol\") ?? request.headers.get(\"x-sim-websocket-protocol\") ?? \"\").split(\",\").map((s) => s.trim()).filter(Boolean);\n const protocol = route.protocols?.find((p) => requested.includes(p)) ?? null;\n if (route.protocols?.length && requested.length && !protocol) return this.withCors(request, problem(400, `unsupported subprotocol (server offers ${route.protocols.join(\", \")})`));\n const failed = failResponse(path);\n if (failed) return this.withCors(request, failed);\n return options.upgrade(route, this.streamContext(run, request, url, params), run, protocol);\n }\n return this.withCors(request, problem(404, `no WebSocket route matches ${path}`));\n }\n\n // Fail mode (after overrides so a test can still force a success).\n const failed = failResponse(path);\n if (failed) {\n run.log(`${method} ${path} → fail mode ${failOverride ?? run.faults.failMode}`);\n await run.clock.sleep(run.faults.delayFor(extraLatency), \"fail-mode latency\");\n return this.withCors(request, failed);\n }\n\n // SSE routes.\n for (const route of run.sseRoutes) {\n if ((route.method ?? \"GET\") !== method) continue;\n const params = matchPath(route.path, path);\n if (!params) continue;\n await run.clock.sleep(run.faults.delayFor(extraLatency), \"sse open latency\");\n const stream = run.streams.openSse(route, this.streamContext(run, request, url, params));\n return this.withCors(request, stream.response);\n }\n\n // HTTP routes (definition order; first match wins).\n for (const route of run.routes) {\n if (route.method !== \"*\" && route.method !== method) continue;\n const params = route.match(path);\n if (!params) continue;\n route.calls++;\n const ctx = this.routeContext(run, request, url, params, route.calls);\n const started = run.clock.now();\n await run.clock.sleep(run.faults.delayFor(extraLatency), `latency ${method} ${path}`);\n const response = await route.handler(ctx);\n run.log(`${method} ${path} → ${response.status}`, { route: route.name ?? route.path, ms: Math.round(run.clock.now() - started) });\n return this.withCors(request, response);\n }\n\n run.log(`${method} ${path} → 404 (no route)`);\n return this.withCors(request, problem(404, `scenario \"${run.scenario.name}\" has no route for ${method} ${path}`, { hint: `${this.controlPath}/status lists routes; set an override to force an answer` }));\n } catch (err) {\n this.log(`[sim] error handling ${request.method} ${url.pathname}: ${err instanceof Error ? err.stack ?? err.message : String(err)}`);\n return this.withCors(request, problem(500, `simulator error: ${err instanceof Error ? err.message : String(err)}`));\n }\n }\n\n private routeContext(run: Run, request: Request, url: URL, params: Record<string, string>, calls: number): RouteContext {\n let parsed: Promise<unknown> | null = null;\n return {\n request,\n url,\n method: request.method.toUpperCase(),\n params,\n query: url.searchParams,\n body: <T,>() => {\n parsed ??= request\n .clone()\n .text()\n .then((t) => (t ? JSON.parse(t) : {}))\n .catch(() => ({}));\n return parsed as Promise<T>;\n },\n state: run.state,\n rng: run.rng,\n clock: run.clock,\n streams: run.streams,\n run: run.info(),\n calls,\n log: (m, d) => run.log(m, d),\n };\n }\n\n streamContext(run: Run, request: Request, url: URL, params: Record<string, string>): StreamContext {\n return { request, url, params, query: url.searchParams, state: run.state, rng: run.rng, clock: run.clock, streams: run.streams, run: run.info(), log: (m, d) => run.log(m, d) };\n }\n\n private withCors(request: Request, response: Response): Response {\n if (!this.cors) return response;\n const origin = request.headers.get(\"origin\");\n if (!origin) return response;\n const headers = new Headers(response.headers);\n headers.set(\"access-control-allow-origin\", origin);\n headers.set(\"access-control-allow-credentials\", \"true\");\n headers.set(\"access-control-allow-methods\", \"GET,POST,PUT,PATCH,DELETE,OPTIONS\");\n headers.set(\"access-control-allow-headers\", request.headers.get(\"access-control-request-headers\") ?? \"*\");\n headers.set(\"access-control-expose-headers\", \"*\");\n headers.set(\"vary\", \"origin\");\n return new Response(response.body, { status: response.status, statusText: response.statusText, headers });\n }\n\n // ── control plane ────────────────────────────────────────────────\n\n private async control(request: Request, url: URL): Promise<Response> {\n const route = url.pathname.slice(this.controlPath.length).replace(/\\/$/, \"\") || \"/\";\n const method = request.method.toUpperCase();\n const body = method === \"GET\" || method === \"DELETE\" ? {} : await request.clone().text().then((t) => (t ? (JSON.parse(t) as Record<string, unknown>) : {})).catch(() => ({} as Record<string, unknown>));\n const runId = String((body as { run?: string }).run ?? url.searchParams.get(\"run\") ?? request.headers.get(\"x-sim-run\") ?? this.cookie(request, \"sim_run\") ?? this.defaultRun);\n const api = this.api;\n const q = (k: string) => url.searchParams.get(k);\n const num = (v: unknown, d: number) => (v === undefined || v === null || v === \"\" ? d : Number(v));\n\n switch (`${method} ${route}`) {\n case \"GET /\":\n return json({ tool: \"@omniaura/scenario-sim\", controlPath: this.controlPath, defaultRun: this.defaultRun, defaultScenario: this.defaultScenario, runs: [...this.runs.keys()] });\n case \"GET /scenarios\":\n return json({ default: this.defaultScenario, scenarios: api.scenarios() });\n case \"GET /status\":\n return json(await api.status(runId));\n case \"POST /select\": {\n const b = body as { scenario?: string; seed?: string };\n if (!b.scenario) return problem(400, \"scenario is required\");\n return json(await api.select(runId, b.scenario, b.seed), { headers: { \"set-cookie\": `sim_scenario=${encodeURIComponent(b.scenario)}; Path=/; SameSite=Lax` } });\n }\n case \"POST /reset\":\n return json(await api.reset(runId, (body as { seed?: string }).seed));\n case \"POST /step\":\n return json(api.step(runId, num((body as { ms?: number }).ms ?? q(\"ms\"), 1000)));\n case \"POST /clock\":\n return json(api.clock(runId, body as { mode?: \"manual\" | \"realtime\"; speed?: number }));\n case \"GET /state\":\n return json(api.state(runId, q(\"collection\") ?? undefined));\n case \"GET /events\":\n return json(api.events(runId, { since: num(q(\"since\"), 0), limit: num(q(\"limit\"), 200), collection: q(\"collection\") ?? undefined }));\n case \"GET /log\":\n return json(api.log(runId, { since: num(q(\"since\"), 0), limit: num(q(\"limit\"), 200) }));\n case \"GET /streams\":\n return json(api.streams(runId));\n case \"POST /streams/disconnect\": {\n const b = body as { id?: string; topic?: string; path?: string; all?: boolean; code?: number; reason?: string; drop?: boolean };\n return json(api.disconnect(runId, b, b));\n }\n case \"POST /streams/pause\": {\n const b = body as { id?: string; paused?: boolean };\n if (!b.id) return problem(400, \"id is required\");\n return json({ ok: api.pause(runId, b.id, b.paused ?? true) });\n }\n case \"POST /publish\": {\n const b = body as { topic?: string; data?: Record<string, unknown> };\n if (!b.topic) return problem(400, \"topic is required\");\n return json(api.publish(runId, b.topic, b.data ?? {}));\n }\n case \"GET /overrides\":\n return json(api.overrides(runId));\n case \"POST /overrides\": {\n const b = body as unknown as OverrideInput;\n if (!b.matcher) return problem(400, \"matcher is required\");\n return json(api.setOverride(runId, b));\n }\n case \"DELETE /overrides\": {\n const matcher = q(\"matcher\");\n const id = q(\"id\");\n return json(api.clearOverrides(runId, id ?? matcher ?? undefined, q(\"method\") ?? undefined));\n }\n case \"POST /faults\":\n return json(api.faults(runId, body as Parameters<typeof api.faults>[1]));\n case \"POST /action\": {\n const b = body as { name?: string; args?: Record<string, unknown> };\n if (!b.name) return problem(400, \"name is required\");\n return json({ result: await api.action(runId, b.name, b.args ?? {}) });\n }\n case \"GET /runs\":\n return json(api.runs());\n case \"DELETE /runs\":\n return json({ deleted: api.deleteRun(runId) });\n default:\n return problem(404, `unknown control route ${method} ${route}`);\n }\n }\n\n /** In-process control API — the same operations the HTTP control plane offers. */\n readonly api = {\n scenarios: () =>\n [...this.scenarios.values()].map((s) => ({ name: s.name, label: s.label ?? null, description: s.description ?? null, seed: s.seed ?? s.name, tags: s.tags ?? [], clock: s.clock ?? { mode: \"realtime\" }, actions: Object.keys(s.actions ?? {}), qa: s.qa ?? null })),\n status: async (runId = this.defaultRun) => {\n const run = this.runs.get(runId);\n if (!run) return { run: runId, scenario: null, exists: false, defaultScenario: this.defaultScenario };\n await run.ready;\n return { exists: true, ...run.status() };\n },\n select: async (runId: string, scenario: string, seed?: string) => {\n const run = this.createRun(runId, scenario, seed);\n await run.ready;\n return run.status();\n },\n reset: async (runId: string, seed?: string) => {\n const existing = this.runs.get(runId);\n const run = this.createRun(runId, existing?.scenario.name ?? this.defaultScenario, seed ?? existing?.seed);\n await run.ready;\n return run.status();\n },\n step: (runId: string, ms: number) => {\n const run = this.require(runId);\n if (run.clock.mode !== \"manual\") run.clock.setMode(\"manual\");\n const r = run.clock.step(ms);\n run.log(`step ${ms}ms → now ${r.now}`, { fired: r.fired.length });\n return { ...r, pending: run.clock.pending() };\n },\n clock: (runId: string, patch: { mode?: \"manual\" | \"realtime\"; speed?: number }) => {\n const run = this.require(runId);\n if (patch.speed !== undefined) run.clock.speed = Math.max(0.01, Number(patch.speed));\n if (patch.mode) run.clock.setMode(patch.mode);\n return { mode: run.clock.mode, speed: run.clock.speed, now: Math.round(run.clock.now()), pending: run.clock.pending() };\n },\n state: (runId: string, collection?: string) => {\n const run = this.require(runId);\n const snap = run.state.snapshot();\n return collection ? { run: runId, collection, items: snap[collection] ?? [] } : { run: runId, counts: run.state.counts(), collections: snap };\n },\n events: (runId: string, opts: { since?: number; limit?: number; collection?: string }) => {\n const run = this.require(runId);\n const events = run.state.events(opts);\n return { run: runId, last: run.state.lastSeq, count: events.length, events };\n },\n log: (runId: string, opts: { since?: number; limit?: number }) => ({ run: runId, entries: this.require(runId).logs(opts) }),\n streams: (runId: string) => {\n const run = this.require(runId);\n return { run: runId, connections: run.streams.list(), topics: run.streams.topics.topics().map((t) => ({ topic: t, last: run.streams.topics.last(t) })), latencyMs: run.streams.latencyMs };\n },\n disconnect: (runId: string, target: { id?: string; topic?: string; path?: string; all?: boolean }, opts: { code?: number; reason?: string; drop?: boolean } = {}) => {\n const run = this.require(runId);\n const closed = run.streams.disconnect(target, opts);\n run.log(`disconnect ${JSON.stringify(target)}`, { closed, drop: opts.drop ?? false });\n return { closed };\n },\n pause: (runId: string, id: string, paused: boolean) => this.require(runId).streams.pause(id, paused),\n publish: (runId: string, topic: string, data: Record<string, unknown>) => this.require(runId).streams.publish(topic, data),\n overrides: (runId: string) => ({ run: runId, overrides: this.require(runId).faults.listOverrides() }),\n setOverride: (runId: string, input: OverrideInput) => {\n const run = this.require(runId);\n const o = run.faults.setOverride(input);\n run.log(`override set ${o.id}`, { matcher: o.matcher, method: o.method ?? \"*\", status: o.status ?? null, times: o.times ?? null });\n return o;\n },\n clearOverrides: (runId: string, target?: string, method?: string) => {\n const run = this.require(runId);\n if (target) return { cleared: run.faults.clearOverride(target, method) };\n run.faults.clearOverrides();\n return { cleared: true };\n },\n faults: (runId: string, patch: { latencyMs?: number; jitterMs?: number; failMode?: \"off\" | \"data\" | \"all\"; shellPaths?: string[]; streamLatencyMs?: number }) => {\n const run = this.require(runId);\n run.faults.configure(patch);\n if (patch.streamLatencyMs !== undefined) run.streams.latencyMs = Math.max(0, patch.streamLatencyMs);\n run.log(\"faults configured\", patch);\n return { ...run.faults.snapshot(), streamLatencyMs: run.streams.latencyMs };\n },\n action: (runId: string, name: string, args: Record<string, unknown> = {}) => this.require(runId).action(name, args),\n runs: () => [...this.runs.values()].map((r) => ({ id: r.id, scenario: r.scenario.name, seed: r.seed, requests: r.requests, createdWall: r.createdWall })),\n deleteRun: (runId: string) => {\n const run = this.runs.get(runId);\n if (!run) return false;\n run.dispose();\n this.runs.delete(runId);\n return true;\n },\n };\n\n private require(runId = this.defaultRun): Run {\n const run = this.runs.get(runId) ?? this.createRun(runId, this.defaultScenario);\n return run;\n }\n\n dispose() {\n for (const run of this.runs.values()) run.dispose();\n this.runs.clear();\n }\n}\n\nexport function matchPath(pattern: string, pathname: string): Record<string, string> | null {\n const keys: string[] = [];\n const re = new RegExp(\n \"^\" +\n pattern\n .split(\"/\")\n .map((seg) => {\n if (seg === \"*\") return \"(?:.*)\";\n if (seg.startsWith(\":\")) {\n keys.push(seg.slice(1));\n return \"([^/]+)\";\n }\n return seg.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n })\n .join(\"/\") +\n \"/?$\",\n );\n const m = re.exec(pathname);\n if (!m) return null;\n const params: Record<string, string> = {};\n keys.forEach((k, i) => (params[k] = decodeURIComponent(m[i + 1] ?? \"\")));\n return params;\n}\n"],"mappings":";;;;;;;AAsDO,IAAM,kBAAkB;AACxB,IAAM,mBAAmB,MAAM,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,SAAS,EAAE,CAAC,eAAe,GAAG,IAAI,EAAE,CAAC;AACtG,IAAM,aAAa,CAAC,aAAuB,SAAS,QAAQ,IAAI,eAAe,MAAM;AASrF,IAAM,YAAN,MAAgB;AAAA,EACZ,YAAY,oBAAI,IAAgC;AAAA,EAChD,OAAO,oBAAI,IAAiB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACQ;AAAA,EACA;AAAA,EAEjB,YAAY,SAA2B;AACrC,QAAI,QAAQ,UAAU,WAAW,EAAG,OAAM,IAAI,MAAM,mCAAmC;AACvF,eAAW,KAAK,QAAQ,WAAW;AACjC,UAAI,KAAK,UAAU,IAAI,EAAE,IAAI,EAAG,OAAM,IAAI,MAAM,sBAAsB,EAAE,IAAI,EAAE;AAC9E,WAAK,UAAU,IAAI,EAAE,MAAM,CAAC;AAAA,IAC9B;AACA,SAAK,kBAAkB,QAAQ,mBAAmB,QAAQ,UAAU,CAAC,EAAG;AACxE,QAAI,CAAC,KAAK,UAAU,IAAI,KAAK,eAAe,EAAG,OAAM,IAAI,MAAM,4BAA4B,KAAK,eAAe,EAAE;AACjH,SAAK,eAAe,QAAQ,eAAe,UAAU,QAAQ,OAAO,EAAE;AACtE,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,OAAO,QAAQ,QAAQ;AAC5B,SAAK,MAAM,QAAQ,QAAQ,MAAM;AAAA,IAAC;AAAA,EACpC;AAAA;AAAA,EAIQ,OAAO,SAAkB,MAA6B;AAC5D,UAAM,SAAS,QAAQ,QAAQ,IAAI,QAAQ,KAAK;AAChD,eAAW,QAAQ,OAAO,MAAM,GAAG,GAAG;AACpC,YAAM,CAAC,GAAG,GAAG,IAAI,IAAI,KAAK,KAAK,EAAE,MAAM,GAAG;AAC1C,UAAI,MAAM,KAAM,QAAO,mBAAmB,KAAK,KAAK,GAAG,CAAC;AAAA,IAC1D;AACA,WAAO;AAAA,EACT;AAAA,EAEA,SAAS,SAAkB,KAAkB;AAC3C,WAAO,QAAQ,QAAQ,IAAI,WAAW,KAAK,KAAK,OAAO,SAAS,SAAS,KAAK,IAAI,aAAa,IAAI,OAAO,KAAK,KAAK;AAAA,EACtH;AAAA,EAEA,gBAAgB,SAAkB,KAAkB;AAClD,WAAO,QAAQ,QAAQ,IAAI,gBAAgB,KAAK,KAAK,OAAO,SAAS,cAAc,KAAK,IAAI,aAAa,IAAI,YAAY,KAAK,IAAI,aAAa,IAAI,UAAU,KAAK,KAAK;AAAA,EACzK;AAAA;AAAA,EAGA,MAAM,OAAO,SAAkB,KAAwB;AACrD,UAAM,KAAK,KAAK,SAAS,SAAS,GAAG;AACrC,QAAI,MAAM,KAAK,KAAK,IAAI,EAAE;AAC1B,QAAI,CAAC,KAAK;AACR,YAAM,OAAO,KAAK,gBAAgB,SAAS,GAAG;AAC9C,YAAM,KAAK,UAAU,IAAI,IAAI;AAAA,IAC/B;AACA,UAAM,IAAI;AACV,WAAO;AAAA,EACT;AAAA,EAEA,UAAU,IAAY,cAAsB,MAAoB;AAC9D,UAAM,WAAW,KAAK,UAAU,IAAI,YAAY;AAChD,QAAI,CAAC,SAAU,OAAM,IAAI,MAAM,qBAAqB,YAAY,iBAAiB,CAAC,GAAG,KAAK,UAAU,KAAK,CAAC,EAAE,KAAK,IAAI,CAAC,GAAG;AACzH,SAAK,KAAK,IAAI,EAAE,GAAG,QAAQ;AAC3B,UAAM,MAAM,IAAI,IAAI,IAAI,UAAU,QAAQ,SAAS,QAAQ,SAAS,MAAM,KAAK,GAAG;AAClF,SAAK,KAAK,IAAI,IAAI,GAAG;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,KAAK,KAAK,YAAwB;AACvC,WAAO,KAAK,KAAK,IAAI,EAAE,KAAK;AAAA,EAC9B;AAAA;AAAA,EAIA,MAAM,OAAO,SAAkB,UAAyB,CAAC,GAAsB;AAC7E,UAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAC/B,QAAI;AACF,UAAI,QAAQ,WAAW,aAAa,KAAK,KAAM,QAAO,KAAK,SAAS,SAAS,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC,CAAC;AAChH,UAAI,IAAI,aAAa,KAAK,eAAe,IAAI,SAAS,WAAW,GAAG,KAAK,WAAW,GAAG,GAAG;AACxF,eAAO,KAAK,SAAS,SAAS,MAAM,KAAK,QAAQ,SAAS,GAAG,CAAC;AAAA,MAChE;AACA,YAAM,MAAM,MAAM,KAAK,OAAO,SAAS,GAAG;AAC1C,UAAI;AACJ,YAAM,OAAO,IAAI;AACjB,YAAM,SAAS,QAAQ,OAAO,YAAY;AAK1C,YAAM,gBAAgB,QAAQ,QAAQ,IAAI,eAAe;AACzD,YAAM,aAAa,QAAQ,QAAQ,IAAI,YAAY;AACnD,YAAM,eAAe,kBAAkB,QAAQ,kBAAkB,MAAM,OAAO,SAAS,OAAO,aAAa,CAAC,IAAI,KAAK,IAAI,GAAG,OAAO,aAAa,CAAC,IAAI;AACrJ,YAAM,eAAe,eAAe,SAAS,eAAe,UAAU,eAAe,QAAQ,aAAa;AAC1G,YAAM,eAAe,CAAC,MAAc;AAClC,YAAI,iBAAiB,KAAM,QAAO,IAAI,OAAO,aAAa,CAAC;AAC3D,YAAI,iBAAiB,MAAO,QAAO;AACnC,YAAI,iBAAiB,UAAU,IAAI,OAAO,WAAW,IAAI,CAAC,EAAG,QAAO;AACpE,eAAO,QAAQ,KAAK,uBAAuB,YAAY,gBAAgB;AAAA,MACzE;AAGA,YAAM,WAAW,IAAI,OAAO,cAAc,MAAM,MAAM;AACtD,UAAI,UAAU;AACZ,YAAI,IAAI,GAAG,MAAM,IAAI,IAAI,oBAAe,SAAS,EAAE,IAAI,EAAE,QAAQ,SAAS,UAAU,MAAM,WAAW,SAAS,aAAa,KAAK,CAAC;AACjI,cAAM,IAAI,MAAM,MAAM,IAAI,OAAO,SAAS,SAAS,WAAW,CAAC,GAAG,YAAY,SAAS,EAAE,EAAE;AAC3F,eAAO,KAAK,SAAS,SAAS,IAAI,OAAO,iBAAiB,QAAQ,CAAC;AAAA,MACrE;AAKA,YAAM,gBAAgB,QAAQ,QAAQ,IAAI,SAAS,KAAK,QAAQ,QAAQ,IAAI,eAAe;AAC3F,UAAI,eAAe,YAAY,MAAM,aAAa;AAChD,mBAAW,SAAS,IAAI,UAAU;AAChC,gBAAM,SAAS,UAAU,MAAM,MAAM,IAAI;AACzC,cAAI,CAAC,OAAQ;AACb,cAAI,CAAC,QAAQ,QAAS,QAAO,KAAK,SAAS,SAAS,QAAQ,KAAK,gDAAgD,CAAC;AAClH,gBAAM,aAAa,QAAQ,QAAQ,IAAI,wBAAwB,KAAK,QAAQ,QAAQ,IAAI,0BAA0B,KAAK,IAAI,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AACzK,gBAAM,WAAW,MAAM,WAAW,KAAK,CAAC,MAAM,UAAU,SAAS,CAAC,CAAC,KAAK;AACxE,cAAI,MAAM,WAAW,UAAU,UAAU,UAAU,CAAC,SAAU,QAAO,KAAK,SAAS,SAAS,QAAQ,KAAK,0CAA0C,MAAM,UAAU,KAAK,IAAI,CAAC,GAAG,CAAC;AACjL,gBAAMA,UAAS,aAAa,IAAI;AAChC,cAAIA,QAAQ,QAAO,KAAK,SAAS,SAASA,OAAM;AAChD,iBAAO,QAAQ,QAAQ,OAAO,KAAK,cAAc,KAAK,SAAS,KAAK,MAAM,GAAG,KAAK,QAAQ;AAAA,QAC5F;AACA,eAAO,KAAK,SAAS,SAAS,QAAQ,KAAK,8BAA8B,IAAI,EAAE,CAAC;AAAA,MAClF;AAGA,YAAM,SAAS,aAAa,IAAI;AAChC,UAAI,QAAQ;AACV,YAAI,IAAI,GAAG,MAAM,IAAI,IAAI,qBAAgB,gBAAgB,IAAI,OAAO,QAAQ,EAAE;AAC9E,cAAM,IAAI,MAAM,MAAM,IAAI,OAAO,SAAS,YAAY,GAAG,mBAAmB;AAC5E,eAAO,KAAK,SAAS,SAAS,MAAM;AAAA,MACtC;AAGA,iBAAW,SAAS,IAAI,WAAW;AACjC,aAAK,MAAM,UAAU,WAAW,OAAQ;AACxC,cAAM,SAAS,UAAU,MAAM,MAAM,IAAI;AACzC,YAAI,CAAC,OAAQ;AACb,cAAM,IAAI,MAAM,MAAM,IAAI,OAAO,SAAS,YAAY,GAAG,kBAAkB;AAC3E,cAAM,SAAS,IAAI,QAAQ,QAAQ,OAAO,KAAK,cAAc,KAAK,SAAS,KAAK,MAAM,CAAC;AACvF,eAAO,KAAK,SAAS,SAAS,OAAO,QAAQ;AAAA,MAC/C;AAGA,iBAAW,SAAS,IAAI,QAAQ;AAC9B,YAAI,MAAM,WAAW,OAAO,MAAM,WAAW,OAAQ;AACrD,cAAM,SAAS,MAAM,MAAM,IAAI;AAC/B,YAAI,CAAC,OAAQ;AACb,cAAM;AACN,cAAM,MAAM,KAAK,aAAa,KAAK,SAAS,KAAK,QAAQ,MAAM,KAAK;AACpE,cAAM,UAAU,IAAI,MAAM,IAAI;AAC9B,cAAM,IAAI,MAAM,MAAM,IAAI,OAAO,SAAS,YAAY,GAAG,WAAW,MAAM,IAAI,IAAI,EAAE;AACpF,cAAM,WAAW,MAAM,MAAM,QAAQ,GAAG;AACxC,YAAI,IAAI,GAAG,MAAM,IAAI,IAAI,WAAM,SAAS,MAAM,IAAI,EAAE,OAAO,MAAM,QAAQ,MAAM,MAAM,IAAI,KAAK,MAAM,IAAI,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;AAChI,eAAO,KAAK,SAAS,SAAS,QAAQ;AAAA,MACxC;AAEA,UAAI,IAAI,GAAG,MAAM,IAAI,IAAI,wBAAmB;AAC5C,aAAO,KAAK,SAAS,SAAS,QAAQ,KAAK,aAAa,IAAI,SAAS,IAAI,sBAAsB,MAAM,IAAI,IAAI,IAAI,EAAE,MAAM,GAAG,KAAK,WAAW,2DAA2D,CAAC,CAAC;AAAA,IAC3M,SAAS,KAAK;AACZ,WAAK,IAAI,wBAAwB,QAAQ,MAAM,IAAI,IAAI,QAAQ,KAAK,eAAe,QAAQ,IAAI,SAAS,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AACnI,aAAO,KAAK,SAAS,SAAS,QAAQ,KAAK,oBAAoB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE,CAAC;AAAA,IACpH;AAAA,EACF;AAAA,EAEQ,aAAa,KAAU,SAAkB,KAAU,QAAgC,OAA6B;AACtH,QAAI,SAAkC;AACtC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,QAAQ,QAAQ,OAAO,YAAY;AAAA,MACnC;AAAA,MACA,OAAO,IAAI;AAAA,MACX,MAAM,MAAU;AACd,mBAAW,QACR,MAAM,EACN,KAAK,EACL,KAAK,CAAC,MAAO,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAE,EACpC,MAAM,OAAO,CAAC,EAAE;AACnB,eAAO;AAAA,MACT;AAAA,MACA,OAAO,IAAI;AAAA,MACX,KAAK,IAAI;AAAA,MACT,OAAO,IAAI;AAAA,MACX,SAAS,IAAI;AAAA,MACb,KAAK,IAAI,KAAK;AAAA,MACd;AAAA,MACA,KAAK,CAAC,GAAG,MAAM,IAAI,IAAI,GAAG,CAAC;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,cAAc,KAAU,SAAkB,KAAU,QAA+C;AACjG,WAAO,EAAE,SAAS,KAAK,QAAQ,OAAO,IAAI,cAAc,OAAO,IAAI,OAAO,KAAK,IAAI,KAAK,OAAO,IAAI,OAAO,SAAS,IAAI,SAAS,KAAK,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,MAAM,IAAI,IAAI,GAAG,CAAC,EAAE;AAAA,EAChL;AAAA,EAEQ,SAAS,SAAkB,UAA8B;AAC/D,QAAI,CAAC,KAAK,KAAM,QAAO;AACvB,UAAM,SAAS,QAAQ,QAAQ,IAAI,QAAQ;AAC3C,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,UAAU,IAAI,QAAQ,SAAS,OAAO;AAC5C,YAAQ,IAAI,+BAA+B,MAAM;AACjD,YAAQ,IAAI,oCAAoC,MAAM;AACtD,YAAQ,IAAI,gCAAgC,mCAAmC;AAC/E,YAAQ,IAAI,gCAAgC,QAAQ,QAAQ,IAAI,gCAAgC,KAAK,GAAG;AACxG,YAAQ,IAAI,iCAAiC,GAAG;AAChD,YAAQ,IAAI,QAAQ,QAAQ;AAC5B,WAAO,IAAI,SAAS,SAAS,MAAM,EAAE,QAAQ,SAAS,QAAQ,YAAY,SAAS,YAAY,QAAQ,CAAC;AAAA,EAC1G;AAAA;AAAA,EAIA,MAAc,QAAQ,SAAkB,KAA6B;AACnE,UAAM,QAAQ,IAAI,SAAS,MAAM,KAAK,YAAY,MAAM,EAAE,QAAQ,OAAO,EAAE,KAAK;AAChF,UAAM,SAAS,QAAQ,OAAO,YAAY;AAC1C,UAAM,OAAO,WAAW,SAAS,WAAW,WAAW,CAAC,IAAI,MAAM,QAAQ,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,MAAO,IAAK,KAAK,MAAM,CAAC,IAAgC,CAAC,CAAE,EAAE,MAAM,OAAO,CAAC,EAA6B;AACvM,UAAM,QAAQ,OAAQ,KAA0B,OAAO,IAAI,aAAa,IAAI,KAAK,KAAK,QAAQ,QAAQ,IAAI,WAAW,KAAK,KAAK,OAAO,SAAS,SAAS,KAAK,KAAK,UAAU;AAC5K,UAAM,MAAM,KAAK;AACjB,UAAM,IAAI,CAAC,MAAc,IAAI,aAAa,IAAI,CAAC;AAC/C,UAAM,MAAM,CAAC,GAAY,MAAe,MAAM,UAAa,MAAM,QAAQ,MAAM,KAAK,IAAI,OAAO,CAAC;AAEhG,YAAQ,GAAG,MAAM,IAAI,KAAK,IAAI;AAAA,MAC5B,KAAK;AACH,eAAO,KAAK,EAAE,MAAM,0BAA0B,aAAa,KAAK,aAAa,YAAY,KAAK,YAAY,iBAAiB,KAAK,iBAAiB,MAAM,CAAC,GAAG,KAAK,KAAK,KAAK,CAAC,EAAE,CAAC;AAAA,MAChL,KAAK;AACH,eAAO,KAAK,EAAE,SAAS,KAAK,iBAAiB,WAAW,IAAI,UAAU,EAAE,CAAC;AAAA,MAC3E,KAAK;AACH,eAAO,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC;AAAA,MACrC,KAAK,gBAAgB;AACnB,cAAM,IAAI;AACV,YAAI,CAAC,EAAE,SAAU,QAAO,QAAQ,KAAK,sBAAsB;AAC3D,eAAO,KAAK,MAAM,IAAI,OAAO,OAAO,EAAE,UAAU,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,cAAc,gBAAgB,mBAAmB,EAAE,QAAQ,CAAC,yBAAyB,EAAE,CAAC;AAAA,MAChK;AAAA,MACA,KAAK;AACH,eAAO,KAAK,MAAM,IAAI,MAAM,OAAQ,KAA2B,IAAI,CAAC;AAAA,MACtE,KAAK;AACH,eAAO,KAAK,IAAI,KAAK,OAAO,IAAK,KAAyB,MAAM,EAAE,IAAI,GAAG,GAAI,CAAC,CAAC;AAAA,MACjF,KAAK;AACH,eAAO,KAAK,IAAI,MAAM,OAAO,IAAwD,CAAC;AAAA,MACxF,KAAK;AACH,eAAO,KAAK,IAAI,MAAM,OAAO,EAAE,YAAY,KAAK,MAAS,CAAC;AAAA,MAC5D,KAAK;AACH,eAAO,KAAK,IAAI,OAAO,OAAO,EAAE,OAAO,IAAI,EAAE,OAAO,GAAG,CAAC,GAAG,OAAO,IAAI,EAAE,OAAO,GAAG,GAAG,GAAG,YAAY,EAAE,YAAY,KAAK,OAAU,CAAC,CAAC;AAAA,MACrI,KAAK;AACH,eAAO,KAAK,IAAI,IAAI,OAAO,EAAE,OAAO,IAAI,EAAE,OAAO,GAAG,CAAC,GAAG,OAAO,IAAI,EAAE,OAAO,GAAG,GAAG,EAAE,CAAC,CAAC;AAAA,MACxF,KAAK;AACH,eAAO,KAAK,IAAI,QAAQ,KAAK,CAAC;AAAA,MAChC,KAAK,4BAA4B;AAC/B,cAAM,IAAI;AACV,eAAO,KAAK,IAAI,WAAW,OAAO,GAAG,CAAC,CAAC;AAAA,MACzC;AAAA,MACA,KAAK,uBAAuB;AAC1B,cAAM,IAAI;AACV,YAAI,CAAC,EAAE,GAAI,QAAO,QAAQ,KAAK,gBAAgB;AAC/C,eAAO,KAAK,EAAE,IAAI,IAAI,MAAM,OAAO,EAAE,IAAI,EAAE,UAAU,IAAI,EAAE,CAAC;AAAA,MAC9D;AAAA,MACA,KAAK,iBAAiB;AACpB,cAAM,IAAI;AACV,YAAI,CAAC,EAAE,MAAO,QAAO,QAAQ,KAAK,mBAAmB;AACrD,eAAO,KAAK,IAAI,QAAQ,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAAA,MACvD;AAAA,MACA,KAAK;AACH,eAAO,KAAK,IAAI,UAAU,KAAK,CAAC;AAAA,MAClC,KAAK,mBAAmB;AACtB,cAAM,IAAI;AACV,YAAI,CAAC,EAAE,QAAS,QAAO,QAAQ,KAAK,qBAAqB;AACzD,eAAO,KAAK,IAAI,YAAY,OAAO,CAAC,CAAC;AAAA,MACvC;AAAA,MACA,KAAK,qBAAqB;AACxB,cAAM,UAAU,EAAE,SAAS;AAC3B,cAAM,KAAK,EAAE,IAAI;AACjB,eAAO,KAAK,IAAI,eAAe,OAAO,MAAM,WAAW,QAAW,EAAE,QAAQ,KAAK,MAAS,CAAC;AAAA,MAC7F;AAAA,MACA,KAAK;AACH,eAAO,KAAK,IAAI,OAAO,OAAO,IAAwC,CAAC;AAAA,MACzE,KAAK,gBAAgB;AACnB,cAAM,IAAI;AACV,YAAI,CAAC,EAAE,KAAM,QAAO,QAAQ,KAAK,kBAAkB;AACnD,eAAO,KAAK,EAAE,QAAQ,MAAM,IAAI,OAAO,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;AAAA,MACvE;AAAA,MACA,KAAK;AACH,eAAO,KAAK,IAAI,KAAK,CAAC;AAAA,MACxB,KAAK;AACH,eAAO,KAAK,EAAE,SAAS,IAAI,UAAU,KAAK,EAAE,CAAC;AAAA,MAC/C;AACE,eAAO,QAAQ,KAAK,yBAAyB,MAAM,IAAI,KAAK,EAAE;AAAA,IAClE;AAAA,EACF;AAAA;AAAA,EAGS,MAAM;AAAA,IACb,WAAW,MACT,CAAC,GAAG,KAAK,UAAU,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,EAAE,SAAS,MAAM,aAAa,EAAE,eAAe,MAAM,MAAM,EAAE,QAAQ,EAAE,MAAM,MAAM,EAAE,QAAQ,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,GAAG,SAAS,OAAO,KAAK,EAAE,WAAW,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,KAAK,EAAE;AAAA,IACrQ,QAAQ,OAAO,QAAQ,KAAK,eAAe;AACzC,YAAM,MAAM,KAAK,KAAK,IAAI,KAAK;AAC/B,UAAI,CAAC,IAAK,QAAO,EAAE,KAAK,OAAO,UAAU,MAAM,QAAQ,OAAO,iBAAiB,KAAK,gBAAgB;AACpG,YAAM,IAAI;AACV,aAAO,EAAE,QAAQ,MAAM,GAAG,IAAI,OAAO,EAAE;AAAA,IACzC;AAAA,IACA,QAAQ,OAAO,OAAe,UAAkB,SAAkB;AAChE,YAAM,MAAM,KAAK,UAAU,OAAO,UAAU,IAAI;AAChD,YAAM,IAAI;AACV,aAAO,IAAI,OAAO;AAAA,IACpB;AAAA,IACA,OAAO,OAAO,OAAe,SAAkB;AAC7C,YAAM,WAAW,KAAK,KAAK,IAAI,KAAK;AACpC,YAAM,MAAM,KAAK,UAAU,OAAO,UAAU,SAAS,QAAQ,KAAK,iBAAiB,QAAQ,UAAU,IAAI;AACzG,YAAM,IAAI;AACV,aAAO,IAAI,OAAO;AAAA,IACpB;AAAA,IACA,MAAM,CAAC,OAAe,OAAe;AACnC,YAAM,MAAM,KAAK,QAAQ,KAAK;AAC9B,UAAI,IAAI,MAAM,SAAS,SAAU,KAAI,MAAM,QAAQ,QAAQ;AAC3D,YAAM,IAAI,IAAI,MAAM,KAAK,EAAE;AAC3B,UAAI,IAAI,QAAQ,EAAE,iBAAY,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChE,aAAO,EAAE,GAAG,GAAG,SAAS,IAAI,MAAM,QAAQ,EAAE;AAAA,IAC9C;AAAA,IACA,OAAO,CAAC,OAAe,UAA4D;AACjF,YAAM,MAAM,KAAK,QAAQ,KAAK;AAC9B,UAAI,MAAM,UAAU,OAAW,KAAI,MAAM,QAAQ,KAAK,IAAI,MAAM,OAAO,MAAM,KAAK,CAAC;AACnF,UAAI,MAAM,KAAM,KAAI,MAAM,QAAQ,MAAM,IAAI;AAC5C,aAAO,EAAE,MAAM,IAAI,MAAM,MAAM,OAAO,IAAI,MAAM,OAAO,KAAK,KAAK,MAAM,IAAI,MAAM,IAAI,CAAC,GAAG,SAAS,IAAI,MAAM,QAAQ,EAAE;AAAA,IACxH;AAAA,IACA,OAAO,CAAC,OAAe,eAAwB;AAC7C,YAAM,MAAM,KAAK,QAAQ,KAAK;AAC9B,YAAM,OAAO,IAAI,MAAM,SAAS;AAChC,aAAO,aAAa,EAAE,KAAK,OAAO,YAAY,OAAO,KAAK,UAAU,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,OAAO,QAAQ,IAAI,MAAM,OAAO,GAAG,aAAa,KAAK;AAAA,IAC9I;AAAA,IACA,QAAQ,CAAC,OAAe,SAAkE;AACxF,YAAM,MAAM,KAAK,QAAQ,KAAK;AAC9B,YAAM,SAAS,IAAI,MAAM,OAAO,IAAI;AACpC,aAAO,EAAE,KAAK,OAAO,MAAM,IAAI,MAAM,SAAS,OAAO,OAAO,QAAQ,OAAO;AAAA,IAC7E;AAAA,IACA,KAAK,CAAC,OAAe,UAA8C,EAAE,KAAK,OAAO,SAAS,KAAK,QAAQ,KAAK,EAAE,KAAK,IAAI,EAAE;AAAA,IACzH,SAAS,CAAC,UAAkB;AAC1B,YAAM,MAAM,KAAK,QAAQ,KAAK;AAC9B,aAAO,EAAE,KAAK,OAAO,aAAa,IAAI,QAAQ,KAAK,GAAG,QAAQ,IAAI,QAAQ,OAAO,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,IAAI,QAAQ,OAAO,KAAK,CAAC,EAAE,EAAE,GAAG,WAAW,IAAI,QAAQ,UAAU;AAAA,IAC3L;AAAA,IACA,YAAY,CAAC,OAAe,QAAuE,OAA2D,CAAC,MAAM;AACnK,YAAM,MAAM,KAAK,QAAQ,KAAK;AAC9B,YAAM,SAAS,IAAI,QAAQ,WAAW,QAAQ,IAAI;AAClD,UAAI,IAAI,cAAc,KAAK,UAAU,MAAM,CAAC,IAAI,EAAE,QAAQ,MAAM,KAAK,QAAQ,MAAM,CAAC;AACpF,aAAO,EAAE,OAAO;AAAA,IAClB;AAAA,IACA,OAAO,CAAC,OAAe,IAAY,WAAoB,KAAK,QAAQ,KAAK,EAAE,QAAQ,MAAM,IAAI,MAAM;AAAA,IACnG,SAAS,CAAC,OAAe,OAAe,SAAkC,KAAK,QAAQ,KAAK,EAAE,QAAQ,QAAQ,OAAO,IAAI;AAAA,IACzH,WAAW,CAAC,WAAmB,EAAE,KAAK,OAAO,WAAW,KAAK,QAAQ,KAAK,EAAE,OAAO,cAAc,EAAE;AAAA,IACnG,aAAa,CAAC,OAAe,UAAyB;AACpD,YAAM,MAAM,KAAK,QAAQ,KAAK;AAC9B,YAAM,IAAI,IAAI,OAAO,YAAY,KAAK;AACtC,UAAI,IAAI,gBAAgB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,QAAQ,EAAE,UAAU,KAAK,QAAQ,EAAE,UAAU,MAAM,OAAO,EAAE,SAAS,KAAK,CAAC;AACjI,aAAO;AAAA,IACT;AAAA,IACA,gBAAgB,CAAC,OAAe,QAAiB,WAAoB;AACnE,YAAM,MAAM,KAAK,QAAQ,KAAK;AAC9B,UAAI,OAAQ,QAAO,EAAE,SAAS,IAAI,OAAO,cAAc,QAAQ,MAAM,EAAE;AACvE,UAAI,OAAO,eAAe;AAC1B,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IACA,QAAQ,CAAC,OAAe,UAAyI;AAC/J,YAAM,MAAM,KAAK,QAAQ,KAAK;AAC9B,UAAI,OAAO,UAAU,KAAK;AAC1B,UAAI,MAAM,oBAAoB,OAAW,KAAI,QAAQ,YAAY,KAAK,IAAI,GAAG,MAAM,eAAe;AAClG,UAAI,IAAI,qBAAqB,KAAK;AAClC,aAAO,EAAE,GAAG,IAAI,OAAO,SAAS,GAAG,iBAAiB,IAAI,QAAQ,UAAU;AAAA,IAC5E;AAAA,IACA,QAAQ,CAAC,OAAe,MAAc,OAAgC,CAAC,MAAM,KAAK,QAAQ,KAAK,EAAE,OAAO,MAAM,IAAI;AAAA,IAClH,MAAM,MAAM,CAAC,GAAG,KAAK,KAAK,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,UAAU,EAAE,SAAS,MAAM,MAAM,EAAE,MAAM,UAAU,EAAE,UAAU,aAAa,EAAE,YAAY,EAAE;AAAA,IACxJ,WAAW,CAAC,UAAkB;AAC5B,YAAM,MAAM,KAAK,KAAK,IAAI,KAAK;AAC/B,UAAI,CAAC,IAAK,QAAO;AACjB,UAAI,QAAQ;AACZ,WAAK,KAAK,OAAO,KAAK;AACtB,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,QAAQ,QAAQ,KAAK,YAAiB;AAC5C,UAAM,MAAM,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,UAAU,OAAO,KAAK,eAAe;AAC9E,WAAO;AAAA,EACT;AAAA,EAEA,UAAU;AACR,eAAW,OAAO,KAAK,KAAK,OAAO,EAAG,KAAI,QAAQ;AAClD,SAAK,KAAK,MAAM;AAAA,EAClB;AACF;AAEO,SAAS,UAAU,SAAiB,UAAiD;AAC1F,QAAM,OAAiB,CAAC;AACxB,QAAM,KAAK,IAAI;AAAA,IACb,MACE,QACG,MAAM,GAAG,EACT,IAAI,CAAC,QAAQ;AACZ,UAAI,QAAQ,IAAK,QAAO;AACxB,UAAI,IAAI,WAAW,GAAG,GAAG;AACvB,aAAK,KAAK,IAAI,MAAM,CAAC,CAAC;AACtB,eAAO;AAAA,MACT;AACA,aAAO,IAAI,QAAQ,uBAAuB,MAAM;AAAA,IAClD,CAAC,EACA,KAAK,GAAG,IACX;AAAA,EACJ;AACA,QAAM,IAAI,GAAG,KAAK,QAAQ;AAC1B,MAAI,CAAC,EAAG,QAAO;AACf,QAAM,SAAiC,CAAC;AACxC,OAAK,QAAQ,CAAC,GAAG,MAAO,OAAO,CAAC,IAAI,mBAAmB,EAAE,IAAI,CAAC,KAAK,EAAE,CAAE;AACvE,SAAO;AACT;","names":["failed"]}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isUpgraded,
|
|
3
|
+
upgradedResponse
|
|
4
|
+
} from "./chunk-KU4W4SKO.js";
|
|
5
|
+
|
|
6
|
+
// src/server.ts
|
|
7
|
+
import { createServer } from "http";
|
|
8
|
+
import { WebSocketServer } from "ws";
|
|
9
|
+
function toWebRequest(req, base) {
|
|
10
|
+
const url = new URL(req.url ?? "/", base);
|
|
11
|
+
const headers = new Headers();
|
|
12
|
+
for (const [k, v] of Object.entries(req.headers)) {
|
|
13
|
+
if (Array.isArray(v)) for (const x of v) headers.append(k, x);
|
|
14
|
+
else if (v !== void 0) headers.set(k, v);
|
|
15
|
+
}
|
|
16
|
+
if (req.headers.upgrade) headers.set("x-sim-upgrade", String(req.headers.upgrade));
|
|
17
|
+
if (req.headers["sec-websocket-protocol"]) headers.set("x-sim-websocket-protocol", String(req.headers["sec-websocket-protocol"]));
|
|
18
|
+
const method = req.method ?? "GET";
|
|
19
|
+
const hasBody = method !== "GET" && method !== "HEAD";
|
|
20
|
+
const body = hasBody ? new ReadableStream({
|
|
21
|
+
start(ctl) {
|
|
22
|
+
req.on("data", (c) => ctl.enqueue(new Uint8Array(c)));
|
|
23
|
+
req.on("end", () => ctl.close());
|
|
24
|
+
req.on("error", (e) => ctl.error(e));
|
|
25
|
+
}
|
|
26
|
+
}) : null;
|
|
27
|
+
return new Request(url, { method, headers, body, ...body ? { duplex: "half" } : {} });
|
|
28
|
+
}
|
|
29
|
+
async function sendWebResponse(res, response) {
|
|
30
|
+
const headers = {};
|
|
31
|
+
response.headers.forEach((v, k) => {
|
|
32
|
+
if (k === "set-cookie") headers[k] = [...Array.isArray(headers[k]) ? headers[k] : [], v];
|
|
33
|
+
else headers[k] = v;
|
|
34
|
+
});
|
|
35
|
+
res.writeHead(response.status, response.statusText, headers);
|
|
36
|
+
if (!response.body) return void res.end();
|
|
37
|
+
const reader = response.body.getReader();
|
|
38
|
+
const pump = async () => {
|
|
39
|
+
for (; ; ) {
|
|
40
|
+
const { value, done } = await reader.read();
|
|
41
|
+
if (done) break;
|
|
42
|
+
res.write(value);
|
|
43
|
+
if (typeof res.flush === "function") res.flush();
|
|
44
|
+
}
|
|
45
|
+
res.end();
|
|
46
|
+
};
|
|
47
|
+
res.on("close", () => void reader.cancel().catch(() => {
|
|
48
|
+
}));
|
|
49
|
+
await pump().catch(() => res.end());
|
|
50
|
+
}
|
|
51
|
+
function attachWebSockets(sim, server, opts = { base: () => "http://localhost" }) {
|
|
52
|
+
const wss = new WebSocketServer({ noServer: true, handleProtocols: (protocols) => pendingProtocol ?? [...protocols][0] ?? false });
|
|
53
|
+
let pendingProtocol = null;
|
|
54
|
+
server.on("upgrade", (req, socket, head) => {
|
|
55
|
+
const url = new URL(req.url ?? "/", opts.base());
|
|
56
|
+
if (opts.match && !opts.match(url.pathname)) return;
|
|
57
|
+
const request = toWebRequest(req, opts.base());
|
|
58
|
+
const upgrade = (route, ctx, run, protocol) => new Promise((resolve) => {
|
|
59
|
+
pendingProtocol = protocol;
|
|
60
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
61
|
+
pendingProtocol = null;
|
|
62
|
+
const transport = {
|
|
63
|
+
send: (data) => ws.readyState === ws.OPEN && ws.send(data),
|
|
64
|
+
close: (code, reason) => ws.close(code, reason),
|
|
65
|
+
drop: () => ws.terminate()
|
|
66
|
+
};
|
|
67
|
+
const sock = run.streams.openSocket(route, ctx, transport, protocol);
|
|
68
|
+
ws.on("message", (data, isBinary) => run.streams.receive(route, ctx, sock, isBinary ? new Uint8Array(data).buffer : data.toString()));
|
|
69
|
+
ws.on("close", (code, reason) => run.streams.clientClosed(route, ctx, sock, code, reason.toString()));
|
|
70
|
+
resolve(upgradedResponse());
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
void sim.handle(request, { upgrade }).then((response) => {
|
|
74
|
+
if (!isUpgraded(response)) {
|
|
75
|
+
socket.write(`HTTP/1.1 ${response.status} ${response.statusText || "Error"}\r
|
|
76
|
+
content-type: application/json\r
|
|
77
|
+
connection: close\r
|
|
78
|
+
\r
|
|
79
|
+
`);
|
|
80
|
+
void response.text().then((t) => {
|
|
81
|
+
socket.write(t);
|
|
82
|
+
socket.destroy();
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
return wss;
|
|
88
|
+
}
|
|
89
|
+
async function serveSimulator(sim, options = {}) {
|
|
90
|
+
const host = options.host ?? "127.0.0.1";
|
|
91
|
+
let base = `http://${host}:${options.port ?? 0}`;
|
|
92
|
+
const server = createServer((req, res) => {
|
|
93
|
+
void sim.handle(toWebRequest(req, base)).then((response) => sendWebResponse(res, response));
|
|
94
|
+
});
|
|
95
|
+
const wss = attachWebSockets(sim, server, { base: () => base });
|
|
96
|
+
const port = await new Promise((resolve, reject) => {
|
|
97
|
+
server.once("error", reject);
|
|
98
|
+
server.listen(options.port ?? 0, host, () => {
|
|
99
|
+
const addr = server.address();
|
|
100
|
+
resolve(typeof addr === "object" && addr ? addr.port : options.port ?? 0);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
base = `http://${host}:${port}`;
|
|
104
|
+
options.log?.(`[scenario-sim] listening at ${base} control: ${base}${sim.controlPath}/status`);
|
|
105
|
+
return {
|
|
106
|
+
server,
|
|
107
|
+
port,
|
|
108
|
+
url: base,
|
|
109
|
+
controlUrl: `${base}${sim.controlPath}`,
|
|
110
|
+
close: () => new Promise((resolve) => {
|
|
111
|
+
sim.dispose();
|
|
112
|
+
for (const client of wss.clients) client.terminate();
|
|
113
|
+
wss.close();
|
|
114
|
+
let done = false;
|
|
115
|
+
const finish = () => {
|
|
116
|
+
if (done) return;
|
|
117
|
+
done = true;
|
|
118
|
+
resolve();
|
|
119
|
+
};
|
|
120
|
+
server.close(finish);
|
|
121
|
+
server.closeAllConnections?.();
|
|
122
|
+
setTimeout(finish, 500).unref?.();
|
|
123
|
+
})
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export {
|
|
128
|
+
toWebRequest,
|
|
129
|
+
sendWebResponse,
|
|
130
|
+
attachWebSockets,
|
|
131
|
+
serveSimulator
|
|
132
|
+
};
|
|
133
|
+
//# sourceMappingURL=chunk-7HBAY3QY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["/**\n * @omniaura/scenario-sim/server — run a Simulator as its own HTTP server\n * (Node or Bun; WebSocket upgrades via `ws`).\n *\n * import { serveSimulator } from \"@omniaura/scenario-sim/server\";\n * const { url } = await serveSimulator(sim, { port: 4100 });\n */\n\nimport { createServer, type IncomingMessage, type Server as HttpServer, type ServerResponse } from \"node:http\";\nimport type { Duplex } from \"node:stream\";\nimport { WebSocketServer, type WebSocket } from \"ws\";\nimport { isUpgraded, upgradedResponse, type Simulator, type UpgradeHook } from \"./core/engine.js\";\nimport type { SocketTransport } from \"./core/streams.js\";\n\nexport function toWebRequest(req: IncomingMessage, base: string): Request {\n const url = new URL(req.url ?? \"/\", base);\n const headers = new Headers();\n for (const [k, v] of Object.entries(req.headers)) {\n if (Array.isArray(v)) for (const x of v) headers.append(k, x);\n else if (v !== undefined) headers.set(k, v);\n }\n // Mirror hop-by-hop upgrade headers into names a browser-grade Request keeps.\n if (req.headers.upgrade) headers.set(\"x-sim-upgrade\", String(req.headers.upgrade));\n if (req.headers[\"sec-websocket-protocol\"]) headers.set(\"x-sim-websocket-protocol\", String(req.headers[\"sec-websocket-protocol\"]));\n const method = req.method ?? \"GET\";\n const hasBody = method !== \"GET\" && method !== \"HEAD\";\n const body = hasBody\n ? new ReadableStream<Uint8Array>({\n start(ctl) {\n req.on(\"data\", (c: Buffer) => ctl.enqueue(new Uint8Array(c)));\n req.on(\"end\", () => ctl.close());\n req.on(\"error\", (e) => ctl.error(e));\n },\n })\n : null;\n return new Request(url, { method, headers, body, ...(body ? { duplex: \"half\" } : {}) } as RequestInit);\n}\n\nexport async function sendWebResponse(res: ServerResponse, response: Response) {\n const headers: Record<string, string | string[]> = {};\n response.headers.forEach((v, k) => {\n if (k === \"set-cookie\") headers[k] = [...(Array.isArray(headers[k]) ? (headers[k] as string[]) : []), v];\n else headers[k] = v;\n });\n res.writeHead(response.status, response.statusText, headers);\n if (!response.body) return void res.end();\n const reader = response.body.getReader();\n const pump = async () => {\n for (;;) {\n const { value, done } = await reader.read();\n if (done) break;\n res.write(value);\n if (typeof (res as unknown as { flush?: () => void }).flush === \"function\") (res as unknown as { flush: () => void }).flush();\n }\n res.end();\n };\n res.on(\"close\", () => void reader.cancel().catch(() => {}));\n await pump().catch(() => res.end());\n}\n\n/**\n * Wire WebSocket upgrades on an http server to the simulator's ws routes.\n * Returns the UpgradeHook to pass into `sim.handle(request, { upgrade })`.\n */\nexport function attachWebSockets(sim: Simulator, server: HttpServer, opts: { base: () => string; match?: (pathname: string) => boolean } = { base: () => \"http://localhost\" }) {\n const wss = new WebSocketServer({ noServer: true, handleProtocols: (protocols) => (pendingProtocol ?? [...protocols][0] ?? false) as string | false });\n let pendingProtocol: string | null = null;\n server.on(\"upgrade\", (req: IncomingMessage, socket: Duplex, head: Buffer) => {\n const url = new URL(req.url ?? \"/\", opts.base());\n if (opts.match && !opts.match(url.pathname)) return;\n const request = toWebRequest(req, opts.base());\n const upgrade: UpgradeHook = (route, ctx, run, protocol) =>\n new Promise<Response>((resolve) => {\n pendingProtocol = protocol;\n wss.handleUpgrade(req, socket, head, (ws: WebSocket) => {\n pendingProtocol = null;\n const transport: SocketTransport = {\n send: (data) => ws.readyState === ws.OPEN && ws.send(data),\n close: (code, reason) => ws.close(code, reason),\n drop: () => ws.terminate(),\n };\n const sock = run.streams.openSocket(route, ctx, transport, protocol);\n ws.on(\"message\", (data, isBinary) => run.streams.receive(route, ctx, sock, isBinary ? new Uint8Array(data as Buffer).buffer : data.toString()));\n ws.on(\"close\", (code, reason) => run.streams.clientClosed(route, ctx, sock, code, reason.toString()));\n resolve(upgradedResponse());\n });\n });\n void sim.handle(request, { upgrade }).then((response) => {\n if (!isUpgraded(response)) {\n socket.write(`HTTP/1.1 ${response.status} ${response.statusText || \"Error\"}\\r\\ncontent-type: application/json\\r\\nconnection: close\\r\\n\\r\\n`);\n void response.text().then((t) => {\n socket.write(t);\n socket.destroy();\n });\n }\n });\n });\n return wss;\n}\n\nexport interface ServeOptions {\n port?: number;\n host?: string;\n log?: (line: string) => void;\n}\n\nexport async function serveSimulator(sim: Simulator, options: ServeOptions = {}) {\n const host = options.host ?? \"127.0.0.1\";\n let base = `http://${host}:${options.port ?? 0}`;\n const server = createServer((req, res) => {\n void sim.handle(toWebRequest(req, base)).then((response) => sendWebResponse(res, response));\n });\n const wss = attachWebSockets(sim, server, { base: () => base });\n const port = await new Promise<number>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(options.port ?? 0, host, () => {\n const addr = server.address();\n resolve(typeof addr === \"object\" && addr ? addr.port : (options.port ?? 0));\n });\n });\n base = `http://${host}:${port}`;\n options.log?.(`[scenario-sim] listening at ${base} control: ${base}${sim.controlPath}/status`);\n return {\n server,\n port,\n url: base,\n controlUrl: `${base}${sim.controlPath}`,\n close: () =>\n new Promise<void>((resolve) => {\n sim.dispose();\n for (const client of wss.clients) client.terminate();\n wss.close();\n let done = false;\n const finish = () => {\n if (done) return;\n done = true;\n resolve();\n };\n server.close(finish);\n // Keep-alive HTTP connections would otherwise hold `close` open until they idle out.\n (server as unknown as { closeAllConnections?: () => void }).closeAllConnections?.();\n setTimeout(finish, 500).unref?.();\n }),\n };\n}\n"],"mappings":"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","names":[]}
|