@fairfox/polly 0.85.2 → 0.86.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/dist/src/client/index.js.map +2 -2
- package/dist/src/client/wrapper.d.ts +3 -3
- package/dist/src/elysia/index.d.ts +1 -1
- package/dist/src/elysia/types.d.ts +11 -2
- package/dist/src/peer.js +30 -1
- package/dist/src/peer.js.map +3 -3
- package/dist/src/shared/lib/peer-relay-adapter.d.ts +6 -0
- package/dist/tools/test/src/browser/run.js +12 -3
- package/dist/tools/test/src/browser/run.js.map +5 -4
- package/dist/tools/test/src/e2e-mesh/index.js +43 -7
- package/dist/tools/test/src/e2e-mesh/index.js.map +6 -5
- package/dist/tools/test/src/e2e-mesh/with-relay.d.ts +1 -1
- package/dist/tools/test/src/e2e-relay/index.js.map +1 -1
- package/dist/tools/test/src/e2e-shared/ephemeral-port.d.ts +73 -0
- package/dist/tools/test/src/e2e-shared/index.d.ts +1 -0
- package/dist/tools/test/src/index.d.ts +1 -0
- package/dist/tools/test/src/index.js +43 -1
- package/dist/tools/test/src/index.js.map +4 -3
- package/dist/tools/test/src/tiers/budget.d.ts +32 -0
- package/dist/tools/test/src/tiers/cli.js +35 -5
- package/dist/tools/test/src/tiers/cli.js.map +6 -5
- package/dist/tools/test/src/tiers/index.d.ts +1 -0
- package/dist/tools/test/src/tiers/reporter.d.ts +0 -5
- package/dist/tools/test/src/tiers/types.d.ts +9 -0
- package/dist/tools/verify/specs/README.md +18 -0
- package/dist/tools/verify/specs/tla/MeshState.cfg +1 -1
- package/dist/tools/verify/specs/tla/MeshState.tla +7 -0
- package/dist/tools/verify/specs/tla/MessageRouter.cfg +4 -2
- package/dist/tools/verify/specs/tla/MessageRouter.tla +45 -10
- package/dist/tools/verify/specs/tla/PeerState.cfg +1 -1
- package/dist/tools/verify/specs/tla/PeerState.tla +7 -0
- package/dist/tools/verify/specs/tla/README.md +1 -1
- package/dist/tools/verify/src/cli.js +235 -182
- package/dist/tools/verify/src/cli.js.map +10 -9
- package/dist/tools/verify/src/config.d.ts +25 -0
- package/dist/tools/verify/src/config.js.map +2 -2
- package/dist/tools/visualize/src/cli.js +437 -45
- package/dist/tools/visualize/src/cli.js.map +7 -5
- package/package.json +1 -1
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../tools/test/src/browser/run.ts", "../src/elysia/signaling-server-plugin.ts", "../tools/test/src/browser/runner-core.ts"],
|
|
3
|
+
"sources": ["../tools/test/src/browser/run.ts", "../src/elysia/signaling-server-plugin.ts", "../tools/test/src/e2e-shared/ephemeral-port.ts", "../tools/test/src/browser/runner-core.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"#!/usr/bin/env bun\n\n/**\n * Browser test runner for Polly applications.\n *\n * Finds all *.browser.ts files in a given directory, bundles each with\n * Bun.build for the browser target (with an internal Automerge WASM fix),\n * serves the bundle on an ephemeral port, opens a Puppeteer page, and\n * polls window.__done for results. Prints pass/fail per test and exits\n * non-zero if any test failed.\n *\n * A signalling server for WebRTC tests starts automatically on a random\n * port. The URL is injected into the bundle via process.env.SIGNALING_URL.\n *\n * Usage (from project root):\n *\n * bun tools/test/src/browser/run.ts [testDir] [filter]\n *\n * Examples:\n *\n * bun tools/test/src/browser/run.ts tests/browser\n * bun tools/test/src/browser/run.ts tests/browser mesh-webrtc\n * HEADLESS=false bun tools/test/src/browser/run.ts tests/browser\n *\n * When invoked without a testDir, defaults to tests/browser relative to cwd.\n */\n\nimport { resolve } from \"node:path\";\nimport { type BunPlugin, Glob } from \"bun\";\nimport { Elysia } from \"elysia\";\nimport puppeteer, { type Page } from \"puppeteer\";\nimport { signalingServer } from \"../../../../src/elysia/signaling-server-plugin\";\nimport { errMessage, type FileTally, runSuite } from \"./runner-core\";\n\n// Automerge WASM fix\n// Bun.build's target: \"browser\" picks Automerge's fullfat_bundler.js which\n// does a static .wasm import that Bun can't wire up. Redirect to the\n// base64 variant which embeds the WASM as a string and self-initialises.\n\n// Resolve Automerge relative to polly's own install, not the runner's CWD.\n// `dist/mjs/entrypoints/fullfat_base64.js` is not in the package's `exports`\n// map, so it cannot be resolved by subpath — resolve the package entry and\n// derive the root. A CWD-relative path silently failed to exist when the\n// dependency was hoisted differently in a consumer monorepo (polly#159).\nconst automergeMarker = \"@automerge/automerge\";\nconst automergeEntry = Bun.resolveSync(automergeMarker, import.meta.dir);\nconst automergeBase64Path = resolve(\n automergeEntry.slice(0, automergeEntry.lastIndexOf(automergeMarker) + automergeMarker.length),\n \"dist/mjs/entrypoints/fullfat_base64.js\"\n);\n\nconst automergeBase64Plugin: BunPlugin = {\n name: \"automerge-base64\",\n setup(build) {\n build.onResolve({ filter: /^@automerge\\/automerge(\\/slim)?$/ }, () => {\n return { path: automergeBase64Path };\n });\n },\n};\n\n// Argument parsing\n\nconst testDir = resolve(process.cwd(), process.argv[2] ?? \"tests/browser\");\nconst filter = process.argv[3] ?? \"\";\nconst headless = process.env[\"HEADLESS\"] !== \"false\";\n\nconst glob = new Glob(\"**/*.browser.{ts,tsx}\");\nconst testFiles: string[] = [];\nfor await (const file of glob.scan({ cwd: testDir, absolute: true })) {\n if (file.includes(\"harness\")) continue;\n if (filter && !file.includes(filter)) continue;\n testFiles.push(file);\n}\n\nif (testFiles.length === 0) {\n console.log(`[browser-runner] no test files found${filter ? ` matching \"${filter}\"` : \"\"}`);\n process.exit(0);\n}\n\nconsole.log(`[browser-runner] found ${testFiles.length} test file(s)`);\n\n// Start server-side infrastructure\n\
|
|
5
|
+
"#!/usr/bin/env bun\n\n/**\n * Browser test runner for Polly applications.\n *\n * Finds all *.browser.ts files in a given directory, bundles each with\n * Bun.build for the browser target (with an internal Automerge WASM fix),\n * serves the bundle on an ephemeral port, opens a Puppeteer page, and\n * polls window.__done for results. Prints pass/fail per test and exits\n * non-zero if any test failed.\n *\n * A signalling server for WebRTC tests starts automatically on a random\n * port. The URL is injected into the bundle via process.env.SIGNALING_URL.\n *\n * Usage (from project root):\n *\n * bun tools/test/src/browser/run.ts [testDir] [filter]\n *\n * Examples:\n *\n * bun tools/test/src/browser/run.ts tests/browser\n * bun tools/test/src/browser/run.ts tests/browser mesh-webrtc\n * HEADLESS=false bun tools/test/src/browser/run.ts tests/browser\n *\n * When invoked without a testDir, defaults to tests/browser relative to cwd.\n */\n\nimport { resolve } from \"node:path\";\nimport { type BunPlugin, Glob } from \"bun\";\nimport { Elysia } from \"elysia\";\nimport puppeteer, { type Page } from \"puppeteer\";\nimport { signalingServer } from \"../../../../src/elysia/signaling-server-plugin\";\nimport { resolveListenPort } from \"../e2e-shared/ephemeral-port\";\nimport { errMessage, type FileTally, runSuite } from \"./runner-core\";\n\n// Automerge WASM fix\n// Bun.build's target: \"browser\" picks Automerge's fullfat_bundler.js which\n// does a static .wasm import that Bun can't wire up. Redirect to the\n// base64 variant which embeds the WASM as a string and self-initialises.\n\n// Resolve Automerge relative to polly's own install, not the runner's CWD.\n// `dist/mjs/entrypoints/fullfat_base64.js` is not in the package's `exports`\n// map, so it cannot be resolved by subpath — resolve the package entry and\n// derive the root. A CWD-relative path silently failed to exist when the\n// dependency was hoisted differently in a consumer monorepo (polly#159).\nconst automergeMarker = \"@automerge/automerge\";\nconst automergeEntry = Bun.resolveSync(automergeMarker, import.meta.dir);\nconst automergeBase64Path = resolve(\n automergeEntry.slice(0, automergeEntry.lastIndexOf(automergeMarker) + automergeMarker.length),\n \"dist/mjs/entrypoints/fullfat_base64.js\"\n);\n\nconst automergeBase64Plugin: BunPlugin = {\n name: \"automerge-base64\",\n setup(build) {\n build.onResolve({ filter: /^@automerge\\/automerge(\\/slim)?$/ }, () => {\n return { path: automergeBase64Path };\n });\n },\n};\n\n// Argument parsing\n\nconst testDir = resolve(process.cwd(), process.argv[2] ?? \"tests/browser\");\nconst filter = process.argv[3] ?? \"\";\nconst headless = process.env[\"HEADLESS\"] !== \"false\";\n\nconst glob = new Glob(\"**/*.browser.{ts,tsx}\");\nconst testFiles: string[] = [];\nfor await (const file of glob.scan({ cwd: testDir, absolute: true })) {\n if (file.includes(\"harness\")) continue;\n if (filter && !file.includes(filter)) continue;\n testFiles.push(file);\n}\n\nif (testFiles.length === 0) {\n console.log(`[browser-runner] no test files found${filter ? ` matching \"${filter}\"` : \"\"}`);\n process.exit(0);\n}\n\nconsole.log(`[browser-runner] found ${testFiles.length} test file(s)`);\n\n// Start server-side infrastructure\n\n// Port 0: the kernel assigns a free port and the server owns it from that\n// moment, so a second runner on the same machine cannot collide (polly#174).\nconst signalingApp = new Elysia().use(signalingServer({ path: \"/polly/signaling\" })).listen(0);\nconst signalingPort = resolveListenPort(signalingApp);\nconsole.log(`[browser-runner] signaling server on ws://127.0.0.1:${signalingPort}/polly/signaling`);\n\n// Launch browser\n//\n// No `protocolTimeout` override: results arrive via `page.exposeFunction`\n// (a push from the page over CDP `Runtime.bindingCalled` events), not via\n// polled `page.evaluate` calls. Without a long-running `Runtime.callFunctionOn`\n// on the hot path there is no protocol round-trip for a busy renderer to\n// stall, so the timeout the previous polling design had to guard against\n// is no longer reachable (polly#138).\n\nconst browser = await puppeteer.launch({\n headless,\n args: [\"--no-sandbox\", \"--disable-setuid-sandbox\"],\n});\n\n/**\n * Build, serve, and run one test file on a fresh page. Returns its\n * pass/fail tally. Build failures are reported here (not thrown);\n * a page-level uncaught error propagates so the suite records the\n * file as failed. The page and server are always cleaned up first.\n */\ninterface TestResult {\n name: string;\n passed: boolean;\n error?: string;\n}\nasync function runFile(testFile: string): Promise<FileTally> {\n const buildResult = await Bun.build({\n entrypoints: [testFile],\n target: \"browser\",\n format: \"esm\",\n minify: false,\n sourcemap: \"inline\",\n plugins: [automergeBase64Plugin],\n define: {\n \"process.env.SIGNALING_URL\": JSON.stringify(\n `ws://127.0.0.1:${signalingPort}/polly/signaling`\n ),\n },\n });\n\n if (!buildResult.success) {\n console.log(\" ❌ build failed:\");\n for (const log of buildResult.logs) {\n console.log(` ${log}`);\n }\n return { passed: 0, failed: 1 };\n }\n\n const jsText = await buildResult.outputs[0]?.text();\n if (!jsText) {\n console.log(\" ❌ build produced no output\");\n return { passed: 0, failed: 1 };\n }\n\n const html = `<!DOCTYPE html>\n<html><head><meta charset=\"utf-8\"></head>\n<body>\n<script type=\"module\">${jsText}</script>\n</body></html>`;\n\n const server = Bun.serve({\n port: 0,\n fetch() {\n return new Response(html, { headers: { \"Content-Type\": \"text/html\" } });\n },\n });\n\n let page: Page | undefined;\n try {\n const newPage = await browser.newPage();\n page = newPage;\n newPage.on(\"console\", (msg) => {\n const text = msg.text();\n if (text.includes(\"[test]\")) {\n console.log(` ${text}`);\n }\n });\n\n // Push-based reporting (polly#138): the page calls back into Node via\n // `__pollyReport(results)` when its in-page suite has finished.\n let reportResolve!: (results: TestResult[]) => void;\n let reportReject!: (err: Error) => void;\n const outcome = new Promise<TestResult[]>((resolve, reject) => {\n reportResolve = resolve;\n reportReject = reject;\n });\n\n // Wire the report channel BEFORE navigating. `exposeFunction` is async;\n // if the page were allowed to load first it could call `__pollyReport`\n // before the binding existed, and the result would be lost forever —\n // the deadlock seen when the runner's CWD was outside the test package\n // (polly#159).\n await newPage.exposeFunction(\"__pollyReport\", (results: TestResult[]) => {\n reportResolve(results);\n });\n newPage.on(\"pageerror\", (err: unknown) => {\n reportReject(err instanceof Error ? err : new Error(errMessage(err)));\n });\n\n await newPage.goto(`http://127.0.0.1:${server.port}/`, { waitUntil: \"domcontentloaded\" });\n\n // Bound the wait so a page that never reports (a swallowed error, a hung\n // renderer) fails the file instead of hanging the whole suite forever\n // (polly#159). Override via POLLY_BROWSER_TIMEOUT_MS.\n const timeoutMs = Number(process.env[\"POLLY_BROWSER_TIMEOUT_MS\"] ?? 60000);\n let timeoutTimer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timeoutTimer = setTimeout(() => {\n reject(\n new Error(\n `timed out after ${timeoutMs}ms waiting for __pollyReport — the in-page suite never reported`\n )\n );\n }, timeoutMs);\n });\n\n let results: TestResult[];\n try {\n results = await Promise.race([outcome, timeout]);\n } finally {\n if (timeoutTimer) clearTimeout(timeoutTimer);\n }\n\n let passed = 0;\n let failed = 0;\n for (const r of results) {\n if (r.passed) {\n console.log(` ✅ ${r.name}`);\n passed += 1;\n } else {\n console.log(` ❌ ${r.name}: ${r.error}`);\n failed += 1;\n }\n }\n return { passed, failed };\n } finally {\n if (page) {\n await page.close().catch(() => {\n // ignore — page may already be gone after an uncaught error\n });\n }\n server.stop();\n }\n}\n\nconst { passed: totalPassed, failed: totalFailed } = await runSuite(testFiles, runFile, {\n label: (testFile) => testFile.replace(`${testDir}/`, \"\"),\n});\n\nawait browser.close();\n(signalingApp as unknown as { server?: { stop?: (f?: boolean) => void } }).server?.stop?.(true);\n\nconsole.log(`\\n[browser-runner] ${totalPassed} passed, ${totalFailed} failed`);\nprocess.exit(totalFailed > 0 ? 1 : 0);\n",
|
|
6
6
|
"// @ts-nocheck - Optional peer dependencies (elysia, @elysiajs/eden)\n/**\n * signalingServer — Phase 2 Elysia plugin that exposes a stateless\n * WebSocket route for SDP/ICE relay between $meshState peers.\n *\n * The mesh transport is a star-of-data-channels: peers establish direct\n * WebRTC connections to each other and exchange document operations\n * peer-to-peer once those channels are open. WebRTC connection setup\n * needs an out-of-band channel for SDP offer/answer and ICE candidate\n * exchange, and that channel is what this plugin provides. The plugin\n * does not own any document state, does not hold any encryption keys,\n * and never inspects the contents of the messages it relays. It is a\n * pure pub-sub by peer id.\n *\n * Once two peers have completed the SDP exchange and opened a direct\n * data channel, the signalling server is no longer on the critical\n * path — the peers talk directly. The signalling server's role is\n * therefore intermittent: peers connect to it only during the brief\n * windows when they are establishing or re-establishing connections.\n *\n * Wire protocol:\n *\n * Client → server (join):\n * { type: \"join\", peerId: \"peer-alice\" }\n *\n * Client → server (signal to another peer):\n * { type: \"signal\", peerId: \"peer-alice\", targetPeerId: \"peer-bob\",\n * payload: { ... } }\n *\n * Server → client (delivered signal):\n * { type: \"signal\", peerId: \"peer-alice\", targetPeerId: \"peer-bob\",\n * payload: { ... } }\n *\n * Server → client (notification of unknown target):\n * { type: \"error\", reason: \"unknown-target\", targetPeerId: \"...\" }\n *\n * The `payload` is opaque to the signalling server — typically it\n * carries an SDP offer, SDP answer, or ICE candidate. Applications can\n * also use the relay for any other peer-to-peer message that needs an\n * intermediary, such as the initial handshake of a pairing flow.\n *\n * @example\n * ```ts\n * import { Elysia } from \"elysia\";\n * import { signalingServer } from \"@fairfox/polly/elysia\";\n *\n * const app = new Elysia()\n * .use(signalingServer({ path: \"/polly/signaling\" }))\n * .listen(8080);\n * ```\n */\n\nimport { Elysia } from \"elysia\";\n\n/** A signalling message. The `type` discriminates between client-to-server\n * requests (join, signal), the error envelope, and the server-to-client\n * discovery frames (peers-present, peer-joined, peer-left) that let\n * peers learn about each other without polling. */\nexport type SignalingMessage =\n | {\n type: \"join\";\n /** The peer registering itself with the signalling server. */\n peerId: string;\n }\n | {\n type: \"signal\";\n /** The peer sending the signal. */\n peerId: string;\n /** The peer the signal is being relayed to. */\n targetPeerId: string;\n /** Opaque payload, typically SDP or ICE. */\n payload: unknown;\n }\n | {\n type: \"error\";\n reason: \"unknown-target\" | \"not-joined\" | \"malformed\";\n targetPeerId?: string;\n }\n | {\n /** Sent to a newcomer immediately after it joins, listing every\n * peer that was already joined at that moment. Empty for a lone\n * newcomer. */\n type: \"peers-present\";\n peerIds: string[];\n }\n | {\n /** Broadcast to every incumbent when a new peer joins. */\n type: \"peer-joined\";\n peerId: string;\n }\n | {\n /** Broadcast to every remaining incumbent when a joined peer\n * closes its socket. Never emitted for a connection that never\n * sent a join frame. */\n type: \"peer-left\";\n peerId: string;\n };\n\n/** A frame whose `type` is outside the built-in signalling vocabulary.\n * Consumers who pass an {@link SignalingServerOptions.onCustomFrame}\n * handler receive these on the server side; everything else — including\n * routing them to a specific peer, storing a session, or rejecting the\n * frame — is the consumer's call. Polly does not touch the body. */\nexport interface CustomSignalingFrame {\n type: string;\n [key: string]: unknown;\n}\n\n/** Minimal surface the custom-frame handler receives in place of the\n * Elysia-specific `ws` object so the plugin stays portable. Exposes the\n * `data` bag (used to stash the authenticated peerId under the existing\n * join handshake) and a `send` method. */\nexport interface CustomFrameSocket {\n data: Record<string, unknown>;\n send: (msg: unknown) => void;\n}\n\nexport interface SignalingServerOptions {\n /** WebSocket route path. Defaults to \"/polly/signaling\". */\n path?: string;\n /** Optional hook for frames whose `type` is outside the built-in\n * vocabulary. The plugin invokes it in place of returning a\n * `malformed` error, so consumers can layer their own application\n * protocol (pairing return tokens, presence pings, etc.) on the\n * existing socket. The `peerId` argument is the sender's\n * authenticated peer id from their prior `join` frame, or\n * `undefined` if they haven't joined yet. */\n onCustomFrame?: (\n socket: CustomFrameSocket,\n frame: CustomSignalingFrame,\n peerId: string | undefined\n ) => void;\n}\n\n/**\n * Construct the signalling-server Elysia plugin. The plugin keeps a\n * per-instance map of peer id → WebSocket connection so that incoming\n * \"signal\" messages can be routed to the right target socket. The map\n * is local to the plugin instance, not shared across processes; for\n * multi-instance deployments behind a load balancer, applications need\n * sticky connection routing or a shared backplane (Redis pub-sub or\n * similar). That is a follow-up.\n */\nexport function signalingServer(options: SignalingServerOptions = {}) {\n const path = options.path ?? \"/polly/signaling\";\n const onCustomFrame = options.onCustomFrame;\n // Per-peer-id map of joined sockets. The inverse mapping is stored\n // directly on ws.data (a mutable property bag that Elysia preserves\n // across message callbacks for a given connection); the webrtc-p2p-chat\n // example in examples/ confirms this pattern is stable under Bun.\n const peerSockets = new Map<string, { send: (msg: unknown) => void }>();\n\n // Intentionally unnamed — Elysia deduplicates plugins by name, and each\n // signalingServer() call needs its own closure-captured peer map.\n const parseMessage = (raw: unknown): SignalingMessage | undefined => {\n try {\n return typeof raw === \"string\" ? JSON.parse(raw) : (raw as unknown as SignalingMessage);\n } catch {\n return undefined;\n }\n };\n\n const handleJoin = (ws: unknown, peerId: string): void => {\n const newcomer = ws as unknown as { send: (m: unknown) => void };\n // Collect the peers that were already joined so we can (a) tell the\n // newcomer who is present and (b) tell each of them about the\n // newcomer. A rejoin with the same peerId replaces the prior entry\n // but is otherwise treated as a fresh arrival.\n const incumbents: Array<{ peerId: string; socket: { send: (m: unknown) => void } }> = [];\n for (const [existingPeerId, existingSocket] of peerSockets) {\n if (existingPeerId === peerId) continue;\n incumbents.push({ peerId: existingPeerId, socket: existingSocket });\n }\n peerSockets.set(peerId, newcomer);\n const wsWithData = ws as unknown as { data: Record<string, unknown> };\n wsWithData.data.peerId = peerId;\n\n newcomer.send({\n type: \"peers-present\",\n peerIds: incumbents.map((i) => i.peerId),\n } as unknown as SignalingMessage);\n\n for (const incumbent of incumbents) {\n try {\n incumbent.socket.send({ type: \"peer-joined\", peerId } as unknown as SignalingMessage);\n } catch {\n // If a send fails we leave the stale socket to its own close\n // handler to evict. Dropping here would open a window where\n // the next signal to this peer still thinks it's alive.\n }\n }\n };\n\n const sendUnknownTarget = (ws: unknown, targetPeerId: string): void => {\n (ws as unknown as { send: (m: unknown) => void }).send({\n type: \"error\",\n reason: \"unknown-target\",\n targetPeerId,\n } as unknown as SignalingMessage);\n };\n\n /** Look up a target socket and confirm it is still open. */\n const findOpenTarget = (targetPeerId: string): { send: (msg: unknown) => void } | undefined => {\n const target = peerSockets.get(targetPeerId);\n if (!target) return undefined;\n const readyState = (target as unknown as { readyState?: number }).readyState;\n const OPEN = 1;\n if (readyState !== undefined && readyState !== OPEN) {\n peerSockets.delete(targetPeerId);\n return undefined;\n }\n return target;\n };\n\n const handleSignal = (ws: unknown, msg: Extract<SignalingMessage, { type: \"signal\" }>): void => {\n const wsWithData = ws as unknown as {\n data: Record<string, unknown>;\n send: (m: unknown) => void;\n };\n const senderId = wsWithData.data.peerId as unknown as string | undefined;\n if (!senderId) {\n wsWithData.send({ type: \"error\", reason: \"not-joined\" } as unknown as SignalingMessage);\n return;\n }\n const target = findOpenTarget(msg.targetPeerId);\n if (!target) {\n sendUnknownTarget(ws, msg.targetPeerId);\n return;\n }\n const relayed: SignalingMessage = {\n type: \"signal\",\n peerId: senderId,\n targetPeerId: msg.targetPeerId,\n payload: msg.payload,\n };\n try {\n target.send(relayed);\n } catch {\n peerSockets.delete(msg.targetPeerId);\n sendUnknownTarget(ws, msg.targetPeerId);\n }\n };\n\n return new Elysia().ws(path, {\n message(ws, raw) {\n const msg = parseMessage(raw);\n if (!msg) {\n ws.send({ type: \"error\", reason: \"malformed\" } as unknown as SignalingMessage);\n return;\n }\n if (msg.type === \"join\") {\n handleJoin(ws, msg.peerId);\n return;\n }\n if (msg.type === \"signal\") {\n handleSignal(ws, msg);\n return;\n }\n // Unknown types route to the consumer's custom-frame hook when\n // one is configured. Without a hook they still fall through to\n // the `malformed` error — same behaviour as before this branch\n // existed.\n if (onCustomFrame !== undefined) {\n const wsWithData = ws as unknown as CustomFrameSocket;\n const senderId = wsWithData.data[\"peerId\"];\n const peerId = typeof senderId === \"string\" ? senderId : undefined;\n onCustomFrame(wsWithData, msg as unknown as CustomSignalingFrame, peerId);\n return;\n }\n ws.send({ type: \"error\", reason: \"malformed\" } as unknown as SignalingMessage);\n },\n\n close(ws) {\n const peerId = (ws.data as unknown as Record<string, unknown>).peerId as unknown as\n | string\n | undefined;\n if (!peerId) {\n // Connection that never sent a join — nothing to broadcast and\n // nothing to evict. A bystander coming and going leaves no trace.\n return;\n }\n // Only evict if the map still points at *this* socket. A stale\n // close after the same peerId rejoined on a new socket should not\n // take the fresh entry with it. The comparison uses the `data` bag\n // Elysia attaches to each connection because it is preserved across\n // message and close callbacks, unlike the `ws` wrapper object which\n // Elysia may or may not reuse.\n const mapped = peerSockets.get(peerId);\n const wsData = (ws as unknown as { data: Record<string, unknown> }).data;\n const mappedData = (mapped as unknown as { data?: Record<string, unknown> } | undefined)\n ?.data;\n if (mapped === undefined || mappedData !== wsData) {\n return;\n }\n peerSockets.delete(peerId);\n for (const [_incumbentId, incumbentSocket] of peerSockets) {\n try {\n incumbentSocket.send({ type: \"peer-left\", peerId } as unknown as SignalingMessage);\n } catch {\n // Incumbent socket is gone; its own close handler will tidy.\n }\n }\n },\n });\n}\n",
|
|
7
|
+
"/**\n * @fairfox/polly/test — ephemeral listen ports.\n *\n * A test that draws a listen port at random from a fixed window can collide\n * with itself, with a second copy of the suite, or with any other process\n * holding a port in that window. The integration suite drew 27 ports from a\n * 10,000-port window, which is a 3.45% self-collision probability per run\n * (birthday bound, `1 - exp(-n(n-1)/2N)`) and a lower bound at that. A\n * collision fails `listen()` and reads as flake, so the natural response is a\n * retry — which narrows the window instead of removing it (polly#174).\n *\n * Port 0 asks the kernel for a free port. The server owns that port from the\n * moment it is assigned, so no other process can take it in between. These\n * helpers read the assigned port back off the two server shapes polly binds:\n *\n * - Bun/Elysia — `app.server.port`, after `.listen(0)`\n * - `ws` WebSocketServer — `wss.address().port`, after `{ port: 0 }`\n *\n * `retryOnPortInUse` covers the one case port 0 cannot: a port that must be\n * known before the server starts, such as a restart on the same port.\n */\n\n/** Elysia hangs the underlying Bun server off `.server`. */\ninterface BunServerHost {\n server?: { port?: number | null } | null;\n}\n\n/** `ws`'s WebSocketServer reports its bound address as an AddressInfo. */\ninterface AddressHost {\n address?: () => string | { port?: number | null } | null;\n}\n\n/**\n * Read the port a Bun/Elysia app was actually assigned.\n *\n * @param app An Elysia app (or any Bun server host) already `.listen(0)`-ed.\n * @throws If the app is not listening — a caller reading the port before the\n * listen resolves gets a named failure, not a URL containing `undefined`.\n *\n * @example\n * ```typescript\n * const app = new Elysia().use(signalingServer({ path })).listen(0);\n * const url = `ws://127.0.0.1:${resolveListenPort(app)}${path}`;\n * ```\n */\nexport function resolveListenPort(app: unknown): number {\n const port = (app as unknown as BunServerHost).server?.port;\n if (typeof port !== \"number\" || port <= 0) {\n throw new Error(\n `resolveListenPort: app is not listening (server.port = ${String(port)}). ` +\n \"Call .listen(0) and read the port from the returned app.\"\n );\n }\n return port;\n}\n\n/**\n * Read the port a `ws` WebSocketServer was actually assigned.\n *\n * @param wss A WebSocketServer constructed with `{ port: 0 }` and already\n * listening — `createPeerRepoServer` awaits that before it returns.\n * @throws If the server is not listening on a TCP port.\n *\n * @example\n * ```typescript\n * const server = await createPeerRepoServer({ port: 0, host: \"127.0.0.1\", storagePath });\n * const url = `ws://127.0.0.1:${resolveWebSocketPort(server.webSocketServer)}`;\n * ```\n */\nexport function resolveWebSocketPort(wss: unknown): number {\n const address = (wss as unknown as AddressHost).address?.();\n const port = typeof address === \"object\" && address !== null ? address.port : undefined;\n if (typeof port !== \"number\" || port <= 0) {\n throw new Error(\n `resolveWebSocketPort: server is not listening on a TCP port (address = ${JSON.stringify(address)}).`\n );\n }\n return port;\n}\n\n/** Bun, Node and `ws` all word an occupied-port failure differently. */\nfunction isPortInUse(error: unknown): boolean {\n if (error instanceof Error && \"code\" in error && error.code === \"EADDRINUSE\") return true;\n const message = error instanceof Error ? error.message : String(error);\n return /EADDRINUSE|address already in use|is port \\d+ in use|Failed to start server/i.test(\n message\n );\n}\n\nexport interface RetryOnPortInUseOptions {\n /** How many times to call `start` in total. Defaults to 5. */\n attempts?: number;\n /** Pause between attempts, in milliseconds. Defaults to 100. */\n delayMs?: number;\n}\n\n/**\n * Start a server on a port that is already decided, retrying a bounded number\n * of times while the port is still held.\n *\n * Only for the case port 0 cannot serve: the port must be known before the\n * server starts — a restart on the same port, or a URL handed out in advance.\n * A retry narrows the collision window rather than removing it, so prefer\n * `.listen(0)` plus {@link resolveListenPort} everywhere else.\n *\n * The final failure is the bind error itself, so the test reports \"port in\n * use\" rather than timing out on a connection to a server that never started.\n *\n * @example\n * ```typescript\n * const app = await retryOnPortInUse(() => startSignaling(port));\n * ```\n */\nexport async function retryOnPortInUse<T>(\n start: () => T | Promise<T>,\n options: RetryOnPortInUseOptions = {}\n): Promise<T> {\n const attempts = options.attempts ?? 5;\n const delayMs = options.delayMs ?? 100;\n let lastError: unknown;\n for (let attempt = 1; attempt <= attempts; attempt += 1) {\n try {\n return await start();\n } catch (error) {\n if (!isPortInUse(error)) throw error;\n lastError = error;\n if (attempt < attempts) await new Promise((r) => setTimeout(r, delayMs));\n }\n }\n throw lastError;\n}\n",
|
|
7
8
|
"/**\n * Suite orchestration for the browser test runner.\n *\n * Extracted from run.ts so the resilience guarantee — a failure in one\n * file never aborts the whole suite — is a pure function that can be\n * unit-tested without launching a browser. run.ts supplies the real\n * per-file `runFile`; the test suite supplies a fake one.\n */\n\n/** Pass/fail tally for one test file or for a whole suite. */\nexport interface FileTally {\n passed: number;\n failed: number;\n}\n\nexport function errMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * Run every test file, isolating each file's failure.\n *\n * - Any thrown error from `runFile` fails only that file and is logged.\n * - A file that returns a tally with `failed > 0` (a genuine red test)\n * is reported as-is.\n *\n * The loop never rejects: a failure in one file can never abort the\n * suite, so the remaining files always execute and report.\n */\nexport async function runSuite(\n testFiles: string[],\n runFile: (testFile: string) => Promise<FileTally>,\n options: {\n label?: (testFile: string) => string;\n log?: (msg: string) => void;\n } = {}\n): Promise<FileTally> {\n const label = options.label ?? ((f) => f);\n const log = options.log ?? console.log;\n\n let totalPassed = 0;\n let totalFailed = 0;\n\n for (const testFile of testFiles) {\n log(`\\n[browser-runner] running ${label(testFile)}`);\n\n let result: FileTally;\n try {\n result = await runFile(testFile);\n } catch (err) {\n log(` ❌ ${errMessage(err)}`);\n result = { passed: 0, failed: 1 };\n }\n\n totalPassed += result.passed;\n totalFailed += result.failed;\n }\n\n return { passed: totalPassed, failed: totalFailed };\n}\n"
|
|
8
9
|
],
|
|
9
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AA2BA;AACA;AACA,mBAAS;AACT;;;ACsBA;AA2FO,SAAS,eAAe,CAAC,UAAkC,CAAC,GAAG;AAAA,EACpE,MAAM,OAAO,QAAQ,QAAQ;AAAA,EAC7B,MAAM,gBAAgB,QAAQ;AAAA,EAK9B,MAAM,cAAc,IAAI;AAAA,EAIxB,MAAM,eAAe,CAAC,QAA+C;AAAA,IACnE,IAAI;AAAA,MACF,OAAO,OAAO,QAAQ,WAAW,KAAK,MAAM,GAAG,IAAK;AAAA,MACpD,MAAM;AAAA,MACN;AAAA;AAAA;AAAA,EAIJ,MAAM,aAAa,CAAC,IAAa,WAAyB;AAAA,IACxD,MAAM,WAAW;AAAA,IAKjB,MAAM,aAAgF,CAAC;AAAA,IACvF,YAAY,gBAAgB,mBAAmB,aAAa;AAAA,MAC1D,IAAI,mBAAmB;AAAA,QAAQ;AAAA,MAC/B,WAAW,KAAK,EAAE,QAAQ,gBAAgB,QAAQ,eAAe,CAAC;AAAA,IACpE;AAAA,IACA,YAAY,IAAI,QAAQ,QAAQ;AAAA,IAChC,MAAM,aAAa;AAAA,IACnB,WAAW,KAAK,SAAS;AAAA,IAEzB,SAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,SAAS,WAAW,IAAI,CAAC,MAAM,EAAE,MAAM;AAAA,IACzC,CAAgC;AAAA,IAEhC,WAAW,aAAa,YAAY;AAAA,MAClC,IAAI;AAAA,QACF,UAAU,OAAO,KAAK,EAAE,MAAM,eAAe,OAAO,CAAgC;AAAA,QACpF,MAAM;AAAA,IAKV;AAAA;AAAA,EAGF,MAAM,oBAAoB,CAAC,IAAa,iBAA+B;AAAA,IACpE,GAAiD,KAAK;AAAA,MACrD,MAAM;AAAA,MACN,QAAQ;AAAA,MACR;AAAA,IACF,CAAgC;AAAA;AAAA,EAIlC,MAAM,iBAAiB,CAAC,iBAAuE;AAAA,IAC7F,MAAM,SAAS,YAAY,IAAI,YAAY;AAAA,IAC3C,IAAI,CAAC;AAAA,MAAQ;AAAA,IACb,MAAM,aAAc,OAA8C;AAAA,IAClE,MAAM,OAAO;AAAA,IACb,IAAI,eAAe,aAAa,eAAe,MAAM;AAAA,MACnD,YAAY,OAAO,YAAY;AAAA,MAC/B;AAAA,IACF;AAAA,IACA,OAAO;AAAA;AAAA,EAGT,MAAM,eAAe,CAAC,IAAa,QAA6D;AAAA,IAC9F,MAAM,aAAa;AAAA,IAInB,MAAM,WAAW,WAAW,KAAK;AAAA,IACjC,IAAI,CAAC,UAAU;AAAA,MACb,WAAW,KAAK,EAAE,MAAM,SAAS,QAAQ,aAAa,CAAgC;AAAA,MACtF;AAAA,IACF;AAAA,IACA,MAAM,SAAS,eAAe,IAAI,YAAY;AAAA,IAC9C,IAAI,CAAC,QAAQ;AAAA,MACX,kBAAkB,IAAI,IAAI,YAAY;AAAA,MACtC;AAAA,IACF;AAAA,IACA,MAAM,UAA4B;AAAA,MAChC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,cAAc,IAAI;AAAA,MAClB,SAAS,IAAI;AAAA,IACf;AAAA,IACA,IAAI;AAAA,MACF,OAAO,KAAK,OAAO;AAAA,MACnB,MAAM;AAAA,MACN,YAAY,OAAO,IAAI,YAAY;AAAA,MACnC,kBAAkB,IAAI,IAAI,YAAY;AAAA;AAAA;AAAA,EAI1C,OAAO,IAAI,OAAO,EAAE,GAAG,MAAM;AAAA,IAC3B,OAAO,CAAC,IAAI,KAAK;AAAA,MACf,MAAM,MAAM,aAAa,GAAG;AAAA,MAC5B,IAAI,CAAC,KAAK;AAAA,QACR,GAAG,KAAK,EAAE,MAAM,SAAS,QAAQ,YAAY,CAAgC;AAAA,QAC7E;AAAA,MACF;AAAA,MACA,IAAI,IAAI,SAAS,QAAQ;AAAA,QACvB,WAAW,IAAI,IAAI,MAAM;AAAA,QACzB;AAAA,MACF;AAAA,MACA,IAAI,IAAI,SAAS,UAAU;AAAA,QACzB,aAAa,IAAI,GAAG;AAAA,QACpB;AAAA,MACF;AAAA,MAKA,IAAI,kBAAkB,WAAW;AAAA,QAC/B,MAAM,aAAa;AAAA,QACnB,MAAM,WAAW,WAAW,KAAK;AAAA,QACjC,MAAM,SAAS,OAAO,aAAa,WAAW,WAAW;AAAA,QACzD,cAAc,YAAY,KAAwC,MAAM;AAAA,QACxE;AAAA,MACF;AAAA,MACA,GAAG,KAAK,EAAE,MAAM,SAAS,QAAQ,YAAY,CAAgC;AAAA;AAAA,IAG/E,KAAK,CAAC,IAAI;AAAA,MACR,MAAM,SAAU,GAAG,KAA4C;AAAA,MAG/D,IAAI,CAAC,QAAQ;AAAA,QAGX;AAAA,MACF;AAAA,MAOA,MAAM,SAAS,YAAY,IAAI,MAAM;AAAA,MACrC,MAAM,SAAU,GAAoD;AAAA,MACpE,MAAM,aAAc,QAChB;AAAA,MACJ,IAAI,WAAW,aAAa,eAAe,QAAQ;AAAA,QACjD;AAAA,MACF;AAAA,MACA,YAAY,OAAO,MAAM;AAAA,MACzB,YAAY,cAAc,oBAAoB,aAAa;AAAA,QACzD,IAAI;AAAA,UACF,gBAAgB,KAAK,EAAE,MAAM,aAAa,OAAO,CAAgC;AAAA,UACjF,MAAM;AAAA,MAGV;AAAA;AAAA,EAEJ,CAAC;AAAA;;;
|
|
10
|
-
"debugId": "
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "4731421A310B38F664756E2164756E21",
|
|
11
12
|
"names": []
|
|
12
13
|
}
|
|
@@ -1184,10 +1184,47 @@ function signalingServer(options = {}) {
|
|
|
1184
1184
|
});
|
|
1185
1185
|
}
|
|
1186
1186
|
|
|
1187
|
-
// tools/test/src/e2e-
|
|
1188
|
-
function
|
|
1189
|
-
|
|
1187
|
+
// tools/test/src/e2e-shared/ephemeral-port.ts
|
|
1188
|
+
function resolveListenPort(app) {
|
|
1189
|
+
const port = app.server?.port;
|
|
1190
|
+
if (typeof port !== "number" || port <= 0) {
|
|
1191
|
+
throw new Error(`resolveListenPort: app is not listening (server.port = ${String(port)}). ` + "Call .listen(0) and read the port from the returned app.");
|
|
1192
|
+
}
|
|
1193
|
+
return port;
|
|
1194
|
+
}
|
|
1195
|
+
function resolveWebSocketPort(wss) {
|
|
1196
|
+
const address = wss.address?.();
|
|
1197
|
+
const port = typeof address === "object" && address !== null ? address.port : undefined;
|
|
1198
|
+
if (typeof port !== "number" || port <= 0) {
|
|
1199
|
+
throw new Error(`resolveWebSocketPort: server is not listening on a TCP port (address = ${JSON.stringify(address)}).`);
|
|
1200
|
+
}
|
|
1201
|
+
return port;
|
|
1202
|
+
}
|
|
1203
|
+
function isPortInUse(error) {
|
|
1204
|
+
if (error instanceof Error && "code" in error && error.code === "EADDRINUSE")
|
|
1205
|
+
return true;
|
|
1206
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1207
|
+
return /EADDRINUSE|address already in use|is port \d+ in use|Failed to start server/i.test(message);
|
|
1190
1208
|
}
|
|
1209
|
+
async function retryOnPortInUse(start, options = {}) {
|
|
1210
|
+
const attempts = options.attempts ?? 5;
|
|
1211
|
+
const delayMs = options.delayMs ?? 100;
|
|
1212
|
+
let lastError;
|
|
1213
|
+
for (let attempt = 1;attempt <= attempts; attempt += 1) {
|
|
1214
|
+
try {
|
|
1215
|
+
return await start();
|
|
1216
|
+
} catch (error) {
|
|
1217
|
+
if (!isPortInUse(error))
|
|
1218
|
+
throw error;
|
|
1219
|
+
lastError = error;
|
|
1220
|
+
if (attempt < attempts)
|
|
1221
|
+
await new Promise((r) => setTimeout(r, delayMs));
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
throw lastError;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// tools/test/src/e2e-mesh/with-relay.ts
|
|
1191
1228
|
async function withRelay(options = {}) {
|
|
1192
1229
|
const mode = options.mode ?? "embedded";
|
|
1193
1230
|
const path = options.path ?? "/polly/signaling";
|
|
@@ -1201,9 +1238,8 @@ async function withRelay(options = {}) {
|
|
|
1201
1238
|
close: async () => {}
|
|
1202
1239
|
};
|
|
1203
1240
|
}
|
|
1204
|
-
const
|
|
1205
|
-
const
|
|
1206
|
-
const url = `ws://127.0.0.1:${port}${path}`;
|
|
1241
|
+
const app = new Elysia2().use(signalingServer({ path })).listen(0);
|
|
1242
|
+
const url = `ws://127.0.0.1:${resolveListenPort(app)}${path}`;
|
|
1207
1243
|
return {
|
|
1208
1244
|
url,
|
|
1209
1245
|
close: async () => {
|
|
@@ -1227,4 +1263,4 @@ export {
|
|
|
1227
1263
|
withRelay
|
|
1228
1264
|
};
|
|
1229
1265
|
|
|
1230
|
-
//# debugId=
|
|
1266
|
+
//# debugId=4C0664CE1341DDA664756E2164756E21
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/shared/lib/encryption.ts", "node:path", "../tools/test/src/e2e-mesh/console-allowlist.ts", "../tools/test/src/e2e-mesh/keys.ts", "../src/shared/lib/signing.ts", "../tools/test/src/e2e-mesh/launch-peer.ts", "node:os", "../src/shared/lib/mesh-diagnostics.ts", "../tools/test/src/e2e-mesh/mesh-assertions.ts", "../tools/test/src/e2e-mesh/serve-consumer.ts", "../tools/test/src/e2e-shared/timeout-context.ts", "../tools/test/src/e2e-mesh/wait-for-convergence.ts", "../tools/test/src/e2e-mesh/with-relay.ts", "../src/elysia/signaling-server-plugin.ts"],
|
|
3
|
+
"sources": ["../src/shared/lib/encryption.ts", "node:path", "../tools/test/src/e2e-mesh/console-allowlist.ts", "../tools/test/src/e2e-mesh/keys.ts", "../src/shared/lib/signing.ts", "../tools/test/src/e2e-mesh/launch-peer.ts", "node:os", "../src/shared/lib/mesh-diagnostics.ts", "../tools/test/src/e2e-mesh/mesh-assertions.ts", "../tools/test/src/e2e-mesh/serve-consumer.ts", "../tools/test/src/e2e-shared/timeout-context.ts", "../tools/test/src/e2e-mesh/wait-for-convergence.ts", "../tools/test/src/e2e-mesh/with-relay.ts", "../src/elysia/signaling-server-plugin.ts", "../tools/test/src/e2e-shared/ephemeral-port.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"/**\n * encryption — symmetric authenticated encryption for Polly's $meshState\n * primitive (Phase 2). Wraps tweetnacl's secretbox (XSalsa20-Poly1305) with\n * a small Polly-flavoured API so the rest of the codebase never imports\n * tweetnacl directly.\n *\n * Every $meshState document has a per-document symmetric key that is\n * provisioned to authorised peers at pairing time and never held by any\n * server. Outgoing operations are encrypted under this key before they\n * touch the network adapter; incoming operations are decrypted on receipt.\n * The signing layer in {@link signing.ts} provides authenticity (proof of\n * who sent the message); this layer provides confidentiality (the bytes\n * are unreadable to anything that does not hold the document key).\n *\n * tweetnacl's secretbox uses a 32-byte symmetric key and a 24-byte nonce.\n * The output of `nacl.secretbox` is the ciphertext concatenated with a\n * 16-byte Poly1305 authentication tag. We package the nonce + ciphertext\n * into a single binary blob using a small length-prefixed envelope so the\n * receiver can recover the nonce without out-of-band coordination.\n *\n * - {@link generateDocumentKey} returns a fresh 32-byte symmetric key.\n *\n * - {@link encrypt} produces a sealed blob from a payload and a key.\n *\n * - {@link decrypt} recovers the payload from a sealed blob and a key.\n * Returns undefined if the blob is malformed or the authentication\n * tag does not match (i.e. wrong key or tampered ciphertext) — the\n * undefined signal lets call sites distinguish \"wrong key\" from\n * \"structurally invalid\" without throwing.\n *\n * - {@link sealEnvelope} and {@link openEnvelope} are convenience helpers\n * that wrap encrypt/decrypt in a structured EncryptedEnvelope shape so\n * the mesh transport layer can handle the binary plumbing uniformly.\n */\n\nimport nacl from \"tweetnacl\";\n\n/** Length in bytes of a secretbox symmetric key. */\nexport const KEY_BYTES = 32;\n/** Length in bytes of a secretbox nonce. */\nexport const NONCE_BYTES = 24;\n/** Length in bytes of the Poly1305 authentication tag. */\nexport const TAG_BYTES = 16;\n\n/**\n * A sealed blob suitable for storage or network transmission. The wire\n * layout is the concatenation of the nonce and the ciphertext+tag from\n * tweetnacl. Callers should not depend on the exact bytes — round-trip\n * through {@link encrypt} / {@link decrypt} or the envelope helpers.\n */\nexport type SealedBytes = Uint8Array;\n\n/** Errors thrown by the encryption subsystem. */\nexport class EncryptionError extends Error {\n readonly code: \"invalid-key-length\" | \"decrypt-failed\" | \"envelope-malformed\";\n constructor(message: string, code: EncryptionError[\"code\"]) {\n super(message);\n this.name = \"EncryptionError\";\n this.code = code;\n }\n}\n\n/**\n * Generate a fresh 32-byte symmetric document key. Calls into tweetnacl's\n * CSPRNG.\n */\nexport function generateDocumentKey(): Uint8Array {\n return nacl.randomBytes(KEY_BYTES);\n}\n\n/**\n * Encrypt a payload under a symmetric key. The returned blob includes a\n * fresh nonce so the receiver does not need any out-of-band coordination\n * to decrypt.\n */\nexport function encrypt(payload: Uint8Array, key: Uint8Array): SealedBytes {\n if (key.length !== KEY_BYTES) {\n throw new EncryptionError(\n `secretbox key must be ${KEY_BYTES} bytes, got ${key.length}.`,\n \"invalid-key-length\"\n );\n }\n const nonce = nacl.randomBytes(NONCE_BYTES);\n const ciphertext = nacl.secretbox(payload, nonce, key);\n const out = new Uint8Array(NONCE_BYTES + ciphertext.length);\n out.set(nonce, 0);\n out.set(ciphertext, NONCE_BYTES);\n return out;\n}\n\n/**\n * Decrypt a sealed blob under a symmetric key. Returns the original\n * payload on success. Returns undefined if the blob is too short to\n * contain a nonce and tag, or if the authentication tag does not match\n * (which indicates either a wrong key or a tampered ciphertext).\n *\n * The undefined return is deliberate: call sites typically want to fall\n * back to a different key or surface a \"could not decrypt\" message rather\n * than catching an exception. Use {@link decryptOrThrow} when an exception\n * is preferred.\n */\nexport function decrypt(sealed: SealedBytes, key: Uint8Array): Uint8Array | undefined {\n if (key.length !== KEY_BYTES) {\n throw new EncryptionError(\n `secretbox key must be ${KEY_BYTES} bytes, got ${key.length}.`,\n \"invalid-key-length\"\n );\n }\n if (sealed.length < NONCE_BYTES + TAG_BYTES) {\n return undefined;\n }\n const nonce = sealed.subarray(0, NONCE_BYTES);\n const ciphertext = sealed.subarray(NONCE_BYTES);\n const opened = nacl.secretbox.open(ciphertext, nonce, key);\n return opened ?? undefined;\n}\n\n/**\n * Decrypt a sealed blob, throwing {@link EncryptionError} on failure\n * instead of returning undefined.\n */\nexport function decryptOrThrow(sealed: SealedBytes, key: Uint8Array): Uint8Array {\n const opened = decrypt(sealed, key);\n if (!opened) {\n throw new EncryptionError(\n `Failed to decrypt sealed blob: wrong key, malformed input, or tampered ciphertext.`,\n \"decrypt-failed\"\n );\n }\n return opened;\n}\n\n/**\n * A high-level structured envelope combining encryption with a small\n * amount of metadata the receiver needs to find the right key. The mesh\n * network adapter uses this shape on the wire.\n */\nexport interface EncryptedEnvelope {\n /** Stable identifier for the document this payload belongs to. The\n * receiver looks this up in its local key store to find the right key. */\n documentId: string;\n /** Sealed blob containing the encrypted payload plus its nonce. */\n sealed: SealedBytes;\n}\n\n/**\n * Encrypt a payload and pack it into an {@link EncryptedEnvelope} along\n * with the document id.\n */\nexport function sealEnvelope(\n payload: Uint8Array,\n documentId: string,\n key: Uint8Array\n): EncryptedEnvelope {\n return {\n documentId,\n sealed: encrypt(payload, key),\n };\n}\n\n/**\n * Decrypt an {@link EncryptedEnvelope} using the given key. Throws on\n * failure for symmetry with {@link sealEnvelope}.\n */\nexport function openEnvelope(envelope: EncryptedEnvelope, key: Uint8Array): Uint8Array {\n return decryptOrThrow(envelope.sealed, key);\n}\n\n/**\n * Serialise an {@link EncryptedEnvelope} to a single binary blob.\n *\n * Wire format:\n *\n * [4 bytes BE: documentId byte length]\n * [N bytes: documentId UTF-8]\n * [remaining: sealed blob (nonce + ciphertext + tag)]\n */\nexport function encodeEncryptedEnvelope(envelope: EncryptedEnvelope): Uint8Array {\n const idBytes = new TextEncoder().encode(envelope.documentId);\n const out = new Uint8Array(4 + idBytes.length + envelope.sealed.length);\n const view = new DataView(out.buffer);\n view.setUint32(0, idBytes.length, false);\n out.set(idBytes, 4);\n out.set(envelope.sealed, 4 + idBytes.length);\n return out;\n}\n\n/**\n * Deserialise a binary envelope produced by {@link encodeEncryptedEnvelope}.\n * Throws on malformed input.\n */\nexport function decodeEncryptedEnvelope(bytes: Uint8Array): EncryptedEnvelope {\n if (bytes.length < 4) {\n throw new EncryptionError(\n `Encrypted envelope too short: ${bytes.length} bytes.`,\n \"envelope-malformed\"\n );\n }\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const idLen = view.getUint32(0, false);\n if (bytes.length < 4 + idLen) {\n throw new EncryptionError(\n `Encrypted envelope truncated: declared id length ${idLen}, total ${bytes.length}.`,\n \"envelope-malformed\"\n );\n }\n const documentId = new TextDecoder().decode(bytes.subarray(4, 4 + idLen));\n const sealed = bytes.slice(4 + idLen);\n return { documentId, sealed };\n}\n",
|
|
6
6
|
"function assertPath(path){if(typeof path!==\"string\")throw TypeError(\"Path must be a string. Received \"+JSON.stringify(path))}function normalizeStringPosix(path,allowAboveRoot){var res=\"\",lastSegmentLength=0,lastSlash=-1,dots=0,code;for(var i=0;i<=path.length;++i){if(i<path.length)code=path.charCodeAt(i);else if(code===47)break;else code=47;if(code===47){if(lastSlash===i-1||dots===1);else if(lastSlash!==i-1&&dots===2){if(res.length<2||lastSegmentLength!==2||res.charCodeAt(res.length-1)!==46||res.charCodeAt(res.length-2)!==46){if(res.length>2){var lastSlashIndex=res.lastIndexOf(\"/\");if(lastSlashIndex!==res.length-1){if(lastSlashIndex===-1)res=\"\",lastSegmentLength=0;else res=res.slice(0,lastSlashIndex),lastSegmentLength=res.length-1-res.lastIndexOf(\"/\");lastSlash=i,dots=0;continue}}else if(res.length===2||res.length===1){res=\"\",lastSegmentLength=0,lastSlash=i,dots=0;continue}}if(allowAboveRoot){if(res.length>0)res+=\"/..\";else res=\"..\";lastSegmentLength=2}}else{if(res.length>0)res+=\"/\"+path.slice(lastSlash+1,i);else res=path.slice(lastSlash+1,i);lastSegmentLength=i-lastSlash-1}lastSlash=i,dots=0}else if(code===46&&dots!==-1)++dots;else dots=-1}return res}function _format(sep,pathObject){var dir=pathObject.dir||pathObject.root,base=pathObject.base||(pathObject.name||\"\")+(pathObject.ext||\"\");if(!dir)return base;if(dir===pathObject.root)return dir+base;return dir+sep+base}function resolve(){var resolvedPath=\"\",resolvedAbsolute=!1,cwd;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path;if(i>=0)path=arguments[i];else{if(cwd===void 0)cwd=process.cwd();path=cwd}if(assertPath(path),path.length===0)continue;resolvedPath=path+\"/\"+resolvedPath,resolvedAbsolute=path.charCodeAt(0)===47}if(resolvedPath=normalizeStringPosix(resolvedPath,!resolvedAbsolute),resolvedAbsolute)if(resolvedPath.length>0)return\"/\"+resolvedPath;else return\"/\";else if(resolvedPath.length>0)return resolvedPath;else return\".\"}function normalize(path){if(assertPath(path),path.length===0)return\".\";var isAbsolute=path.charCodeAt(0)===47,trailingSeparator=path.charCodeAt(path.length-1)===47;if(path=normalizeStringPosix(path,!isAbsolute),path.length===0&&!isAbsolute)path=\".\";if(path.length>0&&trailingSeparator)path+=\"/\";if(isAbsolute)return\"/\"+path;return path}function isAbsolute(path){return assertPath(path),path.length>0&&path.charCodeAt(0)===47}function join(){if(arguments.length===0)return\".\";var joined;for(var i=0;i<arguments.length;++i){var arg=arguments[i];if(assertPath(arg),arg.length>0)if(joined===void 0)joined=arg;else joined+=\"/\"+arg}if(joined===void 0)return\".\";return normalize(joined)}function relative(from,to){if(assertPath(from),assertPath(to),from===to)return\"\";if(from=resolve(from),to=resolve(to),from===to)return\"\";var fromStart=1;for(;fromStart<from.length;++fromStart)if(from.charCodeAt(fromStart)!==47)break;var fromEnd=from.length,fromLen=fromEnd-fromStart,toStart=1;for(;toStart<to.length;++toStart)if(to.charCodeAt(toStart)!==47)break;var toEnd=to.length,toLen=toEnd-toStart,length=fromLen<toLen?fromLen:toLen,lastCommonSep=-1,i=0;for(;i<=length;++i){if(i===length){if(toLen>length){if(to.charCodeAt(toStart+i)===47)return to.slice(toStart+i+1);else if(i===0)return to.slice(toStart+i)}else if(fromLen>length){if(from.charCodeAt(fromStart+i)===47)lastCommonSep=i;else if(i===0)lastCommonSep=0}break}var fromCode=from.charCodeAt(fromStart+i),toCode=to.charCodeAt(toStart+i);if(fromCode!==toCode)break;else if(fromCode===47)lastCommonSep=i}var out=\"\";for(i=fromStart+lastCommonSep+1;i<=fromEnd;++i)if(i===fromEnd||from.charCodeAt(i)===47)if(out.length===0)out+=\"..\";else out+=\"/..\";if(out.length>0)return out+to.slice(toStart+lastCommonSep);else{if(toStart+=lastCommonSep,to.charCodeAt(toStart)===47)++toStart;return to.slice(toStart)}}function _makeLong(path){return path}function dirname(path){if(assertPath(path),path.length===0)return\".\";var code=path.charCodeAt(0),hasRoot=code===47,end=-1,matchedSlash=!0;for(var i=path.length-1;i>=1;--i)if(code=path.charCodeAt(i),code===47){if(!matchedSlash){end=i;break}}else matchedSlash=!1;if(end===-1)return hasRoot?\"/\":\".\";if(hasRoot&&end===1)return\"//\";return path.slice(0,end)}function basename(path,ext){if(ext!==void 0&&typeof ext!==\"string\")throw TypeError('\"ext\" argument must be a string');assertPath(path);var start=0,end=-1,matchedSlash=!0,i;if(ext!==void 0&&ext.length>0&&ext.length<=path.length){if(ext.length===path.length&&ext===path)return\"\";var extIdx=ext.length-1,firstNonSlashEnd=-1;for(i=path.length-1;i>=0;--i){var code=path.charCodeAt(i);if(code===47){if(!matchedSlash){start=i+1;break}}else{if(firstNonSlashEnd===-1)matchedSlash=!1,firstNonSlashEnd=i+1;if(extIdx>=0)if(code===ext.charCodeAt(extIdx)){if(--extIdx===-1)end=i}else extIdx=-1,end=firstNonSlashEnd}}if(start===end)end=firstNonSlashEnd;else if(end===-1)end=path.length;return path.slice(start,end)}else{for(i=path.length-1;i>=0;--i)if(path.charCodeAt(i)===47){if(!matchedSlash){start=i+1;break}}else if(end===-1)matchedSlash=!1,end=i+1;if(end===-1)return\"\";return path.slice(start,end)}}function extname(path){assertPath(path);var startDot=-1,startPart=0,end=-1,matchedSlash=!0,preDotState=0;for(var i=path.length-1;i>=0;--i){var code=path.charCodeAt(i);if(code===47){if(!matchedSlash){startPart=i+1;break}continue}if(end===-1)matchedSlash=!1,end=i+1;if(code===46){if(startDot===-1)startDot=i;else if(preDotState!==1)preDotState=1}else if(startDot!==-1)preDotState=-1}if(startDot===-1||end===-1||preDotState===0||preDotState===1&&startDot===end-1&&startDot===startPart+1)return\"\";return path.slice(startDot,end)}function format(pathObject){if(pathObject===null||typeof pathObject!==\"object\")throw TypeError('The \"pathObject\" argument must be of type Object. Received type '+typeof pathObject);return _format(\"/\",pathObject)}function parse(path){assertPath(path);var ret={root:\"\",dir:\"\",base:\"\",ext:\"\",name:\"\"};if(path.length===0)return ret;var code=path.charCodeAt(0),isAbsolute2=code===47,start;if(isAbsolute2)ret.root=\"/\",start=1;else start=0;var startDot=-1,startPart=0,end=-1,matchedSlash=!0,i=path.length-1,preDotState=0;for(;i>=start;--i){if(code=path.charCodeAt(i),code===47){if(!matchedSlash){startPart=i+1;break}continue}if(end===-1)matchedSlash=!1,end=i+1;if(code===46){if(startDot===-1)startDot=i;else if(preDotState!==1)preDotState=1}else if(startDot!==-1)preDotState=-1}if(startDot===-1||end===-1||preDotState===0||preDotState===1&&startDot===end-1&&startDot===startPart+1){if(end!==-1)if(startPart===0&&isAbsolute2)ret.base=ret.name=path.slice(1,end);else ret.base=ret.name=path.slice(startPart,end)}else{if(startPart===0&&isAbsolute2)ret.name=path.slice(1,startDot),ret.base=path.slice(1,end);else ret.name=path.slice(startPart,startDot),ret.base=path.slice(startPart,end);ret.ext=path.slice(startDot,end)}if(startPart>0)ret.dir=path.slice(0,startPart-1);else if(isAbsolute2)ret.dir=\"/\";return ret}var sep=\"/\",delimiter=\":\",posix=((p)=>(p.posix=p,p))({resolve,normalize,isAbsolute,join,relative,_makeLong,dirname,basename,extname,format,parse,sep,delimiter,win32:null,posix:null});var path_default=posix;export{sep,resolve,relative,posix,parse,normalize,join,isAbsolute,format,extname,dirname,delimiter,path_default as default,basename,_makeLong};",
|
|
@@ -14,10 +14,11 @@
|
|
|
14
14
|
"/**\n * @fairfox/polly/test/e2e-mesh — bundle and serve the e2e consumer.\n *\n * Bun.build compiles `examples/e2e-consumer/main.ts` for the browser\n * target with the Automerge base64 fix (same plugin the existing browser\n * runner uses). Bun.serve then hands the HTML on \"/\" with a bootstrap\n * shim injected, and the JS on \"/main.js\". Puppeteer points at the\n * returned URL.\n *\n * The kit owns this so every e2e script gets the same boot path: build\n * the in-tree consumer, serve from a fresh ephemeral port, inject the\n * peer-specific bootstrap. No script should call Bun.build directly —\n * keeping it in one place means the Automerge plugin and the bootstrap\n * shape stay coherent across the suite.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { BunPlugin } from \"bun\";\n\n// __dirname here is packages/polly/tools/test/src/e2e-mesh. The consumer\n// lives at packages/polly/examples/e2e-consumer so it inherits polly's\n// node_modules at bundle time; placing it at the monorepo root would\n// require it to declare its own workspace entry plus polly's runtime\n// dependencies, which is more coupling than the test deserves.\nconst pollyRoot = resolve(__dirname, \"../../../..\");\nconst consumerEntry = resolve(pollyRoot, \"examples/e2e-consumer/main.ts\");\nconst consumerHtml = resolve(pollyRoot, \"examples/e2e-consumer/index.html\");\nconst automergeBase64Path = resolve(\n pollyRoot,\n \"node_modules/@automerge/automerge/dist/mjs/entrypoints/fullfat_base64.js\"\n);\n\nconst automergeBase64Plugin: BunPlugin = {\n name: \"automerge-base64\",\n setup(build) {\n build.onResolve({ filter: /^@automerge\\/automerge(\\/slim)?$/ }, () => ({\n path: automergeBase64Path,\n }));\n },\n};\n\nexport interface ServeConsumerOptions {\n /** The bootstrap object that the page reads from window.__pollyE2eBootstrap. */\n bootstrap: Record<string, unknown>;\n}\n\nexport interface ServeConsumerResult {\n /** http://127.0.0.1:<port>/ — pass to puppeteer page.goto. */\n url: string;\n /** Stop the server. Idempotent. */\n close: () => Promise<void>;\n}\n\n/**\n * Bundle the consumer and serve it on an ephemeral port. The HTML's\n * `<script type=\"module\" src=\"./main.js\">` resolves to the freshly built\n * bundle; the bootstrap shim is inserted right before it so the global\n * is set by the time `main.ts` reads it.\n */\nexport async function serveConsumer(options: ServeConsumerOptions): Promise<ServeConsumerResult> {\n const buildResult = await Bun.build({\n entrypoints: [consumerEntry],\n target: \"browser\",\n format: \"esm\",\n minify: false,\n sourcemap: \"inline\",\n plugins: [automergeBase64Plugin],\n });\n if (!buildResult.success) {\n const logs = buildResult.logs.map((log) => String(log)).join(\"\\n\");\n throw new Error(`serveConsumer: build failed:\\n${logs}`);\n }\n const jsText = await buildResult.outputs[0]?.text();\n if (!jsText) {\n throw new Error(\"serveConsumer: build produced no output\");\n }\n\n const rawHtml = readFileSync(consumerHtml, \"utf-8\");\n const bootstrapJson = JSON.stringify(options.bootstrap);\n const bootstrapShim = `<script>window.__pollyE2eBootstrap = ${bootstrapJson};</script>`;\n const html = rawHtml.replace(\n /<script type=\"module\" src=\"\\.\\/main\\.js\"><\\/script>/,\n `${bootstrapShim}\\n <script type=\"module\" src=\"./main.js\"></script>`\n );\n\n const server = Bun.serve({\n port: 0,\n fetch(req) {\n const url = new URL(req.url);\n if (url.pathname === \"/\" || url.pathname === \"/index.html\") {\n return new Response(html, {\n headers: { \"Content-Type\": \"text/html; charset=utf-8\" },\n });\n }\n if (url.pathname === \"/main.js\") {\n return new Response(jsText, {\n headers: { \"Content-Type\": \"application/javascript; charset=utf-8\" },\n });\n }\n return new Response(\"not found\", { status: 404 });\n },\n });\n\n return {\n url: `http://127.0.0.1:${server.port}/`,\n close: async () => {\n server.stop();\n },\n };\n}\n",
|
|
15
15
|
"/**\n * @fairfox/polly/test/e2e-shared — timeout diagnostic context.\n *\n * A convergence poller that times out can only show the per-peer values it\n * was watching. That answers \"what did each peer see\" but not \"why\" — was the\n * peer ever connected to the relay, does the hub even know about the document?\n * The pollers accept an optional `context()` that a caller wires to live\n * transport state (e.g. `relayStats(server)`); it is evaluated ONLY on the\n * timeout path and appended to the failure, so a hung e2e self-diagnoses\n * instead of leaving the reader to guess.\n *\n * Borrowed from fairfox's `waitForLine(..., context)` pattern, where the relay\n * heartbeat is embedded in every timeout so the error pinpoints sync state.\n */\n\n/** Evaluate a timeout-only diagnostic context, never letting it throw — a\n * broken context must not mask the real timeout it is trying to explain. */\nexport async function resolveContext(\n context: (() => string | Promise<string>) | undefined\n): Promise<string> {\n if (!context) return \"\";\n try {\n return `\\n\\ntransport: ${await context()}`;\n } catch (err) {\n return `\\n\\ntransport: <context threw: ${err instanceof Error ? err.message : String(err)}>`;\n }\n}\n",
|
|
16
16
|
"/**\n * @fairfox/polly/test/e2e-mesh — waitForConvergence.\n *\n * Polls a consumer-supplied predicate against every launched peer until\n * the predicate returns true on all of them, or the timeout expires.\n * The predicate runs in the *node* side (the script) and is handed a\n * snapshot reader function that reads from the peer's page DOM.\n *\n * Typical use: assert every peer's `[data-e2e='items']` UL contains the\n * expected set of values.\n */\n\nimport { resolveContext } from \"../e2e-shared/timeout-context\";\nimport type { LaunchedPeer } from \"./launch-peer\";\n\nexport interface PeerSnapshot {\n peerId: string;\n /** Items currently rendered in the consumer's [data-e2e='items'] list. */\n items: string[];\n /** Connected peer count reported by the consumer. */\n peerCount: number;\n /** Status text the consumer currently displays. */\n status: string;\n}\n\nexport type ConvergencePredicate = (snapshot: PeerSnapshot) => boolean;\n\nexport interface WaitForConvergenceOptions {\n /** Cap wait time before throwing. Defaults to 20s. */\n timeoutMs?: number;\n /** Poll interval. Defaults to 200ms. */\n pollMs?: number;\n /**\n * Optional one-line diagnostic snapshot, evaluated ONLY on timeout and\n * appended to the failure. Use it to surface transport state the per-peer\n * DOM snapshot can't show — signaling-relay connections, doc count, etc. A\n * throwing or rejecting context is swallowed so it can never mask the real\n * timeout.\n */\n context?: () => string | Promise<string>;\n}\n\nasync function readPeerSnapshot(peer: LaunchedPeer): Promise<PeerSnapshot> {\n return peer.page\n .evaluate(() => {\n const itemEls = Array.from(document.querySelectorAll(\"[data-e2e-item]\"));\n const items = itemEls.map((el) => el.textContent ?? \"\");\n const peerCountText = document.querySelector(\"[data-e2e='peer-count']\")?.textContent ?? \"0\";\n const status = document.querySelector(\"[data-e2e='status']\")?.textContent ?? \"\";\n return { items, peerCount: Number(peerCountText) || 0, status };\n })\n .then((data) => ({ peerId: peer.peerId, ...data }));\n}\n\n/**\n * Block until the predicate is true for every peer, or throw.\n */\nexport async function waitForConvergence(\n peers: ReadonlyArray<LaunchedPeer>,\n predicate: ConvergencePredicate,\n options: WaitForConvergenceOptions = {}\n): Promise<void> {\n const { timeoutMs = 20_000, pollMs = 200 } = options;\n const deadline = Date.now() + timeoutMs;\n let lastSnapshots: PeerSnapshot[] = [];\n\n while (Date.now() < deadline) {\n const snapshots = await Promise.all(peers.map(readPeerSnapshot));\n lastSnapshots = snapshots;\n if (snapshots.every(predicate)) return;\n await new Promise((r) => setTimeout(r, pollMs));\n }\n\n const summary = lastSnapshots\n .map(\n (s) =>\n ` ${s.peerId}: status=\"${s.status}\" peerCount=${s.peerCount} items=${JSON.stringify(s.items)}`\n )\n .join(\"\\n\");\n const transport = await resolveContext(options.context);\n throw new Error(\n `waitForConvergence: predicate did not hold for every peer within ${timeoutMs}ms.\\n${summary}${transport}`\n );\n}\n\n/**\n * Convenience: wait until every peer reports it sees at least N connected\n * peers. Used right after launching to confirm the WebRTC handshake\n * completed before driving any user-facing flow.\n */\nexport async function waitForMeshConnected(\n peers: ReadonlyArray<LaunchedPeer>,\n options: WaitForConvergenceOptions = {}\n): Promise<void> {\n const minPeers = peers.length - 1;\n await waitForConvergence(peers, (snapshot) => snapshot.peerCount >= minPeers, options);\n}\n",
|
|
17
|
-
"/**\n * @fairfox/polly/test/e2e-mesh — withRelay helper.\n *\n * Boots a polly signalling relay on an ephemeral port for e2e scripts.\n * The relay is the same Elysia plugin polly ships at runtime, so a script\n * driving the relay through `withRelay` exercises the production protocol\n * with no shimming. Two modes:\n *\n * - \"embedded\" (default): start an Elysia app on a
|
|
18
|
-
"// @ts-nocheck - Optional peer dependencies (elysia, @elysiajs/eden)\n/**\n * signalingServer — Phase 2 Elysia plugin that exposes a stateless\n * WebSocket route for SDP/ICE relay between $meshState peers.\n *\n * The mesh transport is a star-of-data-channels: peers establish direct\n * WebRTC connections to each other and exchange document operations\n * peer-to-peer once those channels are open. WebRTC connection setup\n * needs an out-of-band channel for SDP offer/answer and ICE candidate\n * exchange, and that channel is what this plugin provides. The plugin\n * does not own any document state, does not hold any encryption keys,\n * and never inspects the contents of the messages it relays. It is a\n * pure pub-sub by peer id.\n *\n * Once two peers have completed the SDP exchange and opened a direct\n * data channel, the signalling server is no longer on the critical\n * path — the peers talk directly. The signalling server's role is\n * therefore intermittent: peers connect to it only during the brief\n * windows when they are establishing or re-establishing connections.\n *\n * Wire protocol:\n *\n * Client → server (join):\n * { type: \"join\", peerId: \"peer-alice\" }\n *\n * Client → server (signal to another peer):\n * { type: \"signal\", peerId: \"peer-alice\", targetPeerId: \"peer-bob\",\n * payload: { ... } }\n *\n * Server → client (delivered signal):\n * { type: \"signal\", peerId: \"peer-alice\", targetPeerId: \"peer-bob\",\n * payload: { ... } }\n *\n * Server → client (notification of unknown target):\n * { type: \"error\", reason: \"unknown-target\", targetPeerId: \"...\" }\n *\n * The `payload` is opaque to the signalling server — typically it\n * carries an SDP offer, SDP answer, or ICE candidate. Applications can\n * also use the relay for any other peer-to-peer message that needs an\n * intermediary, such as the initial handshake of a pairing flow.\n *\n * @example\n * ```ts\n * import { Elysia } from \"elysia\";\n * import { signalingServer } from \"@fairfox/polly/elysia\";\n *\n * const app = new Elysia()\n * .use(signalingServer({ path: \"/polly/signaling\" }))\n * .listen(8080);\n * ```\n */\n\nimport { Elysia } from \"elysia\";\n\n/** A signalling message. The `type` discriminates between client-to-server\n * requests (join, signal), the error envelope, and the server-to-client\n * discovery frames (peers-present, peer-joined, peer-left) that let\n * peers learn about each other without polling. */\nexport type SignalingMessage =\n | {\n type: \"join\";\n /** The peer registering itself with the signalling server. */\n peerId: string;\n }\n | {\n type: \"signal\";\n /** The peer sending the signal. */\n peerId: string;\n /** The peer the signal is being relayed to. */\n targetPeerId: string;\n /** Opaque payload, typically SDP or ICE. */\n payload: unknown;\n }\n | {\n type: \"error\";\n reason: \"unknown-target\" | \"not-joined\" | \"malformed\";\n targetPeerId?: string;\n }\n | {\n /** Sent to a newcomer immediately after it joins, listing every\n * peer that was already joined at that moment. Empty for a lone\n * newcomer. */\n type: \"peers-present\";\n peerIds: string[];\n }\n | {\n /** Broadcast to every incumbent when a new peer joins. */\n type: \"peer-joined\";\n peerId: string;\n }\n | {\n /** Broadcast to every remaining incumbent when a joined peer\n * closes its socket. Never emitted for a connection that never\n * sent a join frame. */\n type: \"peer-left\";\n peerId: string;\n };\n\n/** A frame whose `type` is outside the built-in signalling vocabulary.\n * Consumers who pass an {@link SignalingServerOptions.onCustomFrame}\n * handler receive these on the server side; everything else — including\n * routing them to a specific peer, storing a session, or rejecting the\n * frame — is the consumer's call. Polly does not touch the body. */\nexport interface CustomSignalingFrame {\n type: string;\n [key: string]: unknown;\n}\n\n/** Minimal surface the custom-frame handler receives in place of the\n * Elysia-specific `ws` object so the plugin stays portable. Exposes the\n * `data` bag (used to stash the authenticated peerId under the existing\n * join handshake) and a `send` method. */\nexport interface CustomFrameSocket {\n data: Record<string, unknown>;\n send: (msg: unknown) => void;\n}\n\nexport interface SignalingServerOptions {\n /** WebSocket route path. Defaults to \"/polly/signaling\". */\n path?: string;\n /** Optional hook for frames whose `type` is outside the built-in\n * vocabulary. The plugin invokes it in place of returning a\n * `malformed` error, so consumers can layer their own application\n * protocol (pairing return tokens, presence pings, etc.) on the\n * existing socket. The `peerId` argument is the sender's\n * authenticated peer id from their prior `join` frame, or\n * `undefined` if they haven't joined yet. */\n onCustomFrame?: (\n socket: CustomFrameSocket,\n frame: CustomSignalingFrame,\n peerId: string | undefined\n ) => void;\n}\n\n/**\n * Construct the signalling-server Elysia plugin. The plugin keeps a\n * per-instance map of peer id → WebSocket connection so that incoming\n * \"signal\" messages can be routed to the right target socket. The map\n * is local to the plugin instance, not shared across processes; for\n * multi-instance deployments behind a load balancer, applications need\n * sticky connection routing or a shared backplane (Redis pub-sub or\n * similar). That is a follow-up.\n */\nexport function signalingServer(options: SignalingServerOptions = {}) {\n const path = options.path ?? \"/polly/signaling\";\n const onCustomFrame = options.onCustomFrame;\n // Per-peer-id map of joined sockets. The inverse mapping is stored\n // directly on ws.data (a mutable property bag that Elysia preserves\n // across message callbacks for a given connection); the webrtc-p2p-chat\n // example in examples/ confirms this pattern is stable under Bun.\n const peerSockets = new Map<string, { send: (msg: unknown) => void }>();\n\n // Intentionally unnamed — Elysia deduplicates plugins by name, and each\n // signalingServer() call needs its own closure-captured peer map.\n const parseMessage = (raw: unknown): SignalingMessage | undefined => {\n try {\n return typeof raw === \"string\" ? JSON.parse(raw) : (raw as unknown as SignalingMessage);\n } catch {\n return undefined;\n }\n };\n\n const handleJoin = (ws: unknown, peerId: string): void => {\n const newcomer = ws as unknown as { send: (m: unknown) => void };\n // Collect the peers that were already joined so we can (a) tell the\n // newcomer who is present and (b) tell each of them about the\n // newcomer. A rejoin with the same peerId replaces the prior entry\n // but is otherwise treated as a fresh arrival.\n const incumbents: Array<{ peerId: string; socket: { send: (m: unknown) => void } }> = [];\n for (const [existingPeerId, existingSocket] of peerSockets) {\n if (existingPeerId === peerId) continue;\n incumbents.push({ peerId: existingPeerId, socket: existingSocket });\n }\n peerSockets.set(peerId, newcomer);\n const wsWithData = ws as unknown as { data: Record<string, unknown> };\n wsWithData.data.peerId = peerId;\n\n newcomer.send({\n type: \"peers-present\",\n peerIds: incumbents.map((i) => i.peerId),\n } as unknown as SignalingMessage);\n\n for (const incumbent of incumbents) {\n try {\n incumbent.socket.send({ type: \"peer-joined\", peerId } as unknown as SignalingMessage);\n } catch {\n // If a send fails we leave the stale socket to its own close\n // handler to evict. Dropping here would open a window where\n // the next signal to this peer still thinks it's alive.\n }\n }\n };\n\n const sendUnknownTarget = (ws: unknown, targetPeerId: string): void => {\n (ws as unknown as { send: (m: unknown) => void }).send({\n type: \"error\",\n reason: \"unknown-target\",\n targetPeerId,\n } as unknown as SignalingMessage);\n };\n\n /** Look up a target socket and confirm it is still open. */\n const findOpenTarget = (targetPeerId: string): { send: (msg: unknown) => void } | undefined => {\n const target = peerSockets.get(targetPeerId);\n if (!target) return undefined;\n const readyState = (target as unknown as { readyState?: number }).readyState;\n const OPEN = 1;\n if (readyState !== undefined && readyState !== OPEN) {\n peerSockets.delete(targetPeerId);\n return undefined;\n }\n return target;\n };\n\n const handleSignal = (ws: unknown, msg: Extract<SignalingMessage, { type: \"signal\" }>): void => {\n const wsWithData = ws as unknown as {\n data: Record<string, unknown>;\n send: (m: unknown) => void;\n };\n const senderId = wsWithData.data.peerId as unknown as string | undefined;\n if (!senderId) {\n wsWithData.send({ type: \"error\", reason: \"not-joined\" } as unknown as SignalingMessage);\n return;\n }\n const target = findOpenTarget(msg.targetPeerId);\n if (!target) {\n sendUnknownTarget(ws, msg.targetPeerId);\n return;\n }\n const relayed: SignalingMessage = {\n type: \"signal\",\n peerId: senderId,\n targetPeerId: msg.targetPeerId,\n payload: msg.payload,\n };\n try {\n target.send(relayed);\n } catch {\n peerSockets.delete(msg.targetPeerId);\n sendUnknownTarget(ws, msg.targetPeerId);\n }\n };\n\n return new Elysia().ws(path, {\n message(ws, raw) {\n const msg = parseMessage(raw);\n if (!msg) {\n ws.send({ type: \"error\", reason: \"malformed\" } as unknown as SignalingMessage);\n return;\n }\n if (msg.type === \"join\") {\n handleJoin(ws, msg.peerId);\n return;\n }\n if (msg.type === \"signal\") {\n handleSignal(ws, msg);\n return;\n }\n // Unknown types route to the consumer's custom-frame hook when\n // one is configured. Without a hook they still fall through to\n // the `malformed` error — same behaviour as before this branch\n // existed.\n if (onCustomFrame !== undefined) {\n const wsWithData = ws as unknown as CustomFrameSocket;\n const senderId = wsWithData.data[\"peerId\"];\n const peerId = typeof senderId === \"string\" ? senderId : undefined;\n onCustomFrame(wsWithData, msg as unknown as CustomSignalingFrame, peerId);\n return;\n }\n ws.send({ type: \"error\", reason: \"malformed\" } as unknown as SignalingMessage);\n },\n\n close(ws) {\n const peerId = (ws.data as unknown as Record<string, unknown>).peerId as unknown as\n | string\n | undefined;\n if (!peerId) {\n // Connection that never sent a join — nothing to broadcast and\n // nothing to evict. A bystander coming and going leaves no trace.\n return;\n }\n // Only evict if the map still points at *this* socket. A stale\n // close after the same peerId rejoined on a new socket should not\n // take the fresh entry with it. The comparison uses the `data` bag\n // Elysia attaches to each connection because it is preserved across\n // message and close callbacks, unlike the `ws` wrapper object which\n // Elysia may or may not reuse.\n const mapped = peerSockets.get(peerId);\n const wsData = (ws as unknown as { data: Record<string, unknown> }).data;\n const mappedData = (mapped as unknown as { data?: Record<string, unknown> } | undefined)\n ?.data;\n if (mapped === undefined || mappedData !== wsData) {\n return;\n }\n peerSockets.delete(peerId);\n for (const [_incumbentId, incumbentSocket] of peerSockets) {\n try {\n incumbentSocket.send({ type: \"peer-left\", peerId } as unknown as SignalingMessage);\n } catch {\n // Incumbent socket is gone; its own close handler will tidy.\n }\n }\n },\n });\n}\n"
|
|
17
|
+
"/**\n * @fairfox/polly/test/e2e-mesh — withRelay helper.\n *\n * Boots a polly signalling relay on an ephemeral port for e2e scripts.\n * The relay is the same Elysia plugin polly ships at runtime, so a script\n * driving the relay through `withRelay` exercises the production protocol\n * with no shimming. Two modes:\n *\n * - \"embedded\" (default): start an Elysia app on a kernel-assigned port and return\n * its URL plus a close callback. The hermetic mode the suite runs in\n * by default; depending on a staging relay would couple CI reliability\n * to a network service we do not control.\n *\n * - \"env\": read SIGNALING_URL from the environment and return that\n * alongside a no-op close. The override the nightly cron uses to smoke\n * the production protocol against the live relay.\n *\n * Lift source: tests/integration/signaling-server.test.ts is the existing\n * recipe; this helper centralises it so every e2e script wires the relay\n * the same way.\n */\n\nimport { Elysia } from \"elysia\";\nimport { signalingServer } from \"../../../../src/elysia/signaling-server-plugin\";\nimport { resolveListenPort } from \"../e2e-shared/ephemeral-port\";\n\nexport interface WithRelayResult {\n /** WebSocket URL of the signalling endpoint, ready to be passed to\n * `createMeshClient({ signaling: { url, peerId } })`. */\n url: string;\n /** Stop the relay. Idempotent; safe to call after a failed boot. */\n close: () => Promise<void>;\n}\n\nexport interface WithRelayOptions {\n /**\n * \"embedded\" boots a fresh relay on an ephemeral port and returns its\n * URL. \"env\" reads SIGNALING_URL from the environment and returns it\n * without booting anything. Defaults to \"embedded\".\n */\n mode?: \"embedded\" | \"env\";\n /** Path under which the signalling endpoint is mounted. Defaults to\n * \"/polly/signaling\" — the same default the SPA wiring uses. */\n path?: string;\n}\n\n/**\n * Start a signalling relay for the duration of an e2e script.\n *\n * @example\n * ```typescript\n * const relay = await withRelay();\n * try {\n * // boot peers pointing signaling.url at relay.url ...\n * } finally {\n * await relay.close();\n * }\n * ```\n */\nexport async function withRelay(options: WithRelayOptions = {}): Promise<WithRelayResult> {\n const mode = options.mode ?? \"embedded\";\n const path = options.path ?? \"/polly/signaling\";\n\n if (mode === \"env\") {\n const url = process.env[\"SIGNALING_URL\"];\n if (!url) {\n throw new Error(\n \"withRelay({ mode: 'env' }) requires SIGNALING_URL to be set in the environment.\"\n );\n }\n return {\n url,\n close: async () => {\n // env mode doesn't own a server, so close is a no-op.\n },\n };\n }\n\n // Port 0: the kernel assigns a free port and the relay owns it from that\n // moment, so no collision window exists for another process to win\n // (polly#174).\n const app = new Elysia().use(signalingServer({ path })).listen(0);\n const url = `ws://127.0.0.1:${resolveListenPort(app)}${path}`;\n\n return {\n url,\n close: async () => {\n // Elysia exposes the underlying Bun server here. The .stop(true)\n // force-closes any open connections so a hung peer cannot keep the\n // server alive past the script's intended lifetime.\n (\n app as unknown as {\n server?: { stop?: (force?: boolean) => void };\n }\n ).server?.stop?.(true);\n },\n };\n}\n",
|
|
18
|
+
"// @ts-nocheck - Optional peer dependencies (elysia, @elysiajs/eden)\n/**\n * signalingServer — Phase 2 Elysia plugin that exposes a stateless\n * WebSocket route for SDP/ICE relay between $meshState peers.\n *\n * The mesh transport is a star-of-data-channels: peers establish direct\n * WebRTC connections to each other and exchange document operations\n * peer-to-peer once those channels are open. WebRTC connection setup\n * needs an out-of-band channel for SDP offer/answer and ICE candidate\n * exchange, and that channel is what this plugin provides. The plugin\n * does not own any document state, does not hold any encryption keys,\n * and never inspects the contents of the messages it relays. It is a\n * pure pub-sub by peer id.\n *\n * Once two peers have completed the SDP exchange and opened a direct\n * data channel, the signalling server is no longer on the critical\n * path — the peers talk directly. The signalling server's role is\n * therefore intermittent: peers connect to it only during the brief\n * windows when they are establishing or re-establishing connections.\n *\n * Wire protocol:\n *\n * Client → server (join):\n * { type: \"join\", peerId: \"peer-alice\" }\n *\n * Client → server (signal to another peer):\n * { type: \"signal\", peerId: \"peer-alice\", targetPeerId: \"peer-bob\",\n * payload: { ... } }\n *\n * Server → client (delivered signal):\n * { type: \"signal\", peerId: \"peer-alice\", targetPeerId: \"peer-bob\",\n * payload: { ... } }\n *\n * Server → client (notification of unknown target):\n * { type: \"error\", reason: \"unknown-target\", targetPeerId: \"...\" }\n *\n * The `payload` is opaque to the signalling server — typically it\n * carries an SDP offer, SDP answer, or ICE candidate. Applications can\n * also use the relay for any other peer-to-peer message that needs an\n * intermediary, such as the initial handshake of a pairing flow.\n *\n * @example\n * ```ts\n * import { Elysia } from \"elysia\";\n * import { signalingServer } from \"@fairfox/polly/elysia\";\n *\n * const app = new Elysia()\n * .use(signalingServer({ path: \"/polly/signaling\" }))\n * .listen(8080);\n * ```\n */\n\nimport { Elysia } from \"elysia\";\n\n/** A signalling message. The `type` discriminates between client-to-server\n * requests (join, signal), the error envelope, and the server-to-client\n * discovery frames (peers-present, peer-joined, peer-left) that let\n * peers learn about each other without polling. */\nexport type SignalingMessage =\n | {\n type: \"join\";\n /** The peer registering itself with the signalling server. */\n peerId: string;\n }\n | {\n type: \"signal\";\n /** The peer sending the signal. */\n peerId: string;\n /** The peer the signal is being relayed to. */\n targetPeerId: string;\n /** Opaque payload, typically SDP or ICE. */\n payload: unknown;\n }\n | {\n type: \"error\";\n reason: \"unknown-target\" | \"not-joined\" | \"malformed\";\n targetPeerId?: string;\n }\n | {\n /** Sent to a newcomer immediately after it joins, listing every\n * peer that was already joined at that moment. Empty for a lone\n * newcomer. */\n type: \"peers-present\";\n peerIds: string[];\n }\n | {\n /** Broadcast to every incumbent when a new peer joins. */\n type: \"peer-joined\";\n peerId: string;\n }\n | {\n /** Broadcast to every remaining incumbent when a joined peer\n * closes its socket. Never emitted for a connection that never\n * sent a join frame. */\n type: \"peer-left\";\n peerId: string;\n };\n\n/** A frame whose `type` is outside the built-in signalling vocabulary.\n * Consumers who pass an {@link SignalingServerOptions.onCustomFrame}\n * handler receive these on the server side; everything else — including\n * routing them to a specific peer, storing a session, or rejecting the\n * frame — is the consumer's call. Polly does not touch the body. */\nexport interface CustomSignalingFrame {\n type: string;\n [key: string]: unknown;\n}\n\n/** Minimal surface the custom-frame handler receives in place of the\n * Elysia-specific `ws` object so the plugin stays portable. Exposes the\n * `data` bag (used to stash the authenticated peerId under the existing\n * join handshake) and a `send` method. */\nexport interface CustomFrameSocket {\n data: Record<string, unknown>;\n send: (msg: unknown) => void;\n}\n\nexport interface SignalingServerOptions {\n /** WebSocket route path. Defaults to \"/polly/signaling\". */\n path?: string;\n /** Optional hook for frames whose `type` is outside the built-in\n * vocabulary. The plugin invokes it in place of returning a\n * `malformed` error, so consumers can layer their own application\n * protocol (pairing return tokens, presence pings, etc.) on the\n * existing socket. The `peerId` argument is the sender's\n * authenticated peer id from their prior `join` frame, or\n * `undefined` if they haven't joined yet. */\n onCustomFrame?: (\n socket: CustomFrameSocket,\n frame: CustomSignalingFrame,\n peerId: string | undefined\n ) => void;\n}\n\n/**\n * Construct the signalling-server Elysia plugin. The plugin keeps a\n * per-instance map of peer id → WebSocket connection so that incoming\n * \"signal\" messages can be routed to the right target socket. The map\n * is local to the plugin instance, not shared across processes; for\n * multi-instance deployments behind a load balancer, applications need\n * sticky connection routing or a shared backplane (Redis pub-sub or\n * similar). That is a follow-up.\n */\nexport function signalingServer(options: SignalingServerOptions = {}) {\n const path = options.path ?? \"/polly/signaling\";\n const onCustomFrame = options.onCustomFrame;\n // Per-peer-id map of joined sockets. The inverse mapping is stored\n // directly on ws.data (a mutable property bag that Elysia preserves\n // across message callbacks for a given connection); the webrtc-p2p-chat\n // example in examples/ confirms this pattern is stable under Bun.\n const peerSockets = new Map<string, { send: (msg: unknown) => void }>();\n\n // Intentionally unnamed — Elysia deduplicates plugins by name, and each\n // signalingServer() call needs its own closure-captured peer map.\n const parseMessage = (raw: unknown): SignalingMessage | undefined => {\n try {\n return typeof raw === \"string\" ? JSON.parse(raw) : (raw as unknown as SignalingMessage);\n } catch {\n return undefined;\n }\n };\n\n const handleJoin = (ws: unknown, peerId: string): void => {\n const newcomer = ws as unknown as { send: (m: unknown) => void };\n // Collect the peers that were already joined so we can (a) tell the\n // newcomer who is present and (b) tell each of them about the\n // newcomer. A rejoin with the same peerId replaces the prior entry\n // but is otherwise treated as a fresh arrival.\n const incumbents: Array<{ peerId: string; socket: { send: (m: unknown) => void } }> = [];\n for (const [existingPeerId, existingSocket] of peerSockets) {\n if (existingPeerId === peerId) continue;\n incumbents.push({ peerId: existingPeerId, socket: existingSocket });\n }\n peerSockets.set(peerId, newcomer);\n const wsWithData = ws as unknown as { data: Record<string, unknown> };\n wsWithData.data.peerId = peerId;\n\n newcomer.send({\n type: \"peers-present\",\n peerIds: incumbents.map((i) => i.peerId),\n } as unknown as SignalingMessage);\n\n for (const incumbent of incumbents) {\n try {\n incumbent.socket.send({ type: \"peer-joined\", peerId } as unknown as SignalingMessage);\n } catch {\n // If a send fails we leave the stale socket to its own close\n // handler to evict. Dropping here would open a window where\n // the next signal to this peer still thinks it's alive.\n }\n }\n };\n\n const sendUnknownTarget = (ws: unknown, targetPeerId: string): void => {\n (ws as unknown as { send: (m: unknown) => void }).send({\n type: \"error\",\n reason: \"unknown-target\",\n targetPeerId,\n } as unknown as SignalingMessage);\n };\n\n /** Look up a target socket and confirm it is still open. */\n const findOpenTarget = (targetPeerId: string): { send: (msg: unknown) => void } | undefined => {\n const target = peerSockets.get(targetPeerId);\n if (!target) return undefined;\n const readyState = (target as unknown as { readyState?: number }).readyState;\n const OPEN = 1;\n if (readyState !== undefined && readyState !== OPEN) {\n peerSockets.delete(targetPeerId);\n return undefined;\n }\n return target;\n };\n\n const handleSignal = (ws: unknown, msg: Extract<SignalingMessage, { type: \"signal\" }>): void => {\n const wsWithData = ws as unknown as {\n data: Record<string, unknown>;\n send: (m: unknown) => void;\n };\n const senderId = wsWithData.data.peerId as unknown as string | undefined;\n if (!senderId) {\n wsWithData.send({ type: \"error\", reason: \"not-joined\" } as unknown as SignalingMessage);\n return;\n }\n const target = findOpenTarget(msg.targetPeerId);\n if (!target) {\n sendUnknownTarget(ws, msg.targetPeerId);\n return;\n }\n const relayed: SignalingMessage = {\n type: \"signal\",\n peerId: senderId,\n targetPeerId: msg.targetPeerId,\n payload: msg.payload,\n };\n try {\n target.send(relayed);\n } catch {\n peerSockets.delete(msg.targetPeerId);\n sendUnknownTarget(ws, msg.targetPeerId);\n }\n };\n\n return new Elysia().ws(path, {\n message(ws, raw) {\n const msg = parseMessage(raw);\n if (!msg) {\n ws.send({ type: \"error\", reason: \"malformed\" } as unknown as SignalingMessage);\n return;\n }\n if (msg.type === \"join\") {\n handleJoin(ws, msg.peerId);\n return;\n }\n if (msg.type === \"signal\") {\n handleSignal(ws, msg);\n return;\n }\n // Unknown types route to the consumer's custom-frame hook when\n // one is configured. Without a hook they still fall through to\n // the `malformed` error — same behaviour as before this branch\n // existed.\n if (onCustomFrame !== undefined) {\n const wsWithData = ws as unknown as CustomFrameSocket;\n const senderId = wsWithData.data[\"peerId\"];\n const peerId = typeof senderId === \"string\" ? senderId : undefined;\n onCustomFrame(wsWithData, msg as unknown as CustomSignalingFrame, peerId);\n return;\n }\n ws.send({ type: \"error\", reason: \"malformed\" } as unknown as SignalingMessage);\n },\n\n close(ws) {\n const peerId = (ws.data as unknown as Record<string, unknown>).peerId as unknown as\n | string\n | undefined;\n if (!peerId) {\n // Connection that never sent a join — nothing to broadcast and\n // nothing to evict. A bystander coming and going leaves no trace.\n return;\n }\n // Only evict if the map still points at *this* socket. A stale\n // close after the same peerId rejoined on a new socket should not\n // take the fresh entry with it. The comparison uses the `data` bag\n // Elysia attaches to each connection because it is preserved across\n // message and close callbacks, unlike the `ws` wrapper object which\n // Elysia may or may not reuse.\n const mapped = peerSockets.get(peerId);\n const wsData = (ws as unknown as { data: Record<string, unknown> }).data;\n const mappedData = (mapped as unknown as { data?: Record<string, unknown> } | undefined)\n ?.data;\n if (mapped === undefined || mappedData !== wsData) {\n return;\n }\n peerSockets.delete(peerId);\n for (const [_incumbentId, incumbentSocket] of peerSockets) {\n try {\n incumbentSocket.send({ type: \"peer-left\", peerId } as unknown as SignalingMessage);\n } catch {\n // Incumbent socket is gone; its own close handler will tidy.\n }\n }\n },\n });\n}\n",
|
|
19
|
+
"/**\n * @fairfox/polly/test — ephemeral listen ports.\n *\n * A test that draws a listen port at random from a fixed window can collide\n * with itself, with a second copy of the suite, or with any other process\n * holding a port in that window. The integration suite drew 27 ports from a\n * 10,000-port window, which is a 3.45% self-collision probability per run\n * (birthday bound, `1 - exp(-n(n-1)/2N)`) and a lower bound at that. A\n * collision fails `listen()` and reads as flake, so the natural response is a\n * retry — which narrows the window instead of removing it (polly#174).\n *\n * Port 0 asks the kernel for a free port. The server owns that port from the\n * moment it is assigned, so no other process can take it in between. These\n * helpers read the assigned port back off the two server shapes polly binds:\n *\n * - Bun/Elysia — `app.server.port`, after `.listen(0)`\n * - `ws` WebSocketServer — `wss.address().port`, after `{ port: 0 }`\n *\n * `retryOnPortInUse` covers the one case port 0 cannot: a port that must be\n * known before the server starts, such as a restart on the same port.\n */\n\n/** Elysia hangs the underlying Bun server off `.server`. */\ninterface BunServerHost {\n server?: { port?: number | null } | null;\n}\n\n/** `ws`'s WebSocketServer reports its bound address as an AddressInfo. */\ninterface AddressHost {\n address?: () => string | { port?: number | null } | null;\n}\n\n/**\n * Read the port a Bun/Elysia app was actually assigned.\n *\n * @param app An Elysia app (or any Bun server host) already `.listen(0)`-ed.\n * @throws If the app is not listening — a caller reading the port before the\n * listen resolves gets a named failure, not a URL containing `undefined`.\n *\n * @example\n * ```typescript\n * const app = new Elysia().use(signalingServer({ path })).listen(0);\n * const url = `ws://127.0.0.1:${resolveListenPort(app)}${path}`;\n * ```\n */\nexport function resolveListenPort(app: unknown): number {\n const port = (app as unknown as BunServerHost).server?.port;\n if (typeof port !== \"number\" || port <= 0) {\n throw new Error(\n `resolveListenPort: app is not listening (server.port = ${String(port)}). ` +\n \"Call .listen(0) and read the port from the returned app.\"\n );\n }\n return port;\n}\n\n/**\n * Read the port a `ws` WebSocketServer was actually assigned.\n *\n * @param wss A WebSocketServer constructed with `{ port: 0 }` and already\n * listening — `createPeerRepoServer` awaits that before it returns.\n * @throws If the server is not listening on a TCP port.\n *\n * @example\n * ```typescript\n * const server = await createPeerRepoServer({ port: 0, host: \"127.0.0.1\", storagePath });\n * const url = `ws://127.0.0.1:${resolveWebSocketPort(server.webSocketServer)}`;\n * ```\n */\nexport function resolveWebSocketPort(wss: unknown): number {\n const address = (wss as unknown as AddressHost).address?.();\n const port = typeof address === \"object\" && address !== null ? address.port : undefined;\n if (typeof port !== \"number\" || port <= 0) {\n throw new Error(\n `resolveWebSocketPort: server is not listening on a TCP port (address = ${JSON.stringify(address)}).`\n );\n }\n return port;\n}\n\n/** Bun, Node and `ws` all word an occupied-port failure differently. */\nfunction isPortInUse(error: unknown): boolean {\n if (error instanceof Error && \"code\" in error && error.code === \"EADDRINUSE\") return true;\n const message = error instanceof Error ? error.message : String(error);\n return /EADDRINUSE|address already in use|is port \\d+ in use|Failed to start server/i.test(\n message\n );\n}\n\nexport interface RetryOnPortInUseOptions {\n /** How many times to call `start` in total. Defaults to 5. */\n attempts?: number;\n /** Pause between attempts, in milliseconds. Defaults to 100. */\n delayMs?: number;\n}\n\n/**\n * Start a server on a port that is already decided, retrying a bounded number\n * of times while the port is still held.\n *\n * Only for the case port 0 cannot serve: the port must be known before the\n * server starts — a restart on the same port, or a URL handed out in advance.\n * A retry narrows the collision window rather than removing it, so prefer\n * `.listen(0)` plus {@link resolveListenPort} everywhere else.\n *\n * The final failure is the bind error itself, so the test reports \"port in\n * use\" rather than timing out on a connection to a server that never started.\n *\n * @example\n * ```typescript\n * const app = await retryOnPortInUse(() => startSignaling(port));\n * ```\n */\nexport async function retryOnPortInUse<T>(\n start: () => T | Promise<T>,\n options: RetryOnPortInUseOptions = {}\n): Promise<T> {\n const attempts = options.attempts ?? 5;\n const delayMs = options.delayMs ?? 100;\n let lastError: unknown;\n for (let attempt = 1; attempt <= attempts; attempt += 1) {\n try {\n return await start();\n } catch (error) {\n if (!isPortInUse(error)) throw error;\n lastError = error;\n if (attempt < attempts) await new Promise((r) => setTimeout(r, delayMs));\n }\n }\n throw lastError;\n}\n"
|
|
19
20
|
],
|
|
20
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA;AA+BO,SAAS,mBAAmB,GAAe;AAAA,EAChD,OAAO,KAAK,YAAY,SAAS;AAAA;AAQ5B,SAAS,OAAO,CAAC,SAAqB,KAA8B;AAAA,EACzE,IAAI,IAAI,WAAW,WAAW;AAAA,IAC5B,MAAM,IAAI,gBACR,yBAAyB,wBAAwB,IAAI,WACrD,oBACF;AAAA,EACF;AAAA,EACA,MAAM,QAAQ,KAAK,YAAY,WAAW;AAAA,EAC1C,MAAM,aAAa,KAAK,UAAU,SAAS,OAAO,GAAG;AAAA,EACrD,MAAM,MAAM,IAAI,WAAW,cAAc,WAAW,MAAM;AAAA,EAC1D,IAAI,IAAI,OAAO,CAAC;AAAA,EAChB,IAAI,IAAI,YAAY,WAAW;AAAA,EAC/B,OAAO;AAAA;AAcF,SAAS,OAAO,CAAC,QAAqB,KAAyC;AAAA,EACpF,IAAI,IAAI,WAAW,WAAW;AAAA,IAC5B,MAAM,IAAI,gBACR,yBAAyB,wBAAwB,IAAI,WACrD,oBACF;AAAA,EACF;AAAA,EACA,IAAI,OAAO,SAAS,cAAc,WAAW;AAAA,IAC3C;AAAA,EACF;AAAA,EACA,MAAM,QAAQ,OAAO,SAAS,GAAG,WAAW;AAAA,EAC5C,MAAM,aAAa,OAAO,SAAS,WAAW;AAAA,EAC9C,MAAM,SAAS,KAAK,UAAU,KAAK,YAAY,OAAO,GAAG;AAAA,EACzD,OAAO,UAAU;AAAA;AAOZ,SAAS,cAAc,CAAC,QAAqB,KAA6B;AAAA,EAC/E,MAAM,SAAS,QAAQ,QAAQ,GAAG;AAAA,EAClC,IAAI,CAAC,QAAQ;AAAA,IACX,MAAM,IAAI,gBACR,sFACA,gBACF;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAoBF,SAAS,YAAY,CAC1B,SACA,YACA,KACmB;AAAA,EACnB,OAAO;AAAA,IACL;AAAA,IACA,QAAQ,QAAQ,SAAS,GAAG;AAAA,EAC9B;AAAA;AAOK,SAAS,YAAY,CAAC,UAA6B,KAA6B;AAAA,EACrF,OAAO,eAAe,SAAS,QAAQ,GAAG;AAAA;AAYrC,SAAS,uBAAuB,CAAC,UAAyC;AAAA,EAC/E,MAAM,UAAU,IAAI,YAAY,EAAE,OAAO,SAAS,UAAU;AAAA,EAC5D,MAAM,MAAM,IAAI,WAAW,IAAI,QAAQ,SAAS,SAAS,OAAO,MAAM;AAAA,EACtE,MAAM,OAAO,IAAI,SAAS,IAAI,MAAM;AAAA,EACpC,KAAK,UAAU,GAAG,QAAQ,QAAQ,KAAK;AAAA,EACvC,IAAI,IAAI,SAAS,CAAC;AAAA,EAClB,IAAI,IAAI,SAAS,QAAQ,IAAI,QAAQ,MAAM;AAAA,EAC3C,OAAO;AAAA;AAOF,SAAS,uBAAuB,CAAC,OAAsC;AAAA,EAC5E,IAAI,MAAM,SAAS,GAAG;AAAA,IACpB,MAAM,IAAI,gBACR,iCAAiC,MAAM,iBACvC,oBACF;AAAA,EACF;AAAA,EACA,MAAM,OAAO,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAAA,EAC1E,MAAM,QAAQ,KAAK,UAAU,GAAG,KAAK;AAAA,EACrC,IAAI,MAAM,SAAS,IAAI,OAAO;AAAA,IAC5B,MAAM,IAAI,gBACR,oDAAoD,gBAAgB,MAAM,WAC1E,oBACF;AAAA,EACF;AAAA,EACA,MAAM,aAAa,IAAI,YAAY,EAAE,OAAO,MAAM,SAAS,GAAG,IAAI,KAAK,CAAC;AAAA,EACxE,MAAM,SAAS,MAAM,MAAM,IAAI,KAAK;AAAA,EACpC,OAAO,EAAE,YAAY,OAAO;AAAA;AAAA,IA1KjB,YAAY,IAEZ,cAAc,IAEd,YAAY,IAWZ;AAAA;AAAA,oBAAN,MAAM,wBAAwB,MAAM;AAAA,IAChC;AAAA,IACT,WAAW,CAAC,SAAiB,MAA+B;AAAA,MAC1D,MAAM,OAAO;AAAA,MACb,KAAK,OAAO;AAAA,MACZ,KAAK,OAAO;AAAA;AAAA,EAEhB;AAAA;;;;;;;;;;;;;;;;;;;;;AC5DA,SAAS,UAAU,CAAC,MAAK;AAAA,EAAC,IAAG,OAAO,SAAO;AAAA,IAAS,MAAM,UAAU,qCAAmC,KAAK,UAAU,IAAI,CAAC;AAAA;AAAE,SAAS,oBAAoB,CAAC,MAAK,gBAAe;AAAA,EAAC,IAAI,MAAI,IAAG,oBAAkB,GAAE,YAAU,IAAG,OAAK,GAAE;AAAA,EAAK,SAAQ,IAAE,EAAE,KAAG,KAAK,QAAO,EAAE,GAAE;AAAA,IAAC,IAAG,IAAE,KAAK;AAAA,MAAO,OAAK,KAAK,WAAW,CAAC;AAAA,IAAO,SAAG,SAAO;AAAA,MAAG;AAAA,IAAW;AAAA,aAAK;AAAA,IAAG,IAAG,SAAO,IAAG;AAAA,MAAC,IAAG,cAAY,IAAE,KAAG,SAAO;AAAA;AAAA,MAAQ,SAAG,cAAY,IAAE,KAAG,SAAO,GAAE;AAAA,QAAC,IAAG,IAAI,SAAO,KAAG,sBAAoB,KAAG,IAAI,WAAW,IAAI,SAAO,CAAC,MAAI,MAAI,IAAI,WAAW,IAAI,SAAO,CAAC,MAAI,IAAG;AAAA,UAAC,IAAG,IAAI,SAAO,GAAE;AAAA,YAAC,IAAI,iBAAe,IAAI,YAAY,GAAG;AAAA,YAAE,IAAG,mBAAiB,IAAI,SAAO,GAAE;AAAA,cAAC,IAAG,mBAAiB;AAAA,gBAAG,MAAI,IAAG,oBAAkB;AAAA,cAAO;AAAA,sBAAI,IAAI,MAAM,GAAE,cAAc,GAAE,oBAAkB,IAAI,SAAO,IAAE,IAAI,YAAY,GAAG;AAAA,cAAE,YAAU,GAAE,OAAK;AAAA,cAAE;AAAA,YAAQ;AAAA,UAAC,EAAM,SAAG,IAAI,WAAS,KAAG,IAAI,WAAS,GAAE;AAAA,YAAC,MAAI,IAAG,oBAAkB,GAAE,YAAU,GAAE,OAAK;AAAA,YAAE;AAAA,UAAQ;AAAA,QAAC;AAAA,QAAC,IAAG,gBAAe;AAAA,UAAC,IAAG,IAAI,SAAO;AAAA,YAAE,OAAK;AAAA,UAAW;AAAA,kBAAI;AAAA,UAAK,oBAAkB;AAAA,QAAC;AAAA,MAAC,EAAK;AAAA,QAAC,IAAG,IAAI,SAAO;AAAA,UAAE,OAAK,MAAI,KAAK,MAAM,YAAU,GAAE,CAAC;AAAA,QAAO;AAAA,gBAAI,KAAK,MAAM,YAAU,GAAE,CAAC;AAAA,QAAE,oBAAkB,IAAE,YAAU;AAAA;AAAA,MAAE,YAAU,GAAE,OAAK;AAAA,IAAC,EAAM,SAAG,SAAO,MAAI,SAAO;AAAA,MAAG,EAAE;AAAA,IAAU;AAAA,aAAK;AAAA,EAAE;AAAA,EAAC,OAAO;AAAA;AAAI,SAAS,OAAO,CAAC,KAAI,YAAW;AAAA,EAAC,IAAI,MAAI,WAAW,OAAK,WAAW,MAAK,OAAK,WAAW,SAAO,WAAW,QAAM,OAAK,WAAW,OAAK;AAAA,EAAI,IAAG,CAAC;AAAA,IAAI,OAAO;AAAA,EAAK,IAAG,QAAM,WAAW;AAAA,IAAK,OAAO,MAAI;AAAA,EAAK,OAAO,MAAI,MAAI;AAAA;AAAK,SAAS,OAAO,GAAE;AAAA,EAAC,IAAI,eAAa,IAAG,mBAAiB,OAAG;AAAA,EAAI,SAAQ,IAAE,UAAU,SAAO,EAAE,KAAG,MAAI,CAAC,kBAAiB,KAAI;AAAA,IAAC,IAAI;AAAA,IAAK,IAAG,KAAG;AAAA,MAAE,OAAK,UAAU;AAAA,IAAO;AAAA,MAAC,IAAG,QAAW;AAAA,QAAE,MAAI,QAAQ,IAAI;AAAA,MAAE,OAAK;AAAA;AAAA,IAAI,IAAG,WAAW,IAAI,GAAE,KAAK,WAAS;AAAA,MAAE;AAAA,IAAS,eAAa,OAAK,MAAI,cAAa,mBAAiB,KAAK,WAAW,CAAC,MAAI;AAAA,EAAE;AAAA,EAAC,IAAG,eAAa,qBAAqB,cAAa,CAAC,gBAAgB,GAAE;AAAA,IAAiB,IAAG,aAAa,SAAO;AAAA,MAAE,OAAM,MAAI;AAAA,IAAkB;AAAA,aAAM;AAAA,EAAS,SAAG,aAAa,SAAO;AAAA,IAAE,OAAO;AAAA,EAAkB;AAAA,WAAM;AAAA;AAAI,SAAS,SAAS,CAAC,MAAK;AAAA,EAAC,IAAG,WAAW,IAAI,GAAE,KAAK,WAAS;AAAA,IAAE,OAAM;AAAA,EAAI,IAAI,aAAW,KAAK,WAAW,CAAC,MAAI,IAAG,oBAAkB,KAAK,WAAW,KAAK,SAAO,CAAC,MAAI;AAAA,EAAG,IAAG,OAAK,qBAAqB,MAAK,CAAC,UAAU,GAAE,KAAK,WAAS,KAAG,CAAC;AAAA,IAAW,OAAK;AAAA,EAAI,IAAG,KAAK,SAAO,KAAG;AAAA,IAAkB,QAAM;AAAA,EAAI,IAAG;AAAA,IAAW,OAAM,MAAI;AAAA,EAAK,OAAO;AAAA;AAAK,SAAS,UAAU,CAAC,MAAK;AAAA,EAAC,OAAO,WAAW,IAAI,GAAE,KAAK,SAAO,KAAG,KAAK,WAAW,CAAC,MAAI;AAAA;AAAG,SAAS,IAAI,GAAE;AAAA,EAAC,IAAG,UAAU,WAAS;AAAA,IAAE,OAAM;AAAA,EAAI,IAAI;AAAA,EAAO,SAAQ,IAAE,EAAE,IAAE,UAAU,QAAO,EAAE,GAAE;AAAA,IAAC,IAAI,MAAI,UAAU;AAAA,IAAG,IAAG,WAAW,GAAG,GAAE,IAAI,SAAO;AAAA,MAAE,IAAG,WAAc;AAAA,QAAE,SAAO;AAAA,MAAS;AAAA,kBAAQ,MAAI;AAAA,EAAG;AAAA,EAAC,IAAG,WAAc;AAAA,IAAE,OAAM;AAAA,EAAI,OAAO,UAAU,MAAM;AAAA;AAAE,SAAS,QAAQ,CAAC,MAAK,IAAG;AAAA,EAAC,IAAG,WAAW,IAAI,GAAE,WAAW,EAAE,GAAE,SAAO;AAAA,IAAG,OAAM;AAAA,EAAG,IAAG,OAAK,QAAQ,IAAI,GAAE,KAAG,QAAQ,EAAE,GAAE,SAAO;AAAA,IAAG,OAAM;AAAA,EAAG,IAAI,YAAU;AAAA,EAAE,MAAK,YAAU,KAAK,QAAO,EAAE;AAAA,IAAU,IAAG,KAAK,WAAW,SAAS,MAAI;AAAA,MAAG;AAAA,EAAM,IAAI,UAAQ,KAAK,QAAO,UAAQ,UAAQ,WAAU,UAAQ;AAAA,EAAE,MAAK,UAAQ,GAAG,QAAO,EAAE;AAAA,IAAQ,IAAG,GAAG,WAAW,OAAO,MAAI;AAAA,MAAG;AAAA,EAAM,IAAI,QAAM,GAAG,QAAO,QAAM,QAAM,SAAQ,SAAO,UAAQ,QAAM,UAAQ,OAAM,gBAAc,IAAG,IAAE;AAAA,EAAE,MAAK,KAAG,QAAO,EAAE,GAAE;AAAA,IAAC,IAAG,MAAI,QAAO;AAAA,MAAC,IAAG,QAAM,QAAO;AAAA,QAAC,IAAG,GAAG,WAAW,UAAQ,CAAC,MAAI;AAAA,UAAG,OAAO,GAAG,MAAM,UAAQ,IAAE,CAAC;AAAA,QAAO,SAAG,MAAI;AAAA,UAAE,OAAO,GAAG,MAAM,UAAQ,CAAC;AAAA,MAAC,EAAM,SAAG,UAAQ,QAAO;AAAA,QAAC,IAAG,KAAK,WAAW,YAAU,CAAC,MAAI;AAAA,UAAG,gBAAc;AAAA,QAAO,SAAG,MAAI;AAAA,UAAE,gBAAc;AAAA,MAAC;AAAA,MAAC;AAAA,IAAK;AAAA,IAAC,IAAI,WAAS,KAAK,WAAW,YAAU,CAAC,GAAE,SAAO,GAAG,WAAW,UAAQ,CAAC;AAAA,IAAE,IAAG,aAAW;AAAA,MAAO;AAAA,IAAW,SAAG,aAAW;AAAA,MAAG,gBAAc;AAAA,EAAC;AAAA,EAAC,IAAI,MAAI;AAAA,EAAG,KAAI,IAAE,YAAU,gBAAc,EAAE,KAAG,SAAQ,EAAE;AAAA,IAAE,IAAG,MAAI,WAAS,KAAK,WAAW,CAAC,MAAI;AAAA,MAAG,IAAG,IAAI,WAAS;AAAA,QAAE,OAAK;AAAA,MAAU;AAAA,eAAK;AAAA,EAAM,IAAG,IAAI,SAAO;AAAA,IAAE,OAAO,MAAI,GAAG,MAAM,UAAQ,aAAa;AAAA,EAAM;AAAA,IAAC,IAAG,WAAS,eAAc,GAAG,WAAW,OAAO,MAAI;AAAA,MAAG,EAAE;AAAA,IAAQ,OAAO,GAAG,MAAM,OAAO;AAAA;AAAA;AAAG,SAAS,SAAS,CAAC,MAAK;AAAA,EAAC,OAAO;AAAA;AAAK,SAAS,OAAO,CAAC,MAAK;AAAA,EAAC,IAAG,WAAW,IAAI,GAAE,KAAK,WAAS;AAAA,IAAE,OAAM;AAAA,EAAI,IAAI,OAAK,KAAK,WAAW,CAAC,GAAE,UAAQ,SAAO,IAAG,MAAI,IAAG,eAAa;AAAA,EAAG,SAAQ,IAAE,KAAK,SAAO,EAAE,KAAG,GAAE,EAAE;AAAA,IAAE,IAAG,OAAK,KAAK,WAAW,CAAC,GAAE,SAAO,IAAG;AAAA,MAAC,IAAG,CAAC,cAAa;AAAA,QAAC,MAAI;AAAA,QAAE;AAAA,MAAK;AAAA,IAAC,EAAM;AAAA,qBAAa;AAAA,EAAG,IAAG,QAAM;AAAA,IAAG,OAAO,UAAQ,MAAI;AAAA,EAAI,IAAG,WAAS,QAAM;AAAA,IAAE,OAAM;AAAA,EAAK,OAAO,KAAK,MAAM,GAAE,GAAG;AAAA;AAAE,SAAS,QAAQ,CAAC,MAAK,KAAI;AAAA,EAAC,IAAG,QAAW,aAAG,OAAO,QAAM;AAAA,IAAS,MAAM,UAAU,iCAAiC;AAAA,EAAE,WAAW,IAAI;AAAA,EAAE,IAAI,QAAM,GAAE,MAAI,IAAG,eAAa,MAAG;AAAA,EAAE,IAAG,QAAW,aAAG,IAAI,SAAO,KAAG,IAAI,UAAQ,KAAK,QAAO;AAAA,IAAC,IAAG,IAAI,WAAS,KAAK,UAAQ,QAAM;AAAA,MAAK,OAAM;AAAA,IAAG,IAAI,SAAO,IAAI,SAAO,GAAE,mBAAiB;AAAA,IAAG,KAAI,IAAE,KAAK,SAAO,EAAE,KAAG,GAAE,EAAE,GAAE;AAAA,MAAC,IAAI,OAAK,KAAK,WAAW,CAAC;AAAA,MAAE,IAAG,SAAO,IAAG;AAAA,QAAC,IAAG,CAAC,cAAa;AAAA,UAAC,QAAM,IAAE;AAAA,UAAE;AAAA,QAAK;AAAA,MAAC,EAAK;AAAA,QAAC,IAAG,qBAAmB;AAAA,UAAG,eAAa,OAAG,mBAAiB,IAAE;AAAA,QAAE,IAAG,UAAQ;AAAA,UAAE,IAAG,SAAO,IAAI,WAAW,MAAM,GAAE;AAAA,YAAC,IAAG,EAAE,WAAS;AAAA,cAAG,MAAI;AAAA,UAAC,EAAM;AAAA,qBAAO,IAAG,MAAI;AAAA;AAAA,IAAiB;AAAA,IAAC,IAAG,UAAQ;AAAA,MAAI,MAAI;AAAA,IAAsB,SAAG,QAAM;AAAA,MAAG,MAAI,KAAK;AAAA,IAAO,OAAO,KAAK,MAAM,OAAM,GAAG;AAAA,EAAC,EAAK;AAAA,IAAC,KAAI,IAAE,KAAK,SAAO,EAAE,KAAG,GAAE,EAAE;AAAA,MAAE,IAAG,KAAK,WAAW,CAAC,MAAI,IAAG;AAAA,QAAC,IAAG,CAAC,cAAa;AAAA,UAAC,QAAM,IAAE;AAAA,UAAE;AAAA,QAAK;AAAA,MAAC,EAAM,SAAG,QAAM;AAAA,QAAG,eAAa,OAAG,MAAI,IAAE;AAAA,IAAE,IAAG,QAAM;AAAA,MAAG,OAAM;AAAA,IAAG,OAAO,KAAK,MAAM,OAAM,GAAG;AAAA;AAAA;AAAG,SAAS,OAAO,CAAC,MAAK;AAAA,EAAC,WAAW,IAAI;AAAA,EAAE,IAAI,WAAS,IAAG,YAAU,GAAE,MAAI,IAAG,eAAa,MAAG,cAAY;AAAA,EAAE,SAAQ,IAAE,KAAK,SAAO,EAAE,KAAG,GAAE,EAAE,GAAE;AAAA,IAAC,IAAI,OAAK,KAAK,WAAW,CAAC;AAAA,IAAE,IAAG,SAAO,IAAG;AAAA,MAAC,IAAG,CAAC,cAAa;AAAA,QAAC,YAAU,IAAE;AAAA,QAAE;AAAA,MAAK;AAAA,MAAC;AAAA,IAAQ;AAAA,IAAC,IAAG,QAAM;AAAA,MAAG,eAAa,OAAG,MAAI,IAAE;AAAA,IAAE,IAAG,SAAO,IAAG;AAAA,MAAC,IAAG,aAAW;AAAA,QAAG,WAAS;AAAA,MAAO,SAAG,gBAAc;AAAA,QAAE,cAAY;AAAA,IAAC,EAAM,SAAG,aAAW;AAAA,MAAG,cAAY;AAAA,EAAE;AAAA,EAAC,IAAG,aAAW,MAAI,QAAM,MAAI,gBAAc,KAAG,gBAAc,KAAG,aAAW,MAAI,KAAG,aAAW,YAAU;AAAA,IAAE,OAAM;AAAA,EAAG,OAAO,KAAK,MAAM,UAAS,GAAG;AAAA;AAAE,SAAS,MAAM,CAAC,YAAW;AAAA,EAAC,IAAG,eAAa,QAAM,OAAO,eAAa;AAAA,IAAS,MAAM,UAAU,qEAAmE,OAAO,UAAU;AAAA,EAAE,OAAO,QAAQ,KAAI,UAAU;AAAA;AAAE,SAAS,KAAK,CAAC,MAAK;AAAA,EAAC,WAAW,IAAI;AAAA,EAAE,IAAI,MAAI,EAAC,MAAK,IAAG,KAAI,IAAG,MAAK,IAAG,KAAI,IAAG,MAAK,GAAE;AAAA,EAAE,IAAG,KAAK,WAAS;AAAA,IAAE,OAAO;AAAA,EAAI,IAAI,OAAK,KAAK,WAAW,CAAC,GAAE,cAAY,SAAO,IAAG;AAAA,EAAM,IAAG;AAAA,IAAY,IAAI,OAAK,KAAI,QAAM;AAAA,EAAO;AAAA,YAAM;AAAA,EAAE,IAAI,WAAS,IAAG,YAAU,GAAE,MAAI,IAAG,eAAa,MAAG,IAAE,KAAK,SAAO,GAAE,cAAY;AAAA,EAAE,MAAK,KAAG,OAAM,EAAE,GAAE;AAAA,IAAC,IAAG,OAAK,KAAK,WAAW,CAAC,GAAE,SAAO,IAAG;AAAA,MAAC,IAAG,CAAC,cAAa;AAAA,QAAC,YAAU,IAAE;AAAA,QAAE;AAAA,MAAK;AAAA,MAAC;AAAA,IAAQ;AAAA,IAAC,IAAG,QAAM;AAAA,MAAG,eAAa,OAAG,MAAI,IAAE;AAAA,IAAE,IAAG,SAAO,IAAG;AAAA,MAAC,IAAG,aAAW;AAAA,QAAG,WAAS;AAAA,MAAO,SAAG,gBAAc;AAAA,QAAE,cAAY;AAAA,IAAC,EAAM,SAAG,aAAW;AAAA,MAAG,cAAY;AAAA,EAAE;AAAA,EAAC,IAAG,aAAW,MAAI,QAAM,MAAI,gBAAc,KAAG,gBAAc,KAAG,aAAW,MAAI,KAAG,aAAW,YAAU,GAAE;AAAA,IAAC,IAAG,QAAM;AAAA,MAAG,IAAG,cAAY,KAAG;AAAA,QAAY,IAAI,OAAK,IAAI,OAAK,KAAK,MAAM,GAAE,GAAG;AAAA,MAAO;AAAA,YAAI,OAAK,IAAI,OAAK,KAAK,MAAM,WAAU,GAAG;AAAA,EAAC,EAAK;AAAA,IAAC,IAAG,cAAY,KAAG;AAAA,MAAY,IAAI,OAAK,KAAK,MAAM,GAAE,QAAQ,GAAE,IAAI,OAAK,KAAK,MAAM,GAAE,GAAG;AAAA,IAAO;AAAA,UAAI,OAAK,KAAK,MAAM,WAAU,QAAQ,GAAE,IAAI,OAAK,KAAK,MAAM,WAAU,GAAG;AAAA,IAAE,IAAI,MAAI,KAAK,MAAM,UAAS,GAAG;AAAA;AAAA,EAAE,IAAG,YAAU;AAAA,IAAE,IAAI,MAAI,KAAK,MAAM,GAAE,YAAU,CAAC;AAAA,EAAO,SAAG;AAAA,IAAY,IAAI,MAAI;AAAA,EAAI,OAAO;AAAA;AAAA,IAAQ,MAAI,KAAI,YAAU,KAAI,OAAiK;AAAA;AAAA,EAAjK,SAAO,CAAC,OAAK,EAAE,QAAM,GAAE,IAAI,EAAC,SAAQ,WAAU,YAAW,MAAK,UAAS,WAAU,SAAQ,UAAS,SAAQ,QAAO,OAAM,KAAI,WAAU,OAAM,MAAK,OAAM,KAAI,CAAC;AAAA,EAAM,eAAa;AAAA;;;ACyB35N,IAAM,yBAAwD;AAAA,EACnE;AAAA,IACE,OAAO;AAAA,IACP,QACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,QACE;AAAA,EACJ;AACF;AAKO,SAAS,oBAAoB,CAClC,MACA,YAA2C,wBAClC;AAAA,EACT,WAAW,SAAS,WAAW;AAAA,IAC7B,IAAI,MAAM,SAAS,MAAM,UAAU,KAAK;AAAA,MAAO;AAAA,IAC/C,IAAI,OAAO,MAAM,UAAU,UAAU;AAAA,MACnC,IAAI,KAAK,KAAK,SAAS,MAAM,KAAK;AAAA,QAAG,OAAO;AAAA,IAC9C,EAAO,SAAI,MAAM,MAAM,KAAK,KAAK,IAAI,GAAG;AAAA,MACtC,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EACA,OAAO;AAAA;;AClDT;;;ACmBA;AAGO,IAAM,mBAAmB;AAEzB,IAAM,mBAAmB;AAEzB,IAAM,kBAAkB;AAAA;AA4BxB,MAAM,qBAAqB,MAAM;AAAA,EAC7B;AAAA,EAMT,WAAW,CAAC,SAAiB,MAA4B;AAAA,IACvD,MAAM,OAAO;AAAA,IACb,KAAK,OAAO;AAAA,IACZ,KAAK,OAAO;AAAA;AAEhB;AAKO,SAAS,sBAAsB,GAAmB;AAAA,EACvD,MAAM,OAAO,MAAK,KAAK,QAAQ;AAAA,EAC/B,OAAO;AAAA,IACL,WAAW,KAAK;AAAA,IAChB,WAAW,KAAK;AAAA,EAClB;AAAA;AAOK,SAAS,wBAAwB,CAAC,WAAuC;AAAA,EAC9E,IAAI,UAAU,WAAW,kBAAkB;AAAA,IACzC,MAAM,IAAI,aACR,8BAA8B,+BAA+B,UAAU,WACvE,oBACF;AAAA,EACF;AAAA,EACA,MAAM,OAAO,MAAK,KAAK,QAAQ,cAAc,SAAS;AAAA,EACtD,OAAO;AAAA,IACL,WAAW,KAAK;AAAA,IAChB,WAAW,KAAK;AAAA,EAClB;AAAA;AAOK,SAAS,IAAI,CAAC,SAAqB,WAAmC;AAAA,EAC3E,IAAI,UAAU,WAAW,kBAAkB;AAAA,IACzC,MAAM,IAAI,aACR,8BAA8B,+BAA+B,UAAU,WACvE,oBACF;AAAA,EACF;AAAA,EACA,OAAO,MAAK,KAAK,SAAS,SAAS,SAAS;AAAA;AASvC,SAAS,MAAM,CAAC,SAAqB,WAAuB,WAAgC;AAAA,EACjG,IAAI,UAAU,WAAW,kBAAkB;AAAA,IACzC,MAAM,IAAI,aACR,8BAA8B,+BAA+B,UAAU,WACvE,oBACF;AAAA,EACF;AAAA,EACA,IAAI,UAAU,WAAW,iBAAiB;AAAA,IACxC,MAAM,IAAI,aACR,6BAA6B,8BAA8B,UAAU,WACrE,0BACF;AAAA,EACF;AAAA,EACA,OAAO,MAAK,KAAK,SAAS,OAAO,SAAS,WAAW,SAAS;AAAA;AAQzD,SAAS,YAAY,CAC1B,SACA,UACA,WACgB;AAAA,EAChB,MAAM,YAAY,KAAK,SAAS,SAAS;AAAA,EACzC,OAAO,EAAE,UAAU,SAAS,UAAU;AAAA;AASjC,SAAS,aAAY,CAAC,UAA0B,WAAmC;AAAA,EACxF,MAAM,KAAK,OAAO,SAAS,SAAS,SAAS,WAAW,SAAS;AAAA,EACjE,IAAI,CAAC,IAAI;AAAA,IACP,MAAM,IAAI,aACR,mDAAmD,SAAS,aAC5D,oBACF;AAAA,EACF;AAAA,EACA,OAAO,SAAS;AAAA;AAeX,SAAS,oBAAoB,CAAC,UAAsC;AAAA,EACzE,MAAM,cAAc,IAAI,YAAY,EAAE,OAAO,SAAS,QAAQ;AAAA,EAC9D,MAAM,QAAQ,IAAI,YAAY,SAAS,kBAAkB,SAAS,QAAQ;AAAA,EAC1E,MAAM,MAAM,IAAI,WAAW,KAAK;AAAA,EAChC,MAAM,OAAO,IAAI,SAAS,IAAI,MAAM;AAAA,EACpC,KAAK,UAAU,GAAG,YAAY,QAAQ,KAAK;AAAA,EAC3C,IAAI,IAAI,aAAa,CAAC;AAAA,EACtB,IAAI,IAAI,SAAS,WAAW,IAAI,YAAY,MAAM;AAAA,EAClD,IAAI,IAAI,SAAS,SAAS,IAAI,YAAY,SAAS,eAAe;AAAA,EAClE,OAAO;AAAA;AAOF,SAAS,oBAAoB,CAAC,OAAmC;AAAA,EACtE,IAAI,MAAM,SAAS,IAAI,iBAAiB;AAAA,IACtC,MAAM,IAAI,aACR,uBAAuB,MAAM,+BAA+B,IAAI,oBAChE,oBACF;AAAA,EACF;AAAA,EACA,MAAM,OAAO,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAAA,EAC1E,MAAM,YAAY,KAAK,UAAU,GAAG,KAAK;AAAA,EACzC,IAAI,MAAM,SAAS,IAAI,YAAY,iBAAiB;AAAA,IAClD,MAAM,IAAI,aACR,8CAA8C,oBAAoB,MAAM,WACxE,oBACF;AAAA,EACF;AAAA,EACA,MAAM,WAAW,IAAI,YAAY,EAAE,OAAO,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC;AAAA,EAC1E,MAAM,YAAY,MAAM,MAAM,IAAI,WAAW,IAAI,YAAY,eAAe;AAAA,EAC5E,MAAM,UAAU,MAAM,MAAM,IAAI,YAAY,eAAe;AAAA,EAC3D,OAAO,EAAE,UAAU,SAAS,UAAU;AAAA;;;ADjMxC,SAAS,QAAQ,CAAC,OAA2B;AAAA,EAC3C,IAAI,SAAS;AAAA,EACb,WAAW,QAAQ,OAAO;AAAA,IACxB,UAAU,OAAO,aAAa,IAAI;AAAA,EACpC;AAAA,EACA,OAAO,KAAK,MAAM;AAAA;AAQb,SAAS,kBAAkB,CAAC,UAAU,UAAU,UAAU,UAA+B;AAAA,EAC9F,MAAM,MAAM,kBAAkB,CAAC,SAAS,OAAO,CAAC;AAAA,EAChD,OAAO,OAAO,SAAS,IAAI;AAAA,EAC3B,IAAI,UAAU,aAAa,UAAU,WAAW;AAAA,IAC9C,MAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAAA,EACA,OAAO;AAAA,IACL,OAAO,CAAC,OAAO,KAAK;AAAA,IACpB,WAAW,IAAI;AAAA,EACjB;AAAA;AAoBK,SAAS,iBAAiB,CAAC,SAAoD;AAAA,EACpF,IAAI,QAAQ,SAAS,GAAG;AAAA,IACtB,MAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AAAA,EACA,MAAM,SAAS,oBAAoB;AAAA,EACnC,MAAM,QAAwB,QAAQ,IAAI,CAAC,WAAW;AAAA,IACpD,MAAM,OAAO,uBAAuB;AAAA,IACpC,OAAO;AAAA,MACL;AAAA,MACA,sBAAsB,SAAS,KAAK,SAAS;AAAA,MAC7C,sBAAsB,SAAS,KAAK,SAAS;AAAA,IAC/C;AAAA,GACD;AAAA,EACD,OAAO,EAAE,OAAO,WAAW,SAAS,MAAM,EAAE;AAAA;AASvC,SAAS,aAAa,CAAC,KAAyB,YAA4C;AAAA,EACjG,MAAM,MAA8B,CAAC;AAAA,EACrC,WAAW,QAAQ,IAAI,OAAO;AAAA,IAC5B,IAAI,KAAK,WAAW;AAAA,MAAY;AAAA,IAChC,IAAI,KAAK,UAAU,KAAK;AAAA,EAC1B;AAAA,EACA,OAAO;AAAA;;AEvFT;;;ACdA,IAAijB,SAAO,QAAQ,GAAE;AAAA,EAAC,OAAM;AAAA;;;ADgBzkB;AACA;;;AE2EA,IAAM,YAAY,IAAI;AAMf,SAAS,kBAAkB,CAAC,YAAkC;AAAA,EACnE,MAAM,QAA6B,KAAK,YAAY,WAAW,KAAK,IAAI,EAAE;AAAA,EAC1E,WAAW,YAAY,WAAW;AAAA,IAChC,IAAI;AAAA,MACF,SAAS,KAAK;AAAA,MACd,MAAM;AAAA,EAKV;AAAA;AAQK,SAAS,0BAA0B,CAAC,UAA8C;AAAA,EACvF,UAAU,IAAI,QAAQ;AAAA,EACtB,OAAO,MAAM;AAAA,IACX,UAAU,OAAO,QAAQ;AAAA;AAAA;AAUtB,SAAS,qBAAqB,GAGnC;AAAA,EACA,MAAM,WAAkC,CAAC;AAAA,EACzC,MAAM,OAAO,2BAA2B,CAAC,UAAU;AAAA,IACjD,SAAS,KAAK,KAAK;AAAA,GACpB;AAAA,EACD,OAAO,EAAE,QAAQ,UAAU,KAAK;AAAA;;;AC9G3B,MAAM,2BAA2B,MAAsC;AAAA,EACnE,OAAO;AAAA,EACP;AAAA,EACT,WAAW,CAAC,SAAiB,YAAgD;AAAA,IAC3E,MAAM,OAAO;AAAA,IACb,KAAK,OAAO;AAAA,IACZ,KAAK,aAAa;AAAA;AAEtB;AA8BO,SAAS,uBAAuB,GAAuB;AAAA,EAC5D,QAAQ,QAAQ,SAAS,sBAAsB;AAAA,EAE/C,SAAS,mBAAmB,CAAC,QAA+C,CAAC,GAAS;AAAA,IACpF,MAAM,UAAU,IAAI,IAAI,KAAK;AAAA,IAC7B,MAAM,aAAa,OAAO,OACxB,CAAC,UAAU,MAAM,KAAK,WAAW,OAAO,KAAK,CAAC,QAAQ,IAAI,MAAM,IAAI,CACtE;AAAA,IACA,IAAI,WAAW,WAAW;AAAA,MAAG;AAAA,IAC7B,MAAM,UAAU,WACb,IAAI,CAAC,UAAU,KAAK,MAAM,QAAQ,KAAK,UAAU,aAAa,KAAK,CAAC,GAAG,EACvE,KAAK;AAAA,CAAI;AAAA,IACZ,MAAM,IAAI,mBACR;AAAA,EAAiE;AAAA,IAC/D,wEACA,6CACF,UACF;AAAA;AAAA,EAGF,OAAO,EAAE,QAAQ,MAAM,oBAAoB;AAAA;AAG7C,SAAS,YAAY,CAAC,OAAqD;AAAA,EAEzE,QAAQ,MAAM,OAAO,WAAW,QAAQ,SAAS;AAAA,EACjD,OAAO;AAAA;;;AHCT,IAAM,gBAAgB;AAEtB,SAAS,UAAU,CAAC,QAAgB,QAAwB;AAAA,EAC1D,MAAM,aAAa,OAAO,QAAQ,mBAAmB,GAAG;AAAA,EACxD,OAAO,QAAQ,QAAQ,aAAa,cAAc,KAAK,IAAI,GAAG;AAAA;AAOhE,eAAsB,UAAU,CAAC,SAAmD;AAAA,EAClF;AAAA,IACE;AAAA,IACA;AAAA,IACA,WAAW,QAAQ,IAAI,gBAAgB;AAAA,IACvC,mBAAmB;AAAA,IACnB,iBAAiB;AAAA,IACjB,gBAAgB,QAAQ,OAAO,GAAG,WAAW;AAAA,IAC7C,cAAc;AAAA,MACZ;AAAA,EAEJ,IAAI,CAAC,WAAW,aAAa;AAAA,IAAG,UAAU,eAAe,EAAE,WAAW,KAAK,CAAC;AAAA,EAC5E,MAAM,cAAc,WAAW,eAAe,MAAM;AAAA,EACpD,IAAI,WAAW,WAAW,GAAG;AAAA,IAC3B,OAAO,aAAa,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EACtD;AAAA,EAEA,MAAM,UAAmB,MAAM,UAAU,OAAO;AAAA,IAC9C;AAAA,IACA;AAAA,IACA,MAAM,CAAC,gBAAgB,0BAA0B;AAAA,EACnD,CAAC;AAAA,EACD,MAAM,OAAO,MAAM,QAAQ,QAAQ;AAAA,EAEnC,MAAM,eAAsC,CAAC;AAAA,EAC7C,MAAM,aAAuB,CAAC;AAAA,EAE9B,KAAK,GAAG,WAAW,CAAC,QAAQ;AAAA,IAC1B,MAAM,QAAQ,IAAI,KAAK;AAAA,IACvB,MAAM,OAAO,IAAI,KAAK;AAAA,IACtB,MAAM,UAAU,qBAAqB,EAAE,OAAO,KAAK,GAAG,gBAAgB;AAAA,IACtE,aAAa,KAAK,EAAE,OAAO,MAAM,QAAQ,CAAC;AAAA,GAC3C;AAAA,EACD,KAAK,GAAG,aAAa,CAAC,QAAQ;AAAA,IAC5B,WAAW,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,GACjE;AAAA,EAED,MAAM,KAAK,KAAK,aAAa,EAAE,WAAW,mBAAmB,CAAC;AAAA,EAE9D,MAAM,WAAW,KAAK,IAAI,IAAI;AAAA,EAC9B,IAAI,QAAQ;AAAA,EACZ,IAAI,aAAa;AAAA,EACjB,OAAO,KAAK,IAAI,IAAI,UAAU;AAAA,IAC5B,aAAa,MAAM,KAAK,SACtB,MAAM,SAAS,cAAc,qBAAqB,GAAG,eAAe,EACtE;AAAA,IACA,IAAI,eAAe,aAAa;AAAA,MAC9B,QAAQ;AAAA,MACR;AAAA,IACF;AAAA,IACA,IAAI,WAAW,WAAW,OAAO,KAAK,WAAW,WAAW,kBAAkB,GAAG;AAAA,MAC/E,MAAM,QAAQ,MAAM;AAAA,MACpB,OAAO,aAAa,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MACpD,MAAM,IAAI,MAAM,cAAc,+BAA+B,aAAa;AAAA,IAC5E;AAAA,IACA,MAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC;AAAA,EACvD;AAAA,EAEA,IAAI,CAAC,OAAO;AAAA,IACV,MAAM,QAAQ,MAAM;AAAA,IACpB,OAAO,aAAa,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IACpD,MAAM,IAAI,MACR,cAAc,oCAAoC,uBAAuB,mCAAmC,cAC9G;AAAA,EACF;AAAA,EAEA,SAAS,yBAAyB,GAAS;AAAA,IACzC,MAAM,MAAM,aAAa,OACvB,CAAC,SACC,CAAC,KAAK,YACL,KAAK,UAAU,WAAW,KAAK,UAAU,UAAU,KAAK,UAAU,UACvE;AAAA,IACA,IAAI,IAAI,SAAS,GAAG;AAAA,MAClB,MAAM,UAAU,IAAI,IAAI,CAAC,MAAM,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK;AAAA,CAAI;AAAA,MACpE,MAAM,IAAI,MAAM,cAAc;AAAA,EAAwC,SAAS;AAAA,IACjF;AAAA,IACA,IAAI,WAAW,SAAS,GAAG;AAAA,MACzB,MAAM,IAAI,MACR,cAAc;AAAA,EAA0B,WAAW,IAAI,CAAC,MAAM,KAAK,GAAG,EAAE,KAAK;AAAA,CAAI,GACnF;AAAA,IACF;AAAA;AAAA,EAGF,eAAe,kBAAkB,GAAmC;AAAA,IAClE,MAAM,SAAS,MAAM,KAAK,SAAS,MAAM;AAAA,MACvC,MAAM,IAAI;AAAA,MACV,OAAO,EAAE,wBAAwB,CAAC,GAAG,EAAE,qBAAqB,IAAI,CAAC;AAAA,KAClE;AAAA,IACD,OAAO;AAAA;AAAA,EAGT,eAAe,mBAAmB,CAChC,QAA+C,CAAC,GACjC;AAAA,IACf,MAAM,UAAU,IAAI,IAAI,KAAK;AAAA,IAC7B,MAAM,SAAS,MAAM,mBAAmB;AAAA,IACxC,MAAM,aAAa,OAAO,OACxB,CAAC,UAAU,MAAM,KAAK,WAAW,OAAO,KAAK,CAAC,QAAQ,IAAI,MAAM,IAAI,CACtE;AAAA,IACA,IAAI,WAAW,WAAW;AAAA,MAAG;AAAA,IAC7B,MAAM,UAAU,WACb,IAAI,CAAC,UAAU;AAAA,MACd,QAAQ,MAAM,WAAW,QAAQ,SAAS;AAAA,MAC1C,OAAO,KAAK,QAAQ,KAAK,UAAU,IAAI;AAAA,KACxC,EACA,KAAK;AAAA,CAAI;AAAA,IACZ,MAAM,IAAI,mBACR,cAAc;AAAA,EAA0E;AAAA,IACtF,wFACF,UACF;AAAA;AAAA,EAGF,IAAI,SAAS;AAAA,EACb,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,YAAY;AAAA,MACjB,IAAI;AAAA,QAAQ;AAAA,MACZ,SAAS;AAAA,MACT,IAAI;AAAA,QACF,MAAM,KAAK,MAAM;AAAA,QACjB,MAAM;AAAA,MAGR,IAAI;AAAA,QACF,MAAM,QAAQ,MAAM;AAAA,QACpB,MAAM;AAAA,MAGR,IAAI;AAAA,QACF,OAAO,aAAa,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,QACpD,MAAM;AAAA;AAAA,EAIZ;AAAA;AA0BF,eAAsB,eAAe,CACnC,QACA,SACuB;AAAA,EACvB;AAAA,IACE;AAAA,IACA,mBAAmB;AAAA,IACnB,iBAAiB;AAAA,MACf;AAAA,EACJ,MAAM,OAAO,MAAM,OAAO,QAAQ,QAAQ;AAAA,EAE1C,MAAM,eAAsC,CAAC;AAAA,EAC7C,MAAM,aAAuB,CAAC;AAAA,EAC9B,KAAK,GAAG,WAAW,CAAC,QAAQ;AAAA,IAC1B,MAAM,QAAQ,IAAI,KAAK;AAAA,IACvB,MAAM,OAAO,IAAI,KAAK;AAAA,IACtB,MAAM,UAAU,qBAAqB,EAAE,OAAO,KAAK,GAAG,gBAAgB;AAAA,IACtE,aAAa,KAAK,EAAE,OAAO,MAAM,QAAQ,CAAC;AAAA,GAC3C;AAAA,EACD,KAAK,GAAG,aAAa,CAAC,QAAQ;AAAA,IAC5B,WAAW,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,GACjE;AAAA,EAED,MAAM,KAAK,KAAK,aAAa,EAAE,WAAW,mBAAmB,CAAC;AAAA,EAC9D,MAAM,WAAW,KAAK,IAAI,IAAI;AAAA,EAC9B,IAAI,QAAQ;AAAA,EACZ,IAAI,aAAa;AAAA,EACjB,OAAO,KAAK,IAAI,IAAI,UAAU;AAAA,IAC5B,aAAa,MAAM,KAAK,SACtB,MAAM,SAAS,cAAc,qBAAqB,GAAG,eAAe,EACtE;AAAA,IACA,IAAI,eAAe,SAAS;AAAA,MAC1B,QAAQ;AAAA,MACR;AAAA,IACF;AAAA,IACA,IAAI,WAAW,WAAW,OAAO,KAAK,WAAW,WAAW,kBAAkB,GAAG;AAAA,MAC/E,MAAM,KAAK,MAAM;AAAA,MACjB,MAAM,IAAI,MAAM,mBAAmB,OAAO,+BAA+B,aAAa;AAAA,IACxF;AAAA,IACA,MAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC;AAAA,EACvD;AAAA,EACA,IAAI,CAAC,OAAO;AAAA,IACV,MAAM,KAAK,MAAM;AAAA,IACjB,MAAM,IAAI,MACR,mBAAmB,OAAO,kDAAkD,mCAAmC,cACjH;AAAA,EACF;AAAA,EAEA,SAAS,yBAAyB,GAAS;AAAA,IACzC,MAAM,MAAM,aAAa,OACvB,CAAC,SACC,CAAC,KAAK,YACL,KAAK,UAAU,WAAW,KAAK,UAAU,UAAU,KAAK,UAAU,UACvE;AAAA,IACA,IAAI,IAAI,SAAS,GAAG;AAAA,MAClB,MAAM,UAAU,IAAI,IAAI,CAAC,MAAM,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK;AAAA,CAAI;AAAA,MACpE,MAAM,IAAI,MAAM,mBAAmB,OAAO;AAAA,EAAwC,SAAS;AAAA,IAC7F;AAAA,IACA,IAAI,WAAW,SAAS,GAAG;AAAA,MACzB,MAAM,IAAI,MACR,mBAAmB,OAAO;AAAA,EAA0B,WAAW,IAAI,CAAC,MAAM,KAAK,GAAG,EAAE,KAAK;AAAA,CAAI,GAC/F;AAAA,IACF;AAAA;AAAA,EAGF,eAAe,kBAAkB,GAAmC;AAAA,IAClE,OAAO,KAAK,SAAS,MAAM;AAAA,MACzB,MAAM,IAAI;AAAA,MACV,OAAO,EAAE,wBAAwB,CAAC,GAAG,EAAE,qBAAqB,IAAI,CAAC;AAAA,KAClE;AAAA;AAAA,EAGH,eAAe,mBAAmB,CAChC,QAA+C,CAAC,GACjC;AAAA,IACf,MAAM,UAAU,IAAI,IAAI,KAAK;AAAA,IAC7B,MAAM,SAAS,MAAM,mBAAmB;AAAA,IACxC,MAAM,aAAa,OAAO,OACxB,CAAC,UAAU,MAAM,KAAK,WAAW,OAAO,KAAK,CAAC,QAAQ,IAAI,MAAM,IAAI,CACtE;AAAA,IACA,IAAI,WAAW,WAAW;AAAA,MAAG;AAAA,IAC7B,MAAM,UAAU,WACb,IAAI,CAAC,UAAU;AAAA,MACd,QAAQ,MAAM,WAAW,QAAQ,SAAS;AAAA,MAC1C,OAAO,KAAK,QAAQ,KAAK,UAAU,IAAI;AAAA,KACxC,EACA,KAAK;AAAA,CAAI;AAAA,IACZ,MAAM,IAAI,mBACR,mBAAmB,OAAO;AAAA,EAA0E,WACpG,UACF;AAAA;AAAA,EAGF,IAAI,SAAS;AAAA,EACb,OAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf;AAAA,IACA,SAAS,OAAO;AAAA,IAChB,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,YAAY;AAAA,MACjB,IAAI;AAAA,QAAQ;AAAA,MACZ,SAAS;AAAA,MACT,IAAI;AAAA,QACF,MAAM,KAAK,MAAM;AAAA,QACjB,MAAM;AAAA;AAAA,EAIZ;AAAA;;AI9WF;AADA;AAAA;AASA,IAAM,YAAY,QAAQ,WAAW,aAAa;AAClD,IAAM,gBAAgB,QAAQ,WAAW,+BAA+B;AACxE,IAAM,eAAe,QAAQ,WAAW,kCAAkC;AAC1E,IAAM,sBAAsB,QAC1B,WACA,0EACF;AAEA,IAAM,wBAAmC;AAAA,EACvC,MAAM;AAAA,EACN,KAAK,CAAC,OAAO;AAAA,IACX,MAAM,UAAU,EAAE,QAAQ,mCAAmC,GAAG,OAAO;AAAA,MACrE,MAAM;AAAA,IACR,EAAE;AAAA;AAEN;AAoBA,eAAsB,aAAa,CAAC,SAA6D;AAAA,EAC/F,MAAM,cAAc,MAAM,IAAI,MAAM;AAAA,IAClC,aAAa,CAAC,aAAa;AAAA,IAC3B,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,SAAS,CAAC,qBAAqB;AAAA,EACjC,CAAC;AAAA,EACD,IAAI,CAAC,YAAY,SAAS;AAAA,IACxB,MAAM,OAAO,YAAY,KAAK,IAAI,CAAC,QAAQ,OAAO,GAAG,CAAC,EAAE,KAAK;AAAA,CAAI;AAAA,IACjE,MAAM,IAAI,MAAM;AAAA,EAAiC,MAAM;AAAA,EACzD;AAAA,EACA,MAAM,SAAS,MAAM,YAAY,QAAQ,IAAI,KAAK;AAAA,EAClD,IAAI,CAAC,QAAQ;AAAA,IACX,MAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AAAA,EAEA,MAAM,UAAU,aAAa,cAAc,OAAO;AAAA,EAClD,MAAM,gBAAgB,KAAK,UAAU,QAAQ,SAAS;AAAA,EACtD,MAAM,gBAAgB,wCAAwC;AAAA,EAC9D,MAAM,OAAO,QAAQ,QACnB,uDACA,GAAG;AAAA,oDACL;AAAA,EAEA,MAAM,SAAS,IAAI,MAAM;AAAA,IACvB,MAAM;AAAA,IACN,KAAK,CAAC,KAAK;AAAA,MACT,MAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAAA,MAC3B,IAAI,IAAI,aAAa,OAAO,IAAI,aAAa,eAAe;AAAA,QAC1D,OAAO,IAAI,SAAS,MAAM;AAAA,UACxB,SAAS,EAAE,gBAAgB,2BAA2B;AAAA,QACxD,CAAC;AAAA,MACH;AAAA,MACA,IAAI,IAAI,aAAa,YAAY;AAAA,QAC/B,OAAO,IAAI,SAAS,QAAQ;AAAA,UAC1B,SAAS,EAAE,gBAAgB,wCAAwC;AAAA,QACrE,CAAC;AAAA,MACH;AAAA,MACA,OAAO,IAAI,SAAS,aAAa,EAAE,QAAQ,IAAI,CAAC;AAAA;AAAA,EAEpD,CAAC;AAAA,EAED,OAAO;AAAA,IACL,KAAK,oBAAoB,OAAO;AAAA,IAChC,OAAO,YAAY;AAAA,MACjB,OAAO,KAAK;AAAA;AAAA,EAEhB;AAAA;;AC5FF,eAAsB,cAAc,CAClC,SACiB;AAAA,EACjB,IAAI,CAAC;AAAA,IAAS,OAAO;AAAA,EACrB,IAAI;AAAA,IACF,OAAO;AAAA;AAAA,aAAkB,MAAM,QAAQ;AAAA,IACvC,OAAO,KAAK;AAAA,IACZ,OAAO;AAAA;AAAA,6BAAkC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA;AAAA;;;ACkB5F,eAAe,gBAAgB,CAAC,MAA2C;AAAA,EACzE,OAAO,KAAK,KACT,SAAS,MAAM;AAAA,IACd,MAAM,UAAU,MAAM,KAAK,SAAS,iBAAiB,iBAAiB,CAAC;AAAA,IACvE,MAAM,QAAQ,QAAQ,IAAI,CAAC,OAAO,GAAG,eAAe,EAAE;AAAA,IACtD,MAAM,gBAAgB,SAAS,cAAc,yBAAyB,GAAG,eAAe;AAAA,IACxF,MAAM,SAAS,SAAS,cAAc,qBAAqB,GAAG,eAAe;AAAA,IAC7E,OAAO,EAAE,OAAO,WAAW,OAAO,aAAa,KAAK,GAAG,OAAO;AAAA,GAC/D,EACA,KAAK,CAAC,UAAU,EAAE,QAAQ,KAAK,WAAW,KAAK,EAAE;AAAA;AAMtD,eAAsB,kBAAkB,CACtC,OACA,WACA,UAAqC,CAAC,GACvB;AAAA,EACf,QAAQ,YAAY,OAAQ,SAAS,QAAQ;AAAA,EAC7C,MAAM,WAAW,KAAK,IAAI,IAAI;AAAA,EAC9B,IAAI,gBAAgC,CAAC;AAAA,EAErC,OAAO,KAAK,IAAI,IAAI,UAAU;AAAA,IAC5B,MAAM,YAAY,MAAM,QAAQ,IAAI,MAAM,IAAI,gBAAgB,CAAC;AAAA,IAC/D,gBAAgB;AAAA,IAChB,IAAI,UAAU,MAAM,SAAS;AAAA,MAAG;AAAA,IAChC,MAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC;AAAA,EAChD;AAAA,EAEA,MAAM,UAAU,cACb,IACC,CAAC,MACC,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,mBAAmB,KAAK,UAAU,EAAE,KAAK,GAChG,EACC,KAAK;AAAA,CAAI;AAAA,EACZ,MAAM,YAAY,MAAM,eAAe,QAAQ,OAAO;AAAA,EACtD,MAAM,IAAI,MACR,oEAAoE;AAAA,EAAiB,UAAU,WACjG;AAAA;AAQF,eAAsB,oBAAoB,CACxC,OACA,UAAqC,CAAC,GACvB;AAAA,EACf,MAAM,WAAW,MAAM,SAAS;AAAA,EAChC,MAAM,mBAAmB,OAAO,CAAC,aAAa,SAAS,aAAa,UAAU,OAAO;AAAA;;ACzEvF,mBAAS;;;AC8BT;AA2FO,SAAS,eAAe,CAAC,UAAkC,CAAC,GAAG;AAAA,EACpE,MAAM,OAAO,QAAQ,QAAQ;AAAA,EAC7B,MAAM,gBAAgB,QAAQ;AAAA,EAK9B,MAAM,cAAc,IAAI;AAAA,EAIxB,MAAM,eAAe,CAAC,QAA+C;AAAA,IACnE,IAAI;AAAA,MACF,OAAO,OAAO,QAAQ,WAAW,KAAK,MAAM,GAAG,IAAK;AAAA,MACpD,MAAM;AAAA,MACN;AAAA;AAAA;AAAA,EAIJ,MAAM,aAAa,CAAC,IAAa,WAAyB;AAAA,IACxD,MAAM,WAAW;AAAA,IAKjB,MAAM,aAAgF,CAAC;AAAA,IACvF,YAAY,gBAAgB,mBAAmB,aAAa;AAAA,MAC1D,IAAI,mBAAmB;AAAA,QAAQ;AAAA,MAC/B,WAAW,KAAK,EAAE,QAAQ,gBAAgB,QAAQ,eAAe,CAAC;AAAA,IACpE;AAAA,IACA,YAAY,IAAI,QAAQ,QAAQ;AAAA,IAChC,MAAM,aAAa;AAAA,IACnB,WAAW,KAAK,SAAS;AAAA,IAEzB,SAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,SAAS,WAAW,IAAI,CAAC,MAAM,EAAE,MAAM;AAAA,IACzC,CAAgC;AAAA,IAEhC,WAAW,aAAa,YAAY;AAAA,MAClC,IAAI;AAAA,QACF,UAAU,OAAO,KAAK,EAAE,MAAM,eAAe,OAAO,CAAgC;AAAA,QACpF,MAAM;AAAA,IAKV;AAAA;AAAA,EAGF,MAAM,oBAAoB,CAAC,IAAa,iBAA+B;AAAA,IACpE,GAAiD,KAAK;AAAA,MACrD,MAAM;AAAA,MACN,QAAQ;AAAA,MACR;AAAA,IACF,CAAgC;AAAA;AAAA,EAIlC,MAAM,iBAAiB,CAAC,iBAAuE;AAAA,IAC7F,MAAM,SAAS,YAAY,IAAI,YAAY;AAAA,IAC3C,IAAI,CAAC;AAAA,MAAQ;AAAA,IACb,MAAM,aAAc,OAA8C;AAAA,IAClE,MAAM,OAAO;AAAA,IACb,IAAI,eAAe,aAAa,eAAe,MAAM;AAAA,MACnD,YAAY,OAAO,YAAY;AAAA,MAC/B;AAAA,IACF;AAAA,IACA,OAAO;AAAA;AAAA,EAGT,MAAM,eAAe,CAAC,IAAa,QAA6D;AAAA,IAC9F,MAAM,aAAa;AAAA,IAInB,MAAM,WAAW,WAAW,KAAK;AAAA,IACjC,IAAI,CAAC,UAAU;AAAA,MACb,WAAW,KAAK,EAAE,MAAM,SAAS,QAAQ,aAAa,CAAgC;AAAA,MACtF;AAAA,IACF;AAAA,IACA,MAAM,SAAS,eAAe,IAAI,YAAY;AAAA,IAC9C,IAAI,CAAC,QAAQ;AAAA,MACX,kBAAkB,IAAI,IAAI,YAAY;AAAA,MACtC;AAAA,IACF;AAAA,IACA,MAAM,UAA4B;AAAA,MAChC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,cAAc,IAAI;AAAA,MAClB,SAAS,IAAI;AAAA,IACf;AAAA,IACA,IAAI;AAAA,MACF,OAAO,KAAK,OAAO;AAAA,MACnB,MAAM;AAAA,MACN,YAAY,OAAO,IAAI,YAAY;AAAA,MACnC,kBAAkB,IAAI,IAAI,YAAY;AAAA;AAAA;AAAA,EAI1C,OAAO,IAAI,OAAO,EAAE,GAAG,MAAM;AAAA,IAC3B,OAAO,CAAC,IAAI,KAAK;AAAA,MACf,MAAM,MAAM,aAAa,GAAG;AAAA,MAC5B,IAAI,CAAC,KAAK;AAAA,QACR,GAAG,KAAK,EAAE,MAAM,SAAS,QAAQ,YAAY,CAAgC;AAAA,QAC7E;AAAA,MACF;AAAA,MACA,IAAI,IAAI,SAAS,QAAQ;AAAA,QACvB,WAAW,IAAI,IAAI,MAAM;AAAA,QACzB;AAAA,MACF;AAAA,MACA,IAAI,IAAI,SAAS,UAAU;AAAA,QACzB,aAAa,IAAI,GAAG;AAAA,QACpB;AAAA,MACF;AAAA,MAKA,IAAI,kBAAkB,WAAW;AAAA,QAC/B,MAAM,aAAa;AAAA,QACnB,MAAM,WAAW,WAAW,KAAK;AAAA,QACjC,MAAM,SAAS,OAAO,aAAa,WAAW,WAAW;AAAA,QACzD,cAAc,YAAY,KAAwC,MAAM;AAAA,QACxE;AAAA,MACF;AAAA,MACA,GAAG,KAAK,EAAE,MAAM,SAAS,QAAQ,YAAY,CAAgC;AAAA;AAAA,IAG/E,KAAK,CAAC,IAAI;AAAA,MACR,MAAM,SAAU,GAAG,KAA4C;AAAA,MAG/D,IAAI,CAAC,QAAQ;AAAA,QAGX;AAAA,MACF;AAAA,MAOA,MAAM,SAAS,YAAY,IAAI,MAAM;AAAA,MACrC,MAAM,SAAU,GAAoD;AAAA,MACpE,MAAM,aAAc,QAChB;AAAA,MACJ,IAAI,WAAW,aAAa,eAAe,QAAQ;AAAA,QACjD;AAAA,MACF;AAAA,MACA,YAAY,OAAO,MAAM;AAAA,MACzB,YAAY,cAAc,oBAAoB,aAAa;AAAA,QACzD,IAAI;AAAA,UACF,gBAAgB,KAAK,EAAE,MAAM,aAAa,OAAO,CAAgC;AAAA,UACjF,MAAM;AAAA,MAGV;AAAA;AAAA,EAEJ,CAAC;AAAA;;;ADlQH,SAAS,QAAQ,GAAW;AAAA,EAI1B,OAAO,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,GAAK;AAAA;AAgBjD,eAAsB,SAAS,CAAC,UAA4B,CAAC,GAA6B;AAAA,EACxF,MAAM,OAAO,QAAQ,QAAQ;AAAA,EAC7B,MAAM,OAAO,QAAQ,QAAQ;AAAA,EAE7B,IAAI,SAAS,OAAO;AAAA,IAClB,MAAM,OAAM,QAAQ,IAAI;AAAA,IACxB,IAAI,CAAC,MAAK;AAAA,MACR,MAAM,IAAI,MACR,iFACF;AAAA,IACF;AAAA,IACA,OAAO;AAAA,MACL;AAAA,MACA,OAAO,YAAY;AAAA,IAGrB;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,SAAS;AAAA,EACtB,MAAM,MAAM,IAAI,QAAO,EAAE,IAAI,gBAAgB,EAAE,KAAK,CAAC,CAAC,EAAE,OAAO,IAAI;AAAA,EACnE,MAAM,MAAM,kBAAkB,OAAO;AAAA,EAErC,OAAO;AAAA,IACL;AAAA,IACA,OAAO,YAAY;AAAA,MAKf,IAGA,QAAQ,OAAO,IAAI;AAAA;AAAA,EAEzB;AAAA;",
|
|
21
|
-
"debugId": "
|
|
21
|
+
"mappings": "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",
|
|
22
|
+
"debugId": "4C0664CE1341DDA664756E2164756E21",
|
|
22
23
|
"names": []
|
|
23
24
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* driving the relay through `withRelay` exercises the production protocol
|
|
7
7
|
* with no shimming. Two modes:
|
|
8
8
|
*
|
|
9
|
-
* - "embedded" (default): start an Elysia app on a
|
|
9
|
+
* - "embedded" (default): start an Elysia app on a kernel-assigned port and return
|
|
10
10
|
* its URL plus a close callback. The hermetic mode the suite runs in
|
|
11
11
|
* by default; depending on a staging relay would couple CI reliability
|
|
12
12
|
* to a network service we do not control.
|