@fairfox/polly 0.28.0 → 0.29.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/elysia/index.js +9 -1
- package/dist/src/elysia/index.js.map +3 -3
- package/dist/src/elysia/signaling-server-plugin.d.ts +25 -0
- package/dist/src/mesh.js +74 -28
- package/dist/src/mesh.js.map +3 -3
- package/dist/src/shared/lib/mesh-signaling-client.d.ts +34 -0
- package/dist/tools/test/src/browser/run.js +9 -1
- package/dist/tools/test/src/browser/run.js.map +3 -3
- package/package.json +1 -1
package/dist/src/elysia/index.js
CHANGED
|
@@ -333,6 +333,7 @@ function polly(config = {}) {
|
|
|
333
333
|
import { Elysia as Elysia3 } from "elysia";
|
|
334
334
|
function signalingServer(options = {}) {
|
|
335
335
|
const path = options.path ?? "/polly/signaling";
|
|
336
|
+
const onCustomFrame = options.onCustomFrame;
|
|
336
337
|
const peerSockets = new Map;
|
|
337
338
|
const parseMessage = (raw) => {
|
|
338
339
|
try {
|
|
@@ -421,6 +422,13 @@ function signalingServer(options = {}) {
|
|
|
421
422
|
handleSignal(ws, msg);
|
|
422
423
|
return;
|
|
423
424
|
}
|
|
425
|
+
if (onCustomFrame !== undefined) {
|
|
426
|
+
const wsWithData = ws;
|
|
427
|
+
const senderId = wsWithData.data["peerId"];
|
|
428
|
+
const peerId = typeof senderId === "string" ? senderId : undefined;
|
|
429
|
+
onCustomFrame(wsWithData, msg, peerId);
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
424
432
|
ws.send({ type: "error", reason: "malformed" });
|
|
425
433
|
},
|
|
426
434
|
close(ws) {
|
|
@@ -449,4 +457,4 @@ export {
|
|
|
449
457
|
peerRepo
|
|
450
458
|
};
|
|
451
459
|
|
|
452
|
-
//# debugId=
|
|
460
|
+
//# debugId=2084E79965BF116064756E2164756E21
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
"// @ts-nocheck - Optional peer dependencies (elysia, @elysiajs/eden)\nimport type { Signal } from \"@preact/signals-core\";\nimport { Elysia } from \"elysia\";\nimport { createLamportClock } from \"../core/clock\";\nimport { serializeFunction } from \"../utils/function-serialization\";\nimport type { PollyConfig, PollyResponseMetadata } from \"./types\";\n\n/**\n * Broadcast message sent to connected clients\n */\ninterface BroadcastMessage {\n type: \"effect\";\n path: string;\n method: string;\n result: unknown;\n clock: { tick: number; contextId: string };\n}\n\n/**\n * Minimal WebSocket interface for broadcasting\n */\ninterface MinimalWebSocket {\n readyState: number;\n send(data: string): void;\n}\n\n/**\n * Route pattern matcher\n * Supports:\n * - Exact match: 'POST /todos'\n * - Param match: 'GET /todos/:id'\n * - Wildcard: '/todos/*'\n */\nfunction matchRoute(pattern: string, method: string, path: string): boolean {\n // Split pattern into method + path or just path\n const hasMethod = pattern.includes(\" \");\n const patternMethod = hasMethod ? pattern.split(\" \")[0] : null;\n const patternPath = hasMethod ? pattern.split(\" \")[1] : pattern;\n\n // Check method\n if (patternMethod && patternMethod !== method) {\n return false;\n }\n\n // Check path\n const patternSegments = patternPath.split(\"/\").filter(Boolean);\n const pathSegments = path.split(\"/\").filter(Boolean);\n\n if (patternSegments.length !== pathSegments.length && !patternPath.includes(\"*\")) {\n return false;\n }\n\n for (let i = 0; i < patternSegments.length; i++) {\n const patternSeg = patternSegments[i];\n const pathSeg = pathSegments[i];\n\n if (patternSeg === \"*\") return true;\n if (patternSeg.startsWith(\":\")) continue; // Param match\n if (patternSeg !== pathSeg) return false;\n }\n\n return true;\n}\n\n/**\n * Find matching config for a route\n */\nfunction findMatchingConfig<T>(\n configs: Record<string, T> | undefined,\n method: string,\n path: string\n): T | undefined {\n if (!configs) return undefined;\n\n for (const [pattern, config] of Object.entries(configs)) {\n if (matchRoute(pattern, method, path)) {\n return config;\n }\n }\n\n return undefined;\n}\n\n/**\n * WebSocket broadcast manager\n */\nclass BroadcastManager {\n private connections = new Map<string, MinimalWebSocket>();\n\n register(clientId: string, ws: MinimalWebSocket) {\n this.connections.set(clientId, ws);\n }\n\n unregister(clientId: string) {\n this.connections.delete(clientId);\n }\n\n broadcast(message: BroadcastMessage, filter?: (clientId: string) => boolean) {\n const payload = JSON.stringify(message);\n\n for (const [clientId, ws] of this.connections.entries()) {\n if (filter && !filter(clientId)) continue;\n if (ws.readyState === 1) {\n // WebSocket.OPEN = 1\n ws.send(payload);\n }\n }\n }\n}\n\n/**\n * Main Polly Elysia plugin\n */\nexport function polly(config: PollyConfig = {}) {\n const isDev = process.env.NODE_ENV !== \"production\";\n const clock = createLamportClock(\"server\");\n const broadcaster = new BroadcastManager();\n const clientStateByConnection = new Map<string, Record<string, Signal<unknown>>>();\n\n const app = new Elysia({ name: \"polly\" })\n // Add state to context\n .decorate(\"pollyState\", {\n client: config.state?.client || {},\n server: config.state?.server || {},\n })\n .decorate(\"pollyClock\", clock)\n .decorate(\"pollyBroadcast\", broadcaster)\n\n // WebSocket endpoint for real-time updates\n .ws(config.websocketPath || \"/polly/ws\", {\n // @ts-expect-error - Elysia WebSocket types from optional peer dependency\n open(ws) {\n const clientId = ws.data.headers?.[\"x-client-id\"] || crypto.randomUUID();\n broadcaster.register(clientId, ws.raw);\n\n // Send initial state sync\n ws.send(\n JSON.stringify({\n type: \"state-sync\",\n state: config.state?.client || {},\n clock: clock.now(),\n })\n );\n },\n // @ts-expect-error - Elysia WebSocket types from optional peer dependency\n close(ws) {\n const clientId = ws.data.headers?.[\"x-client-id\"];\n if (clientId) {\n broadcaster.unregister(clientId);\n clientStateByConnection.delete(clientId);\n }\n },\n // @ts-expect-error - Elysia WebSocket types from optional peer dependency\n message(ws, message) {\n // Handle client state updates\n const data = JSON.parse(message as unknown as string);\n\n if (data.type === \"state-update\") {\n const clientId = ws.data.headers?.[\"x-client-id\"];\n if (clientId) {\n clientStateByConnection.set(clientId, data.state);\n }\n }\n },\n })\n\n // Authorization hook (runs before handler)\n // @ts-expect-error - Elysia context types from optional peer dependency\n .onBeforeHandle(async ({ request, pollyState, body, params }) => {\n const method = request.method;\n const path = new URL(request.url).pathname;\n\n const authHandler = findMatchingConfig(config.authorization, method, path);\n\n if (authHandler) {\n const allowed = await authHandler({\n state: pollyState,\n body,\n params,\n headers: Object.fromEntries(request.headers.entries()),\n });\n\n if (!allowed) {\n return new Response(\"Unauthorized\", { status: 403 });\n }\n }\n })\n\n // Response hook (runs after handler)\n // @ts-expect-error - Elysia context types from optional peer dependency\n .onAfterHandle(\n async ({ request, response, _pollyState, pollyClock, pollyBroadcast, _body, _params }) => {\n const method = request.method;\n const path = new URL(request.url).pathname;\n\n // Find matching effect config\n const effectConfig = findMatchingConfig(config.effects, method, path);\n\n // Tick clock\n pollyClock.tick();\n\n // If broadcast enabled, send to all connected clients\n // This works in both dev and prod for real-time updates\n if (effectConfig?.broadcast) {\n const broadcastMessage = {\n type: \"effect\",\n path,\n method,\n result: response,\n clock: pollyClock.now(),\n };\n\n if (effectConfig.broadcastFilter) {\n pollyBroadcast.broadcast(broadcastMessage, (clientId) => {\n const clientState = clientStateByConnection.get(clientId) || {};\n return effectConfig.broadcastFilter?.(clientState) ?? false;\n });\n } else {\n pollyBroadcast.broadcast(broadcastMessage);\n }\n }\n\n // In production, skip expensive metadata operations\n if (!isDev) {\n return response;\n }\n\n // DEV ONLY: Add Polly metadata to response for debugging/hot-reload\n const offlineConfig = findMatchingConfig(config.offline, method, path);\n const metadata: PollyResponseMetadata = {\n clientEffect: effectConfig\n ? {\n handler: serializeFunction(effectConfig.client),\n broadcast: effectConfig.broadcast || false,\n }\n : undefined,\n offline: offlineConfig,\n clock: pollyClock.now(),\n };\n\n // Attach metadata as header\n return new Response(JSON.stringify(response), {\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Polly-Metadata\": JSON.stringify(metadata),\n },\n });\n }\n );\n\n return app;\n}\n",
|
|
8
8
|
"/**\n * Lamport Clock Implementation\n *\n * Provides logical timestamps for distributed systems to establish\n * causal ordering of events across different contexts (client/server).\n *\n * Key properties:\n * - Each event increments the local clock\n * - When receiving a message, clock = max(local, received) + 1\n * - If A happens before B, then timestamp(A) < timestamp(B)\n *\n * References:\n * - Lamport, L. (1978). \"Time, Clocks, and the Ordering of Events in a Distributed System\"\n * - https://lamport.azurewebsites.net/pubs/time-clocks.pdf\n */\n\n/**\n * Lamport clock state\n */\nexport interface LamportClock {\n tick: number;\n contextId: string;\n}\n\n/**\n * Lamport clock with operations\n */\nexport interface LamportClockOps {\n /**\n * Get current clock value\n */\n now(): LamportClock;\n\n /**\n * Increment the clock (before sending a message or performing an action)\n */\n tick(): number;\n\n /**\n * Update clock when receiving a message\n * Sets clock to max(local, received) + 1\n */\n update(receivedClock: LamportClock): void;\n}\n\n/**\n * Create a Lamport clock for a specific context\n *\n * @param contextId - Unique identifier for this context (e.g., \"client\", \"server\", \"worker-1\")\n * @returns Clock operations\n *\n * @example\n * ```typescript\n * const serverClock = createLamportClock(\"server\");\n *\n * // Before sending a message\n * serverClock.tick();\n * const timestamp = serverClock.now();\n * send({ data: \"...\", clock: timestamp });\n *\n * // When receiving a message\n * onReceive((message) => {\n * serverClock.update(message.clock);\n * // Process message with updated clock\n * });\n * ```\n */\nexport function createLamportClock(contextId: string): LamportClockOps {\n let tick = 0;\n\n return {\n now(): LamportClock {\n return { tick, contextId };\n },\n\n tick(): number {\n tick += 1;\n return tick;\n },\n\n update(receivedClock: LamportClock): void {\n tick = Math.max(tick, receivedClock.tick) + 1;\n },\n };\n}\n",
|
|
9
9
|
"import serialize from \"serialize-javascript\";\n\n/**\n * Check if we're in development mode\n */\nconst isDev = process.env.NODE_ENV !== \"production\";\n\n/**\n * Serialize a function to send to client\n *\n * DEV ONLY: Used for hot reloading and debugging\n * PROD: No-op - client effects are baked into bundle at build time\n */\n// biome-ignore lint/complexity/noBannedTypes: Generic function serialization requires Function type\nexport function serializeFunction(fn: Function): string {\n if (!isDev) {\n // In production, return empty string - this won't be used\n return \"\";\n }\n\n return serialize(fn, { space: 0 });\n}\n\n/**\n * Deserialize a function received from server\n *\n * DEV ONLY: Eval serialized function source\n * PROD: Should never be called - effects come from bundle\n */\n// biome-ignore lint/complexity/noBannedTypes: Generic function deserialization requires Function type\nexport function deserializeFunction(serialized: string): Function {\n if (!isDev) {\n throw new Error(\n \"[Polly] deserializeFunction should not be called in production. \" +\n \"Client effects should be imported from your bundle.\"\n );\n }\n\n if (!serialized) {\n throw new Error(\"[Polly] Cannot deserialize empty function\");\n }\n\n // biome-ignore lint/security/noGlobalEval: Required for dev-mode function deserialization\n return eval(`(${serialized})`);\n}\n",
|
|
10
|
-
"// @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\nexport interface SignalingServerOptions {\n /** WebSocket route path. Defaults to \"/polly/signaling\". */\n path?: string;\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 // 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 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"
|
|
10
|
+
"// @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"
|
|
11
11
|
],
|
|
12
|
-
"mappings": "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
|
|
13
|
-
"debugId": "
|
|
12
|
+
"mappings": "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",
|
|
13
|
+
"debugId": "2084E79965BF116064756E2164756E21",
|
|
14
14
|
"names": []
|
|
15
15
|
}
|
|
@@ -86,9 +86,34 @@ export type SignalingMessage = {
|
|
|
86
86
|
type: "peer-left";
|
|
87
87
|
peerId: string;
|
|
88
88
|
};
|
|
89
|
+
/** A frame whose `type` is outside the built-in signalling vocabulary.
|
|
90
|
+
* Consumers who pass an {@link SignalingServerOptions.onCustomFrame}
|
|
91
|
+
* handler receive these on the server side; everything else — including
|
|
92
|
+
* routing them to a specific peer, storing a session, or rejecting the
|
|
93
|
+
* frame — is the consumer's call. Polly does not touch the body. */
|
|
94
|
+
export interface CustomSignalingFrame {
|
|
95
|
+
type: string;
|
|
96
|
+
[key: string]: unknown;
|
|
97
|
+
}
|
|
98
|
+
/** Minimal surface the custom-frame handler receives in place of the
|
|
99
|
+
* Elysia-specific `ws` object so the plugin stays portable. Exposes the
|
|
100
|
+
* `data` bag (used to stash the authenticated peerId under the existing
|
|
101
|
+
* join handshake) and a `send` method. */
|
|
102
|
+
export interface CustomFrameSocket {
|
|
103
|
+
data: Record<string, unknown>;
|
|
104
|
+
send: (msg: unknown) => void;
|
|
105
|
+
}
|
|
89
106
|
export interface SignalingServerOptions {
|
|
90
107
|
/** WebSocket route path. Defaults to "/polly/signaling". */
|
|
91
108
|
path?: string;
|
|
109
|
+
/** Optional hook for frames whose `type` is outside the built-in
|
|
110
|
+
* vocabulary. The plugin invokes it in place of returning a
|
|
111
|
+
* `malformed` error, so consumers can layer their own application
|
|
112
|
+
* protocol (pairing return tokens, presence pings, etc.) on the
|
|
113
|
+
* existing socket. The `peerId` argument is the sender's
|
|
114
|
+
* authenticated peer id from their prior `join` frame, or
|
|
115
|
+
* `undefined` if they haven't joined yet. */
|
|
116
|
+
onCustomFrame?: (socket: CustomFrameSocket, frame: CustomSignalingFrame, peerId: string | undefined) => void;
|
|
92
117
|
}
|
|
93
118
|
/**
|
|
94
119
|
* Construct the signalling-server Elysia plugin. The plugin keeps a
|
package/dist/src/mesh.js
CHANGED
|
@@ -1163,6 +1163,22 @@ function deserialiseMessage(bytes) {
|
|
|
1163
1163
|
// src/shared/lib/mesh-signaling-client.ts
|
|
1164
1164
|
var RECONNECT_BASE_DELAY_MS = 250;
|
|
1165
1165
|
var RECONNECT_MAX_DELAY_MS = 30000;
|
|
1166
|
+
function parseFrame(raw) {
|
|
1167
|
+
let parsed;
|
|
1168
|
+
try {
|
|
1169
|
+
parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
1170
|
+
} catch {
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
const record = parsed;
|
|
1177
|
+
if (typeof record["type"] !== "string") {
|
|
1178
|
+
return;
|
|
1179
|
+
}
|
|
1180
|
+
return record;
|
|
1181
|
+
}
|
|
1166
1182
|
|
|
1167
1183
|
class MeshSignalingClient {
|
|
1168
1184
|
url;
|
|
@@ -1174,6 +1190,7 @@ class MeshSignalingClient {
|
|
|
1174
1190
|
onPeersPresent;
|
|
1175
1191
|
onPeerJoined;
|
|
1176
1192
|
onPeerLeft;
|
|
1193
|
+
onCustomFrame;
|
|
1177
1194
|
socket;
|
|
1178
1195
|
joined = false;
|
|
1179
1196
|
stopping = false;
|
|
@@ -1195,6 +1212,8 @@ class MeshSignalingClient {
|
|
|
1195
1212
|
this.onPeerJoined = options.onPeerJoined;
|
|
1196
1213
|
if (options.onPeerLeft !== undefined)
|
|
1197
1214
|
this.onPeerLeft = options.onPeerLeft;
|
|
1215
|
+
if (options.onCustomFrame !== undefined)
|
|
1216
|
+
this.onCustomFrame = options.onCustomFrame;
|
|
1198
1217
|
const WS = options.WebSocket ?? globalThis.WebSocket;
|
|
1199
1218
|
if (typeof WS !== "function") {
|
|
1200
1219
|
throw new Error("MeshSignalingClient: no WebSocket implementation found. Pass one via options.WebSocket, or run in an environment where `globalThis.WebSocket` exists (Node 21+, Bun, browsers).");
|
|
@@ -1253,36 +1272,56 @@ class MeshSignalingClient {
|
|
|
1253
1272
|
}, delay);
|
|
1254
1273
|
}
|
|
1255
1274
|
dispatchFrame(raw) {
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
msg = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
1259
|
-
} catch {
|
|
1275
|
+
const record = parseFrame(raw);
|
|
1276
|
+
if (record === undefined) {
|
|
1260
1277
|
return;
|
|
1261
1278
|
}
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
return;
|
|
1267
|
-
case "peers-present":
|
|
1268
|
-
if (Array.isArray(msg.peerIds))
|
|
1269
|
-
this.onPeersPresent?.(msg.peerIds);
|
|
1270
|
-
return;
|
|
1271
|
-
case "peer-joined":
|
|
1272
|
-
if (typeof msg.peerId === "string")
|
|
1273
|
-
this.onPeerJoined?.(msg.peerId);
|
|
1274
|
-
return;
|
|
1275
|
-
case "peer-left":
|
|
1276
|
-
if (typeof msg.peerId === "string")
|
|
1277
|
-
this.onPeerLeft?.(msg.peerId);
|
|
1278
|
-
return;
|
|
1279
|
-
case "error":
|
|
1280
|
-
if (msg.reason)
|
|
1281
|
-
this.onError?.(msg.reason, msg.targetPeerId);
|
|
1282
|
-
return;
|
|
1283
|
-
default:
|
|
1284
|
-
return;
|
|
1279
|
+
const handler = this.builtInHandler(record["type"]);
|
|
1280
|
+
if (handler !== undefined) {
|
|
1281
|
+
handler(record);
|
|
1282
|
+
return;
|
|
1285
1283
|
}
|
|
1284
|
+
this.onCustomFrame?.(record);
|
|
1285
|
+
}
|
|
1286
|
+
builtInHandler(type) {
|
|
1287
|
+
if (type === "signal") {
|
|
1288
|
+
return (record) => {
|
|
1289
|
+
if (typeof record["peerId"] === "string") {
|
|
1290
|
+
this.onSignal(record["peerId"], record["payload"]);
|
|
1291
|
+
}
|
|
1292
|
+
};
|
|
1293
|
+
}
|
|
1294
|
+
if (type === "peers-present") {
|
|
1295
|
+
return (record) => {
|
|
1296
|
+
if (Array.isArray(record["peerIds"])) {
|
|
1297
|
+
this.onPeersPresent?.(record["peerIds"]);
|
|
1298
|
+
}
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
if (type === "peer-joined") {
|
|
1302
|
+
return (record) => {
|
|
1303
|
+
if (typeof record["peerId"] === "string") {
|
|
1304
|
+
this.onPeerJoined?.(record["peerId"]);
|
|
1305
|
+
}
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
if (type === "peer-left") {
|
|
1309
|
+
return (record) => {
|
|
1310
|
+
if (typeof record["peerId"] === "string") {
|
|
1311
|
+
this.onPeerLeft?.(record["peerId"]);
|
|
1312
|
+
}
|
|
1313
|
+
};
|
|
1314
|
+
}
|
|
1315
|
+
if (type === "error") {
|
|
1316
|
+
return (record) => {
|
|
1317
|
+
if (typeof record["reason"] !== "string") {
|
|
1318
|
+
return;
|
|
1319
|
+
}
|
|
1320
|
+
const targetPeerId = typeof record["targetPeerId"] === "string" ? record["targetPeerId"] : undefined;
|
|
1321
|
+
this.onError?.(record["reason"], targetPeerId);
|
|
1322
|
+
};
|
|
1323
|
+
}
|
|
1324
|
+
return;
|
|
1286
1325
|
}
|
|
1287
1326
|
sendSignal(targetPeerId, payload) {
|
|
1288
1327
|
if (!this.socket || this.socket.readyState !== this.WebSocketCtor.OPEN || !this.joined) {
|
|
@@ -1297,6 +1336,13 @@ class MeshSignalingClient {
|
|
|
1297
1336
|
this.socket.send(JSON.stringify(msg));
|
|
1298
1337
|
return true;
|
|
1299
1338
|
}
|
|
1339
|
+
sendCustom(type, payload = {}) {
|
|
1340
|
+
if (!this.socket || this.socket.readyState !== this.WebSocketCtor.OPEN || !this.joined) {
|
|
1341
|
+
return false;
|
|
1342
|
+
}
|
|
1343
|
+
this.socket.send(JSON.stringify({ ...payload, type }));
|
|
1344
|
+
return true;
|
|
1345
|
+
}
|
|
1300
1346
|
close() {
|
|
1301
1347
|
this.stopping = true;
|
|
1302
1348
|
if (this.reconnectTimer) {
|
|
@@ -2547,4 +2593,4 @@ export {
|
|
|
2547
2593
|
$meshCounter
|
|
2548
2594
|
};
|
|
2549
2595
|
|
|
2550
|
-
//# debugId=
|
|
2596
|
+
//# debugId=D3C1A8646491034D64756E2164756E21
|
package/dist/src/mesh.js.map
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"/**\n * mesh-client — first-class factory for constructing a Polly mesh client.\n *\n * The mesh transport stack has five pieces that have to be wired together:\n * a {@link MeshSignalingClient} talking to the relay server, a\n * {@link MeshWebRTCAdapter} that owns the per-peer RTCPeerConnections, a\n * {@link MeshNetworkAdapter} that signs and encrypts every message on the\n * way through, an Automerge `Repo` that drives sync, and a `MeshKeyring`\n * that holds the crypto material. Prior to this module, every consuming\n * application had to assemble the five pieces by hand — and in Node or\n * Bun had to monkey-patch `globalThis.WebSocket` / `globalThis.RTCPeerConnection`\n * because the lower-level primitives reached for those globals.\n *\n * `createMeshClient` takes options, hands back a `MeshClient`, and also\n * calls `configureMeshState(client.repo)` so `$meshState` works without\n * a second setup step. The WebSocket and RTCPeerConnection implementations\n * are injectable; defaults read from `globalThis` for browser ergonomics.\n * The companion `@fairfox/polly/mesh/node` subpath provides a CLI bootstrap\n * helper that wires werift (or `@roamhq/wrtc` if the consumer prefers) and\n * a file-backed keyring store.\n */\n\nimport { type PeerId, Repo, type StorageAdapterInterface } from \"@automerge/automerge-repo/slim\";\nimport type { KeyringStorage } from \"./keyring-storage\";\nimport { DEFAULT_MESH_KEY_ID, type MeshKeyring, MeshNetworkAdapter } from \"./mesh-network-adapter\";\nimport { MeshSignalingClient, type MeshSignalingClientOptions } from \"./mesh-signaling-client\";\nimport { configureMeshState } from \"./mesh-state\";\nimport { MeshWebRTCAdapter, type MeshWebRTCAdapterOptions } from \"./mesh-webrtc-adapter\";\n\n/** Options for {@link createMeshClient}. */\nexport interface CreateMeshClientOptions {\n /** Signalling-server configuration. `peerId` must be the same identity\n * this client's keyring was paired with on other peers. */\n signaling: {\n url: string;\n peerId: string;\n /** Optional WebSocket ctor override (e.g. `ws` on old Node). Defaults\n * to `globalThis.WebSocket`. */\n WebSocket?: MeshSignalingClientOptions[\"WebSocket\"];\n /** Forwarded error callback for diagnostic UI. */\n onError?: MeshSignalingClientOptions[\"onError\"];\n };\n /** WebRTC configuration. On browsers the defaults are fine; in Node or\n * Bun pass the `RTCPeerConnection` ctor from `werift` or `@roamhq/wrtc`. */\n rtc?: {\n RTCPeerConnection?: MeshWebRTCAdapterOptions[\"RTCPeerConnection\"];\n iceServers?: RTCIceServer[];\n dataChannelLabel?: string;\n };\n /** The local peer's keyring — either a fully-constructed instance, or a\n * persistence adapter to load one from. When a storage adapter is given\n * and `storage.load()` resolves to `null`, the factory throws with a\n * message pointing at the bootstrap helper in `@fairfox/polly/mesh/node`;\n * we deliberately do not generate an identity silently. */\n keyring: MeshKeyring | { storage: KeyringStorage };\n /** Optional Automerge-Repo storage adapter. Applications that want\n * durable local state pass an IndexedDB adapter in browsers or a\n * filesystem adapter in Node; omitting it keeps the Repo in-memory. */\n repoStorage?: StorageAdapterInterface;\n /** When `false`, signs but does not encrypt. Defaults to `true` — the\n * full $meshState posture where the server is off the data path. */\n encryptionEnabled?: boolean;\n}\n\n/** Handle returned by {@link createMeshClient}. */\nexport interface MeshClient {\n /** The Automerge Repo. `$meshState` has already been configured against\n * this repo, so primitives just work — but the repo is exposed in case\n * the application needs it directly (server-side cron, bulk exports,\n * migration tools). */\n repo: Repo;\n /** The configured keyring. Exposed so the application can inspect or\n * mutate it (add authorised peers, apply revocations) and then\n * re-persist via its storage. */\n keyring: MeshKeyring;\n /** The signalling client. Exposed for applications that need to hook\n * lifecycle events or send custom signalling payloads. */\n signaling: MeshSignalingClient;\n /** The WebRTC network adapter. Exposed for advanced use (blob store\n * wiring, peer-connection introspection). */\n networkAdapter: MeshNetworkAdapter;\n /** The underlying WebRTC adapter wrapped by {@link networkAdapter}. */\n webrtcAdapter: MeshWebRTCAdapter;\n /** Close the signalling WebSocket, tear down every RTCPeerConnection,\n * and shut the Repo cleanly. Idempotent. */\n close(): Promise<void>;\n}\n\n/**\n * Construct a fully-wired mesh client. Resolves once the signalling\n * connection is open and the Repo is ready to mutate documents; WebRTC\n * peer connections negotiate asynchronously in the background.\n */\nexport async function createMeshClient(options: CreateMeshClientOptions): Promise<MeshClient> {\n const keyring = await resolveKeyring(options.keyring);\n const encryptionEnabled = options.encryptionEnabled ?? true;\n\n // A mesh keyring must carry the per-Repo document key used by\n // MeshNetworkAdapter's encryption layer. We fail loud rather than\n // silently disable encryption when encryptionEnabled is true.\n if (encryptionEnabled && !keyring.documentKeys.has(DEFAULT_MESH_KEY_ID)) {\n throw new Error(\n `createMeshClient: encryption is enabled but the keyring has no document key for \"${DEFAULT_MESH_KEY_ID}\". Bootstrap or apply a pairing token that carries the document key before connecting.`\n );\n }\n\n const knownPeerIds = [...keyring.knownPeers.keys()].filter(\n (id) => id !== options.signaling.peerId\n );\n\n const webrtcAdapterOptions: MeshWebRTCAdapterOptions = {\n signaling: undefined as unknown as MeshSignalingClient, // wired after signaling construction\n peerId: options.signaling.peerId,\n knownPeerIds,\n ...(options.rtc?.iceServers !== undefined && { iceServers: options.rtc.iceServers }),\n ...(options.rtc?.dataChannelLabel !== undefined && {\n dataChannelLabel: options.rtc.dataChannelLabel,\n }),\n ...(options.rtc?.RTCPeerConnection !== undefined && {\n RTCPeerConnection: options.rtc.RTCPeerConnection,\n }),\n };\n\n // The signalling client needs a handleSignal callback, but that callback\n // lives on the WebRTC adapter — which itself wants a reference to the\n // signalling client for sending answers. Break the cycle by letting the\n // signalling client's callbacks reach the adapter through a closure\n // over `webrtcAdapter`, which is assigned immediately below. The same\n // closure pattern wires the peer-discovery callbacks\n // (onPeersPresent / onPeerJoined / onPeerLeft) through to the adapter's\n // dispatch methods.\n let webrtcAdapter: MeshWebRTCAdapter | undefined;\n const signaling = new MeshSignalingClient({\n url: options.signaling.url,\n peerId: options.signaling.peerId,\n ...(options.signaling.WebSocket !== undefined && { WebSocket: options.signaling.WebSocket }),\n ...(options.signaling.onError !== undefined && { onError: options.signaling.onError }),\n onSignal: (fromPeerId, payload) => {\n webrtcAdapter?.handleSignal(fromPeerId, payload);\n },\n onPeersPresent: (peerIds) => {\n webrtcAdapter?.handlePeersPresent(peerIds);\n },\n onPeerJoined: (peerId) => {\n webrtcAdapter?.handlePeerJoined(peerId);\n },\n onPeerLeft: (peerId) => {\n webrtcAdapter?.handlePeerLeft(peerId);\n },\n });\n\n webrtcAdapterOptions.signaling = signaling;\n webrtcAdapter = new MeshWebRTCAdapter(webrtcAdapterOptions);\n\n const networkAdapter = new MeshNetworkAdapter({\n base: webrtcAdapter,\n keyring,\n encryptionEnabled,\n });\n\n // The Repo's peerId MUST match the mesh peer id we signed the keyring\n // against. Automerge would otherwise auto-generate a random \"peer-xxxxx\"\n // identifier, and `MeshNetworkAdapter`'s outgoing envelope would carry\n // that auto-id as its `senderId` — a value the remote keyring has never\n // seen and cannot look up in `knownPeers`. Every message would then fail\n // signature verification silently, and no `$meshState` sync would ever\n // apply.\n const repo = new Repo({\n network: [networkAdapter],\n peerId: options.signaling.peerId as unknown as PeerId,\n ...(options.repoStorage !== undefined && { storage: options.repoStorage }),\n });\n\n configureMeshState(repo);\n\n await signaling.connect();\n\n return {\n repo,\n keyring,\n signaling,\n networkAdapter,\n webrtcAdapter,\n close: async () => {\n signaling.close();\n webrtcAdapter?.disconnect();\n await repo.shutdown();\n },\n };\n}\n\nasync function resolveKeyring(\n source: MeshKeyring | { storage: KeyringStorage }\n): Promise<MeshKeyring> {\n if (\"storage\" in source) {\n const loaded = await source.storage.load();\n if (loaded === null) {\n throw new Error(\n \"createMeshClient: keyring storage returned null (no saved keyring). In a Node CLI, bootstrap with `bootstrapCliKeyring` from `@fairfox/polly/mesh/node`; in a browser, run your pairing flow first and save the keyring through the storage adapter before constructing the client.\"\n );\n }\n return loaded;\n }\n return source;\n}\n",
|
|
14
14
|
"/**\n * mesh-network-adapter — Phase 2 wrapping NetworkAdapter that adds Polly's\n * mesh-transport semantics on top of any underlying Automerge NetworkAdapter.\n *\n * The mesh transport's job is to make every message between peers signed\n * and encrypted before it reaches the wire. Rather than reimplementing the\n * Automerge sync protocol, this adapter takes a base adapter (in production\n * a real WebRTC or WebSocket adapter; in tests an in-memory loopback) and\n * applies the crypto envelope to every message that flows through.\n *\n * Outgoing path (Repo → wire):\n * 1. The Repo's NetworkSubsystem calls send(message) on this adapter.\n * 2. We serialise the message to bytes, encrypt them under the local\n * keyring's document key, sign the resulting blob with the local\n * identity's secret key, and pack the pair into a MeshFrame.\n * 3. We hand the MeshFrame off to the base adapter, which puts it on\n * whatever wire it owns.\n *\n * Incoming path (wire → Repo):\n * 1. The base adapter emits a 'message' event with bytes from the wire.\n * 2. We unpack the MeshFrame, look up the sender's public key in the\n * keyring, verify the signature, look up the document key, decrypt\n * the payload, and deserialise it back to the original message.\n * 3. We re-emit the 'message' event upward to the Repo's NetworkSubsystem\n * with the decrypted message.\n *\n * The keyring is an injected dependency. In production it's backed by\n * persistent storage and populated through the pairing flow. For tests it\n * is just a Map of publicly-known fixtures that both sides share.\n *\n * Caveat for the Phase 2 first cut: Automerge sync messages don't have a\n * stable \"what document does this belong to\" field at the wire level (the\n * documentId is part of the message contents). The mesh adapter therefore\n * uses a single per-Repo encryption key for now rather than per-document\n * keys, and stores the key once in the keyring under the well-known id\n * \"polly-mesh-default\". The plan describes per-document keys as the right\n * end state; that requires either parsing the message to extract the\n * documentId before encrypting (peeking inside the binary protocol) or\n * threading the document context through the network subsystem (which\n * needs upstream support). A follow-up will address this.\n */\n\nimport {\n type Message,\n NetworkAdapter,\n type PeerId,\n type PeerMetadata,\n} from \"@automerge/automerge-repo/slim\";\nimport {\n decodeEncryptedEnvelope,\n encodeEncryptedEnvelope,\n openEnvelope as openEncryptedEnvelope,\n sealEnvelope as sealEncryptedEnvelope,\n} from \"./encryption\";\nimport {\n decodeSignedEnvelope,\n encodeSignedEnvelope,\n openEnvelope as openSignedEnvelope,\n type SigningKeyPair,\n signEnvelope,\n} from \"./signing\";\n\n/** The well-known document id used for the Phase 2 first-cut single-key\n * encryption mode. See the file-level comment for the per-document key\n * follow-up. */\nexport const DEFAULT_MESH_KEY_ID = \"polly-mesh-default\";\n\n/**\n * A mesh keyring holds the local peer's signing identity, the public keys\n * of every peer the local node will accept messages from, the symmetric\n * encryption keys for documents the local node has access to, and the set\n * of peers whose keys have been revoked.\n */\nexport interface MeshKeyring {\n /** The local peer's signing keypair. The secret never leaves this\n * keyring; the public key is gossiped through the access set. */\n identity: SigningKeyPair;\n /** Map from peer id (string) to that peer's signing public key. The\n * mesh adapter rejects messages from peers not present in this map. */\n knownPeers: Map<string, Uint8Array>;\n /** Map from document key id (typically the documentId, or the well-known\n * default for the single-key first cut) to the symmetric encryption key. */\n documentKeys: Map<string, Uint8Array>;\n /** Set of peer ids whose keys have been revoked. The mesh adapter drops\n * incoming messages from any peer in this set, even if the peer is still\n * present in {@link knownPeers}. Revocation is applied via the revocation\n * module; the set is kept separate from knownPeers so that an application\n * can audit who was once authorised without losing the revocation record. */\n revokedPeers: Set<string>;\n /** Optional set of peer ids authorised to issue revocations. When present\n * and non-empty, `decodeRevocation` accepts a signed record only if the\n * issuer is in this set. When undefined or empty, any signed revocation\n * from a known peer is accepted (the Phase 2 first-cut default). This\n * field layers a \"who can revoke whom\" check on top of the signature\n * layer without breaking existing callers. */\n revocationAuthority?: Set<string>;\n}\n\n/**\n * Constructor options for {@link MeshNetworkAdapter}.\n */\nexport interface MeshNetworkAdapterOptions {\n /** The underlying NetworkAdapter that puts crypto-wrapped bytes on the\n * wire. In production this is a WebRTC or WebSocket adapter; in tests\n * it's an in-memory loopback. */\n base: NetworkAdapter;\n /** The local node's keyring. The adapter signs every outgoing message\n * with `identity.secretKey` and verifies every incoming message against\n * the public keys in `knownPeers`. */\n keyring: MeshKeyring;\n /** When false, the adapter signs but does not encrypt. Outgoing messages\n * carry a signature envelope but the payload is plaintext; incoming\n * messages are verified against the sender's public key without a\n * decryption step. This mode is used by $peerState's `sign: true`\n * option, where the server must still be able to parse Automerge sync\n * messages. Defaults to true (encrypt + sign, the full $meshState\n * posture). */\n encryptionEnabled?: boolean;\n}\n\n/**\n * NetworkAdapter that wraps another adapter with Polly's mesh-transport\n * crypto envelope. Every outgoing message is encrypted then signed; every\n * incoming message is verified then decrypted before being forwarded to\n * the Repo's network subsystem.\n *\n * The adapter delegates lifecycle (connect, disconnect, isReady, peer\n * discovery) to the base adapter unchanged. Only the message body is\n * intercepted.\n */\nexport class MeshNetworkAdapter extends NetworkAdapter {\n readonly base: NetworkAdapter;\n readonly keyring: MeshKeyring;\n readonly encryptionEnabled: boolean;\n\n constructor(options: MeshNetworkAdapterOptions) {\n super();\n this.base = options.base;\n this.keyring = options.keyring;\n this.encryptionEnabled = options.encryptionEnabled ?? true;\n\n // Forward lifecycle and peer events from the base adapter.\n this.base.on(\"close\", () => this.emit(\"close\"));\n this.base.on(\"peer-candidate\", (payload) => this.emit(\"peer-candidate\", payload));\n this.base.on(\"peer-disconnected\", (payload) => this.emit(\"peer-disconnected\", payload));\n\n // Intercept incoming messages: the base adapter will surface them as\n // 'message' events with crypto-wrapped payloads. We unwrap and re-emit.\n this.base.on(\"message\", (rawMessage) => {\n const unwrapped = this.tryUnwrap(rawMessage);\n if (unwrapped) {\n this.emit(\"message\", unwrapped);\n }\n // Silently drop messages that fail verification or decryption. A\n // production adapter would surface this through a diagnostic channel\n // so the application could prompt the user; the Phase 2 first cut\n // logs through the standard \"drop unknown\" semantics of the network\n // subsystem.\n });\n }\n\n isReady(): boolean {\n return this.base.isReady();\n }\n\n whenReady(): Promise<void> {\n return this.base.whenReady();\n }\n\n connect(peerId: PeerId, peerMetadata?: PeerMetadata): void {\n this.peerId = peerId;\n if (peerMetadata !== undefined) {\n this.peerMetadata = peerMetadata;\n }\n this.base.connect(peerId, peerMetadata);\n }\n\n disconnect(): void {\n this.base.disconnect();\n }\n\n send(message: Message): void {\n const wrapped = this.wrap(message);\n this.base.send(wrapped);\n }\n\n /**\n * Wrap an outgoing Automerge message in an encrypt-then-sign envelope.\n * The wrapped payload is returned as a Message with the original sender\n * and target ids and the crypto blob in the `data` field.\n */\n private wrap(message: Message): Message {\n const serialised = serialiseMessage(message);\n\n let payloadToSign: Uint8Array;\n if (this.encryptionEnabled) {\n const docKey = this.keyring.documentKeys.get(DEFAULT_MESH_KEY_ID);\n if (!docKey) {\n throw new Error(\n `MeshNetworkAdapter: missing document encryption key under id \"${DEFAULT_MESH_KEY_ID}\". Provision the key in the keyring before sending.`\n );\n }\n const encrypted = sealEncryptedEnvelope(serialised, DEFAULT_MESH_KEY_ID, docKey);\n payloadToSign = encodeEncryptedEnvelope(encrypted);\n } else {\n payloadToSign = serialised;\n }\n\n const signed = signEnvelope(payloadToSign, message.senderId, this.keyring.identity.secretKey);\n const signedBytes = encodeSignedEnvelope(signed);\n\n return {\n type: message.type,\n senderId: message.senderId,\n targetId: message.targetId,\n data: signedBytes,\n } as unknown as Message;\n }\n\n /**\n * Try to unwrap an incoming crypto-wrapped message. Returns the original\n * Message on success, undefined on verification or decryption failure.\n */\n private tryUnwrap(message: Message): Message | undefined {\n if (!message.data) return undefined;\n\n let signed: ReturnType<typeof decodeSignedEnvelope>;\n try {\n signed = decodeSignedEnvelope(message.data);\n } catch {\n return undefined;\n }\n\n // Drop messages from peers whose keys have been revoked, even if the\n // public key is still present in knownPeers. The revocation set is the\n // authoritative \"this peer is no longer trusted\" marker.\n if (this.keyring.revokedPeers.has(signed.senderId)) {\n return undefined;\n }\n\n const senderKey = this.keyring.knownPeers.get(signed.senderId);\n if (!senderKey) {\n return undefined;\n }\n\n let verifiedPayload: Uint8Array;\n try {\n verifiedPayload = openSignedEnvelope(signed, senderKey);\n } catch {\n return undefined;\n }\n\n if (!this.encryptionEnabled) {\n // Sign-only mode: the verified payload IS the serialised message.\n return deserialiseMessage(verifiedPayload);\n }\n\n // Full encrypt+sign mode: unwrap the encryption envelope.\n let encrypted: ReturnType<typeof decodeEncryptedEnvelope>;\n try {\n encrypted = decodeEncryptedEnvelope(verifiedPayload);\n } catch {\n return undefined;\n }\n\n const docKey = this.keyring.documentKeys.get(encrypted.documentId);\n if (!docKey) {\n return undefined;\n }\n\n let plaintext: Uint8Array;\n try {\n plaintext = openEncryptedEnvelope(encrypted, docKey);\n } catch {\n return undefined;\n }\n\n return deserialiseMessage(plaintext);\n }\n}\n\n// ─── message serialisation ─────────────────────────────────────────────────\n\n/**\n * Serialise an Automerge sync message to a binary blob suitable for\n * encryption. The format is a length-prefixed JSON header (carrying the\n * non-binary fields) followed by the raw `data` bytes (which Automerge's\n * sync messages carry as Uint8Array). This avoids round-tripping the\n * binary payload through JSON, which would balloon its size.\n */\nfunction serialiseMessage(message: Message): Uint8Array {\n const headerObj: Record<string, unknown> = {\n type: message.type,\n senderId: message.senderId,\n targetId: message.targetId,\n };\n if (\"documentId\" in message && message.documentId !== undefined) {\n headerObj[\"documentId\"] = message.documentId;\n }\n if (\"count\" in message && message.count !== undefined) {\n headerObj[\"count\"] = message.count;\n }\n if (\"sessionId\" in message && message.sessionId !== undefined) {\n headerObj[\"sessionId\"] = message.sessionId;\n }\n const headerBytes = new TextEncoder().encode(JSON.stringify(headerObj));\n const dataBytes: Uint8Array =\n \"data\" in message && message.data instanceof Uint8Array ? message.data : new Uint8Array(0);\n\n const out = new Uint8Array(4 + headerBytes.length + dataBytes.length);\n const view = new DataView(out.buffer);\n view.setUint32(0, headerBytes.length, false);\n out.set(headerBytes, 4);\n out.set(dataBytes, 4 + headerBytes.length);\n return out;\n}\n\n/**\n * Inverse of {@link serialiseMessage}.\n */\nfunction deserialiseMessage(bytes: Uint8Array): Message {\n if (bytes.length < 4) {\n throw new Error(\"MeshNetworkAdapter: message too short to deserialise.\");\n }\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const headerLen = view.getUint32(0, false);\n if (bytes.length < 4 + headerLen) {\n throw new Error(\"MeshNetworkAdapter: message header truncated.\");\n }\n const header = JSON.parse(new TextDecoder().decode(bytes.subarray(4, 4 + headerLen)));\n const data = bytes.slice(4 + headerLen);\n return { ...header, data } as unknown as Message;\n}\n",
|
|
15
15
|
"/**\n * signing — Ed25519 signing and verification for Polly's $meshState\n * primitive (Phase 2). Wraps tweetnacl with a small Polly-flavoured API\n * so the rest of the codebase never imports tweetnacl directly.\n *\n * Every operation that flows through a $meshState transport is signed by\n * the originating peer's private key before transmission and verified by\n * every receiving peer against a known public-key set before being applied.\n * This is the Byzantine-tolerance mechanism: a peer whose private key is\n * compromised can be revoked through a further signed operation, after\n * which honest peers reject anything signed by the revoked key.\n *\n * tweetnacl uses the Ed25519 curve. Public keys and signatures are 32 and\n * 64 bytes respectively, which keeps the per-op overhead small enough that\n * signing every Automerge sync message is feasible even on mobile.\n *\n * The shape of the wrapper:\n *\n * - {@link generateSigningKeyPair} produces a new Ed25519 keypair. The\n * private key never leaves the device that generated it; the public\n * key is gossiped through the access set.\n *\n * - {@link sign} produces a 64-byte detached signature over a payload.\n *\n * - {@link verify} checks a payload against a signature and a public\n * key. Returns boolean rather than throwing so call sites can handle\n * verification failure as a normal control-flow case.\n *\n * - {@link signEnvelope} and {@link openEnvelope} package payload + sender\n * id + signature into a single binary envelope, which is what the mesh\n * network adapter actually puts on the wire.\n */\n\nimport nacl from \"tweetnacl\";\n\n/** Length in bytes of an Ed25519 public key. */\nexport const PUBLIC_KEY_BYTES = 32;\n/** Length in bytes of an Ed25519 secret (private) key. */\nexport const SECRET_KEY_BYTES = 64;\n/** Length in bytes of an Ed25519 detached signature. */\nexport const SIGNATURE_BYTES = 64;\n\n/**\n * An Ed25519 keypair. The {@link publicKey} is safe to share with peers;\n * the {@link secretKey} must never leave the device.\n */\nexport interface SigningKeyPair {\n publicKey: Uint8Array;\n secretKey: Uint8Array;\n}\n\n/**\n * A signed envelope. The wire format is the concatenation of the sender id\n * length, the sender id bytes, the signature, and the payload. Callers\n * shouldn't rely on the exact layout — use {@link signEnvelope} and\n * {@link openEnvelope} to round-trip.\n */\nexport interface SignedEnvelope {\n /** Stable sender peer identifier (UTF-8 string). The receiving side uses\n * this to look up the sender's public key in the document's access set. */\n senderId: string;\n /** The original payload bytes, untouched. */\n payload: Uint8Array;\n /** 64-byte Ed25519 signature over the payload. */\n signature: Uint8Array;\n}\n\n/** Errors thrown by the signing subsystem. */\nexport class SigningError extends Error {\n readonly code:\n | \"invalid-secret-key\"\n | \"invalid-public-key\"\n | \"invalid-signature-length\"\n | \"envelope-malformed\";\n\n constructor(message: string, code: SigningError[\"code\"]) {\n super(message);\n this.name = \"SigningError\";\n this.code = code;\n }\n}\n\n/**\n * Generate a fresh Ed25519 keypair. Calls into tweetnacl's CSPRNG.\n */\nexport function generateSigningKeyPair(): SigningKeyPair {\n const pair = nacl.sign.keyPair();\n return {\n publicKey: pair.publicKey,\n secretKey: pair.secretKey,\n };\n}\n\n/**\n * Reconstruct a keypair from an existing 64-byte secret key. Useful for\n * loading keys from persistent storage. Throws if the key is the wrong size.\n */\nexport function signingKeyPairFromSecret(secretKey: Uint8Array): SigningKeyPair {\n if (secretKey.length !== SECRET_KEY_BYTES) {\n throw new SigningError(\n `Ed25519 secret key must be ${SECRET_KEY_BYTES} bytes, got ${secretKey.length}.`,\n \"invalid-secret-key\"\n );\n }\n const pair = nacl.sign.keyPair.fromSecretKey(secretKey);\n return {\n publicKey: pair.publicKey,\n secretKey: pair.secretKey,\n };\n}\n\n/**\n * Produce a 64-byte detached signature over the given payload using the\n * supplied secret key.\n */\nexport function sign(payload: Uint8Array, secretKey: Uint8Array): Uint8Array {\n if (secretKey.length !== SECRET_KEY_BYTES) {\n throw new SigningError(\n `Ed25519 secret key must be ${SECRET_KEY_BYTES} bytes, got ${secretKey.length}.`,\n \"invalid-secret-key\"\n );\n }\n return nacl.sign.detached(payload, secretKey);\n}\n\n/**\n * Verify a detached signature against a payload and a public key. Returns\n * true if the signature is valid, false otherwise. Wrong-length keys or\n * signatures throw {@link SigningError} so callers can distinguish a bad\n * signature from a misshapen input.\n */\nexport function verify(payload: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean {\n if (publicKey.length !== PUBLIC_KEY_BYTES) {\n throw new SigningError(\n `Ed25519 public key must be ${PUBLIC_KEY_BYTES} bytes, got ${publicKey.length}.`,\n \"invalid-public-key\"\n );\n }\n if (signature.length !== SIGNATURE_BYTES) {\n throw new SigningError(\n `Ed25519 signature must be ${SIGNATURE_BYTES} bytes, got ${signature.length}.`,\n \"invalid-signature-length\"\n );\n }\n return nacl.sign.detached.verify(payload, signature, publicKey);\n}\n\n/**\n * Sign a payload and pack it into a {@link SignedEnvelope} along with the\n * sender id. The mesh network adapter calls this on every outgoing message\n * before handing it to the transport.\n */\nexport function signEnvelope(\n payload: Uint8Array,\n senderId: string,\n secretKey: Uint8Array\n): SignedEnvelope {\n const signature = sign(payload, secretKey);\n return { senderId, payload, signature };\n}\n\n/**\n * Verify a {@link SignedEnvelope} against the sender's known public key.\n * Returns the inner payload on success, throws on failure. The mesh\n * network adapter calls this on every incoming message before forwarding\n * the payload to the underlying Automerge sync subsystem.\n */\nexport function openEnvelope(envelope: SignedEnvelope, publicKey: Uint8Array): Uint8Array {\n const ok = verify(envelope.payload, envelope.signature, publicKey);\n if (!ok) {\n throw new SigningError(\n `Signature verification failed for envelope from ${envelope.senderId}.`,\n \"envelope-malformed\"\n );\n }\n return envelope.payload;\n}\n\n/**\n * Serialise a {@link SignedEnvelope} to a single binary blob suitable for\n * transmission over a network adapter. Wire format:\n *\n * [4 bytes BE: senderId byte length]\n * [N bytes: senderId UTF-8]\n * [64 bytes: signature]\n * [remaining: payload]\n *\n * Callers should not depend on the exact bytes — they should round-trip\n * through {@link encodeSignedEnvelope} / {@link decodeSignedEnvelope}.\n */\nexport function encodeSignedEnvelope(envelope: SignedEnvelope): Uint8Array {\n const senderBytes = new TextEncoder().encode(envelope.senderId);\n const total = 4 + senderBytes.length + SIGNATURE_BYTES + envelope.payload.length;\n const out = new Uint8Array(total);\n const view = new DataView(out.buffer);\n view.setUint32(0, senderBytes.length, false);\n out.set(senderBytes, 4);\n out.set(envelope.signature, 4 + senderBytes.length);\n out.set(envelope.payload, 4 + senderBytes.length + SIGNATURE_BYTES);\n return out;\n}\n\n/**\n * Deserialise a binary envelope produced by {@link encodeSignedEnvelope}.\n * Throws on malformed input.\n */\nexport function decodeSignedEnvelope(bytes: Uint8Array): SignedEnvelope {\n if (bytes.length < 4 + SIGNATURE_BYTES) {\n throw new SigningError(\n `Envelope too short: ${bytes.length} bytes, need at least ${4 + SIGNATURE_BYTES}.`,\n \"envelope-malformed\"\n );\n }\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const senderLen = view.getUint32(0, false);\n if (bytes.length < 4 + senderLen + SIGNATURE_BYTES) {\n throw new SigningError(\n `Envelope truncated: declared sender length ${senderLen}, total ${bytes.length}.`,\n \"envelope-malformed\"\n );\n }\n const senderId = new TextDecoder().decode(bytes.subarray(4, 4 + senderLen));\n const signature = bytes.slice(4 + senderLen, 4 + senderLen + SIGNATURE_BYTES);\n const payload = bytes.slice(4 + senderLen + SIGNATURE_BYTES);\n return { senderId, payload, signature };\n}\n",
|
|
16
|
-
"/**\n * mesh-signaling-client — browser-side client for Polly's signalingServer\n * Elysia plugin. Connects to the signalling WebSocket, registers a peer\n * id, and relays SDP/ICE messages between local WebRTC connections and\n * remote peers.\n *\n * This module is the companion to {@link signalingServer} from the Elysia\n * plugin family. The server accepts \"join\" and \"signal\" messages; this\n * client produces them. The protocol matches: opening the connection,\n * sending a \"join\" with the local peer id, and then using sendSignal()\n * to forward SDP and ICE messages to specific target peers.\n *\n * Because this client is browser-only in its first incarnation — it\n * assumes the global `WebSocket` is available — it cannot be exercised\n * under bun:test the way the server-side plugin is. The first validation\n * of this code path is either a Playwright harness or a human running\n * the browser-side example that consumes it.\n */\n\n/** A signal message either sent to or received from the signalling server.\n * Matches the wire format produced by the Elysia signalingServer plugin. */\nexport interface SignalingMessage {\n type: \"join\" | \"signal\" | \"error\" | \"peers-present\" | \"peer-joined\" | \"peer-left\";\n peerId?: string;\n peerIds?: string[];\n targetPeerId?: string;\n payload?: unknown;\n reason?: \"unknown-target\" | \"not-joined\" | \"malformed\";\n}\n\n/** Options for constructing a {@link MeshSignalingClient}. */\nexport interface MeshSignalingClientOptions {\n /** The signalling server URL (ws:// or wss://). */\n url: string;\n /** The local peer id that this client will register with on join. */\n peerId: string;\n /** Callback invoked whenever a signal message from another peer arrives.\n * The receiver dispatches to the right PeerConnection based on the\n * `fromPeerId`. */\n onSignal: (fromPeerId: string, payload: unknown) => void;\n /** Optional callback invoked when the server returns an error (for\n * diagnostic UI or reconnection logic). */\n onError?: (reason: string, targetPeerId?: string) => void;\n /** Optional callback for the open and close lifecycle events. */\n onOpen?: () => void;\n onClose?: () => void;\n /** Optional callback invoked once, immediately after the server's\n * response to our `join`, listing every peer already joined at that\n * moment. Empty list when the lobby is otherwise empty. */\n onPeersPresent?: (peerIds: string[]) => void;\n /** Optional callback invoked each time a new peer joins the signalling\n * server after we have already joined. */\n onPeerJoined?: (peerId: string) => void;\n /** Optional callback invoked each time a joined peer's socket closes\n * (including graceful disconnect and abrupt drops detected by the\n * server). Fires at most once per departure. */\n onPeerLeft?: (peerId: string) => void;\n /** WebSocket constructor. Defaults to `globalThis.WebSocket`. Inject a\n * different implementation (e.g. `ws` package's `WebSocket`) when running\n * in an environment without a native WebSocket global, or to use a custom\n * subclass for tests or instrumentation. */\n WebSocket?: typeof WebSocket;\n}\n\n/**\n * Thin wrapper around a WebSocket connection to a Polly signalling server.\n * Handles the join handshake, routes incoming signals to the supplied\n * callback, and exposes a {@link sendSignal} method for outgoing signals.\n *\n * This class is deliberately small. It has no opinion on the signal\n * payload shape (the wire carries it as `unknown`), so it can carry SDP\n * offers, SDP answers, ICE candidates, or any other message the\n * WebRTC adapter wants to exchange with peers.\n */\n/** Base delay (ms) between reconnect attempts. Doubles per attempt up\n * to {@link RECONNECT_MAX_DELAY_MS}. */\nconst RECONNECT_BASE_DELAY_MS = 250;\n/** Ceiling for the exponential backoff so a long outage does not leave\n * the client silent for minutes between probes. */\nconst RECONNECT_MAX_DELAY_MS = 30_000;\n\nexport class MeshSignalingClient {\n readonly url: string;\n readonly peerId: string;\n private readonly onSignal: (fromPeerId: string, payload: unknown) => void;\n private readonly onError?: (reason: string, targetPeerId?: string) => void;\n private readonly onOpen?: () => void;\n private readonly onClose?: () => void;\n private readonly onPeersPresent?: (peerIds: string[]) => void;\n private readonly onPeerJoined?: (peerId: string) => void;\n private readonly onPeerLeft?: (peerId: string) => void;\n private socket: WebSocket | undefined;\n private joined = false;\n private stopping = false;\n private reconnectTimer: ReturnType<typeof setTimeout> | undefined;\n private readonly WebSocketCtor: typeof WebSocket;\n\n constructor(options: MeshSignalingClientOptions) {\n this.url = options.url;\n this.peerId = options.peerId;\n this.onSignal = options.onSignal;\n if (options.onError !== undefined) this.onError = options.onError;\n if (options.onOpen !== undefined) this.onOpen = options.onOpen;\n if (options.onClose !== undefined) this.onClose = options.onClose;\n if (options.onPeersPresent !== undefined) this.onPeersPresent = options.onPeersPresent;\n if (options.onPeerJoined !== undefined) this.onPeerJoined = options.onPeerJoined;\n if (options.onPeerLeft !== undefined) this.onPeerLeft = options.onPeerLeft;\n const WS = options.WebSocket ?? globalThis.WebSocket;\n if (typeof WS !== \"function\") {\n throw new Error(\n \"MeshSignalingClient: no WebSocket implementation found. Pass one via options.WebSocket, or run in an environment where `globalThis.WebSocket` exists (Node 21+, Bun, browsers).\"\n );\n }\n this.WebSocketCtor = WS;\n }\n\n /**\n * Open the WebSocket and send the join message. Resolves once the\n * connection is open; callers should not send signals before this\n * promise resolves.\n */\n async connect(): Promise<void> {\n this.stopping = false;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n return new Promise((resolve, reject) => {\n const ws = new this.WebSocketCtor(this.url);\n this.socket = ws;\n let settled = false;\n\n ws.addEventListener(\"open\", () => {\n // Send the join message as the first frame. The server registers\n // the peer id and uses it as the authenticated sender for all\n // subsequent signals on this connection.\n ws.send(JSON.stringify({ type: \"join\", peerId: this.peerId } satisfies SignalingMessage));\n this.joined = true;\n this.onOpen?.();\n if (!settled) {\n settled = true;\n resolve();\n }\n });\n\n ws.addEventListener(\"message\", (event) => {\n this.dispatchFrame(event.data);\n });\n\n ws.addEventListener(\"error\", (err) => {\n // Only the initial connect rejects here. Post-open errors route\n // through the close handler's reconnect path.\n if (!settled) {\n settled = true;\n reject(err);\n }\n });\n\n ws.addEventListener(\"close\", () => {\n const wasOpen = this.joined;\n this.joined = false;\n this.onClose?.();\n // If the caller asked to stop, respect it. Otherwise a close on\n // an established connection — or a close that preempted `open`\n // — kicks off the reconnect loop.\n if (!this.stopping && wasOpen) {\n this.scheduleReconnect(0);\n }\n });\n });\n }\n\n /** Schedule the next reconnect attempt with exponential backoff. */\n private scheduleReconnect(attempt: number): void {\n if (this.stopping) return;\n const delay = Math.min(RECONNECT_MAX_DELAY_MS, RECONNECT_BASE_DELAY_MS * 2 ** attempt);\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = undefined;\n if (this.stopping) return;\n void this.connect().catch(() => {\n this.scheduleReconnect(attempt + 1);\n });\n }, delay);\n }\n\n /**\n * Parse and route an incoming frame. Extracted from the open/message\n * closure in {@link connect} so the discriminated-union switch stays\n * below the linter's cognitive-complexity ceiling.\n */\n private dispatchFrame(raw: unknown): void {\n let msg: SignalingMessage;\n try {\n msg = typeof raw === \"string\" ? JSON.parse(raw) : (raw as SignalingMessage);\n } catch {\n return;\n }\n switch (msg.type) {\n case \"signal\":\n if (typeof msg.peerId === \"string\") this.onSignal(msg.peerId, msg.payload);\n return;\n case \"peers-present\":\n if (Array.isArray(msg.peerIds)) this.onPeersPresent?.(msg.peerIds);\n return;\n case \"peer-joined\":\n if (typeof msg.peerId === \"string\") this.onPeerJoined?.(msg.peerId);\n return;\n case \"peer-left\":\n if (typeof msg.peerId === \"string\") this.onPeerLeft?.(msg.peerId);\n return;\n case \"error\":\n if (msg.reason) this.onError?.(msg.reason, msg.targetPeerId);\n return;\n default:\n return;\n }\n }\n\n /**\n * Send a signal to another peer via the signalling server. The server\n * validates the sender (replacing the claimed peerId with the\n * authenticated join id) and routes to the target. Returns true if\n * the message was sent, false if the connection is not open.\n */\n sendSignal(targetPeerId: string, payload: unknown): boolean {\n if (!this.socket || this.socket.readyState !== this.WebSocketCtor.OPEN || !this.joined) {\n return false;\n }\n const msg: SignalingMessage = {\n type: \"signal\",\n peerId: this.peerId,\n targetPeerId,\n payload,\n };\n this.socket.send(JSON.stringify(msg));\n return true;\n }\n\n /**\n * Close the underlying WebSocket connection. The server's close handler\n * will evict this peer from its routing table. Also cancels any\n * pending reconnect attempt so the client stays closed until the\n * caller reopens it with another {@link connect} call.\n */\n close(): void {\n this.stopping = true;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n this.socket?.close();\n this.socket = undefined;\n this.joined = false;\n }\n\n /** True if the signalling connection is open and joined. */\n get isConnected(): boolean {\n return this.joined && this.socket?.readyState === this.WebSocketCtor.OPEN;\n }\n}\n",
|
|
16
|
+
"/**\n * mesh-signaling-client — browser-side client for Polly's signalingServer\n * Elysia plugin. Connects to the signalling WebSocket, registers a peer\n * id, and relays SDP/ICE messages between local WebRTC connections and\n * remote peers.\n *\n * This module is the companion to {@link signalingServer} from the Elysia\n * plugin family. The server accepts \"join\" and \"signal\" messages; this\n * client produces them. The protocol matches: opening the connection,\n * sending a \"join\" with the local peer id, and then using sendSignal()\n * to forward SDP and ICE messages to specific target peers.\n *\n * Because this client is browser-only in its first incarnation — it\n * assumes the global `WebSocket` is available — it cannot be exercised\n * under bun:test the way the server-side plugin is. The first validation\n * of this code path is either a Playwright harness or a human running\n * the browser-side example that consumes it.\n */\n\n/** A signal message either sent to or received from the signalling server.\n * Matches the wire format produced by the Elysia signalingServer plugin. */\nexport interface SignalingMessage {\n type: \"join\" | \"signal\" | \"error\" | \"peers-present\" | \"peer-joined\" | \"peer-left\";\n peerId?: string;\n peerIds?: string[];\n targetPeerId?: string;\n payload?: unknown;\n reason?: \"unknown-target\" | \"not-joined\" | \"malformed\";\n}\n\n/** A frame whose `type` is outside the built-in {@link SignalingMessage}\n * vocabulary. Consumers who want to layer application protocols on the\n * signalling socket — pairing return tokens, presence pings, anything\n * else that benefits from sharing the existing connection and its\n * reconnect state — receive these through {@link MeshSignalingClientOptions.onCustomFrame}\n * and produce them through {@link MeshSignalingClient.sendCustom}. Polly\n * does not interpret the body; the signalling server routes it per its\n * own conventions. The field `type` is always present; everything else\n * is application-defined. */\nexport interface CustomSignalingFrame {\n type: string;\n [key: string]: unknown;\n}\n\n/** Options for constructing a {@link MeshSignalingClient}. */\nexport interface MeshSignalingClientOptions {\n /** The signalling server URL (ws:// or wss://). */\n url: string;\n /** The local peer id that this client will register with on join. */\n peerId: string;\n /** Callback invoked whenever a signal message from another peer arrives.\n * The receiver dispatches to the right PeerConnection based on the\n * `fromPeerId`. */\n onSignal: (fromPeerId: string, payload: unknown) => void;\n /** Optional callback invoked when the server returns an error (for\n * diagnostic UI or reconnection logic). */\n onError?: (reason: string, targetPeerId?: string) => void;\n /** Optional callback for the open and close lifecycle events. */\n onOpen?: () => void;\n onClose?: () => void;\n /** Optional callback invoked once, immediately after the server's\n * response to our `join`, listing every peer already joined at that\n * moment. Empty list when the lobby is otherwise empty. */\n onPeersPresent?: (peerIds: string[]) => void;\n /** Optional callback invoked each time a new peer joins the signalling\n * server after we have already joined. */\n onPeerJoined?: (peerId: string) => void;\n /** Optional callback invoked each time a joined peer's socket closes\n * (including graceful disconnect and abrupt drops detected by the\n * server). Fires at most once per departure. */\n onPeerLeft?: (peerId: string) => void;\n /** Optional callback invoked for any frame whose `type` is outside the\n * built-in {@link SignalingMessage} vocabulary. Consumers use this to\n * layer their own protocol on top of the signalling socket — pairing\n * return tokens, presence pings, anything else that benefits from\n * sharing the existing connection and its reconnect state. A frame\n * that arrives before the join handshake completes or that fails to\n * parse as JSON is dropped silently, as with the built-in types. */\n onCustomFrame?: (frame: CustomSignalingFrame) => void;\n /** WebSocket constructor. Defaults to `globalThis.WebSocket`. Inject a\n * different implementation (e.g. `ws` package's `WebSocket`) when running\n * in an environment without a native WebSocket global, or to use a custom\n * subclass for tests or instrumentation. */\n WebSocket?: typeof WebSocket;\n}\n\n/**\n * Thin wrapper around a WebSocket connection to a Polly signalling server.\n * Handles the join handshake, routes incoming signals to the supplied\n * callback, and exposes a {@link sendSignal} method for outgoing signals.\n *\n * This class is deliberately small. It has no opinion on the signal\n * payload shape (the wire carries it as `unknown`), so it can carry SDP\n * offers, SDP answers, ICE candidates, or any other message the\n * WebRTC adapter wants to exchange with peers.\n */\n/** Base delay (ms) between reconnect attempts. Doubles per attempt up\n * to {@link RECONNECT_MAX_DELAY_MS}. */\nconst RECONNECT_BASE_DELAY_MS = 250;\n/** Ceiling for the exponential backoff so a long outage does not leave\n * the client silent for minutes between probes. */\nconst RECONNECT_MAX_DELAY_MS = 30_000;\n\n/** Parse a raw frame from the socket into a record with a string `type`,\n * or `undefined` if the frame is unparseable or malformed. Extracted so\n * {@link MeshSignalingClient.dispatchFrame} stays below the linter's\n * cognitive-complexity ceiling. */\nfunction parseFrame(raw: unknown): Record<string, unknown> | undefined {\n let parsed: unknown;\n try {\n parsed = typeof raw === \"string\" ? JSON.parse(raw) : raw;\n } catch {\n return undefined;\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return undefined;\n }\n const record = parsed as Record<string, unknown>;\n if (typeof record[\"type\"] !== \"string\") {\n return undefined;\n }\n return record;\n}\n\nexport class MeshSignalingClient {\n readonly url: string;\n readonly peerId: string;\n private readonly onSignal: (fromPeerId: string, payload: unknown) => void;\n private readonly onError?: (reason: string, targetPeerId?: string) => void;\n private readonly onOpen?: () => void;\n private readonly onClose?: () => void;\n private readonly onPeersPresent?: (peerIds: string[]) => void;\n private readonly onPeerJoined?: (peerId: string) => void;\n private readonly onPeerLeft?: (peerId: string) => void;\n private readonly onCustomFrame?: (frame: CustomSignalingFrame) => void;\n private socket: WebSocket | undefined;\n private joined = false;\n private stopping = false;\n private reconnectTimer: ReturnType<typeof setTimeout> | undefined;\n private readonly WebSocketCtor: typeof WebSocket;\n\n constructor(options: MeshSignalingClientOptions) {\n this.url = options.url;\n this.peerId = options.peerId;\n this.onSignal = options.onSignal;\n if (options.onError !== undefined) this.onError = options.onError;\n if (options.onOpen !== undefined) this.onOpen = options.onOpen;\n if (options.onClose !== undefined) this.onClose = options.onClose;\n if (options.onPeersPresent !== undefined) this.onPeersPresent = options.onPeersPresent;\n if (options.onPeerJoined !== undefined) this.onPeerJoined = options.onPeerJoined;\n if (options.onPeerLeft !== undefined) this.onPeerLeft = options.onPeerLeft;\n if (options.onCustomFrame !== undefined) this.onCustomFrame = options.onCustomFrame;\n const WS = options.WebSocket ?? globalThis.WebSocket;\n if (typeof WS !== \"function\") {\n throw new Error(\n \"MeshSignalingClient: no WebSocket implementation found. Pass one via options.WebSocket, or run in an environment where `globalThis.WebSocket` exists (Node 21+, Bun, browsers).\"\n );\n }\n this.WebSocketCtor = WS;\n }\n\n /**\n * Open the WebSocket and send the join message. Resolves once the\n * connection is open; callers should not send signals before this\n * promise resolves.\n */\n async connect(): Promise<void> {\n this.stopping = false;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n return new Promise((resolve, reject) => {\n const ws = new this.WebSocketCtor(this.url);\n this.socket = ws;\n let settled = false;\n\n ws.addEventListener(\"open\", () => {\n // Send the join message as the first frame. The server registers\n // the peer id and uses it as the authenticated sender for all\n // subsequent signals on this connection.\n ws.send(JSON.stringify({ type: \"join\", peerId: this.peerId } satisfies SignalingMessage));\n this.joined = true;\n this.onOpen?.();\n if (!settled) {\n settled = true;\n resolve();\n }\n });\n\n ws.addEventListener(\"message\", (event) => {\n this.dispatchFrame(event.data);\n });\n\n ws.addEventListener(\"error\", (err) => {\n // Only the initial connect rejects here. Post-open errors route\n // through the close handler's reconnect path.\n if (!settled) {\n settled = true;\n reject(err);\n }\n });\n\n ws.addEventListener(\"close\", () => {\n const wasOpen = this.joined;\n this.joined = false;\n this.onClose?.();\n // If the caller asked to stop, respect it. Otherwise a close on\n // an established connection — or a close that preempted `open`\n // — kicks off the reconnect loop.\n if (!this.stopping && wasOpen) {\n this.scheduleReconnect(0);\n }\n });\n });\n }\n\n /** Schedule the next reconnect attempt with exponential backoff. */\n private scheduleReconnect(attempt: number): void {\n if (this.stopping) return;\n const delay = Math.min(RECONNECT_MAX_DELAY_MS, RECONNECT_BASE_DELAY_MS * 2 ** attempt);\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = undefined;\n if (this.stopping) return;\n void this.connect().catch(() => {\n this.scheduleReconnect(attempt + 1);\n });\n }, delay);\n }\n\n /**\n * Parse and route an incoming frame. Extracted from the open/message\n * closure in {@link connect} so the discriminated-union switch stays\n * below the linter's cognitive-complexity ceiling.\n */\n private dispatchFrame(raw: unknown): void {\n const record = parseFrame(raw);\n if (record === undefined) {\n return;\n }\n const handler = this.builtInHandler(record[\"type\"]);\n if (handler !== undefined) {\n handler(record);\n return;\n }\n // Unknown types route to the custom-frame handler, which consumers\n // use to layer application protocols on the shared socket. Without\n // a handler the frame is silently dropped, preserving the old\n // behaviour byte-for-byte.\n this.onCustomFrame?.(record as CustomSignalingFrame);\n }\n\n private builtInHandler(type: unknown): ((record: Record<string, unknown>) => void) | undefined {\n if (type === \"signal\") {\n return (record) => {\n if (typeof record[\"peerId\"] === \"string\") {\n this.onSignal(record[\"peerId\"], record[\"payload\"]);\n }\n };\n }\n if (type === \"peers-present\") {\n return (record) => {\n if (Array.isArray(record[\"peerIds\"])) {\n this.onPeersPresent?.(record[\"peerIds\"] as string[]);\n }\n };\n }\n if (type === \"peer-joined\") {\n return (record) => {\n if (typeof record[\"peerId\"] === \"string\") {\n this.onPeerJoined?.(record[\"peerId\"]);\n }\n };\n }\n if (type === \"peer-left\") {\n return (record) => {\n if (typeof record[\"peerId\"] === \"string\") {\n this.onPeerLeft?.(record[\"peerId\"]);\n }\n };\n }\n if (type === \"error\") {\n return (record) => {\n if (typeof record[\"reason\"] !== \"string\") {\n return;\n }\n const targetPeerId =\n typeof record[\"targetPeerId\"] === \"string\" ? record[\"targetPeerId\"] : undefined;\n this.onError?.(record[\"reason\"], targetPeerId);\n };\n }\n return undefined;\n }\n\n /**\n * Send a signal to another peer via the signalling server. The server\n * validates the sender (replacing the claimed peerId with the\n * authenticated join id) and routes to the target. Returns true if\n * the message was sent, false if the connection is not open.\n */\n sendSignal(targetPeerId: string, payload: unknown): boolean {\n if (!this.socket || this.socket.readyState !== this.WebSocketCtor.OPEN || !this.joined) {\n return false;\n }\n const msg: SignalingMessage = {\n type: \"signal\",\n peerId: this.peerId,\n targetPeerId,\n payload,\n };\n this.socket.send(JSON.stringify(msg));\n return true;\n }\n\n /**\n * Send a custom frame over the signalling socket. The frame is serialised\n * as `{ type, ...payload }`. The server must be configured to route this\n * frame type (polly does not interpret it). Returns true if the message\n * was sent, false if the connection is not open.\n *\n * Intended for application-level protocols that want to share the\n * existing signalling connection — for example, a pairing flow that\n * delivers a reciprocal token from the scanner back to the issuer.\n */\n sendCustom(type: string, payload: Record<string, unknown> = {}): boolean {\n if (!this.socket || this.socket.readyState !== this.WebSocketCtor.OPEN || !this.joined) {\n return false;\n }\n this.socket.send(JSON.stringify({ ...payload, type }));\n return true;\n }\n\n /**\n * Close the underlying WebSocket connection. The server's close handler\n * will evict this peer from its routing table. Also cancels any\n * pending reconnect attempt so the client stays closed until the\n * caller reopens it with another {@link connect} call.\n */\n close(): void {\n this.stopping = true;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n this.socket?.close();\n this.socket = undefined;\n this.joined = false;\n }\n\n /** True if the signalling connection is open and joined. */\n get isConnected(): boolean {\n return this.joined && this.socket?.readyState === this.WebSocketCtor.OPEN;\n }\n}\n",
|
|
17
17
|
"/**\n * mesh-state — Phase 2 wrappers exposing $meshState, $meshText, $meshCounter,\n * and $meshList. These are the application-facing constructors for the\n * strongest resilience tier in RFC-041: every device is a full Automerge\n * replica, the server is *not on the data path at all*, and the application\n * functions with zero server uptime once direct peer connections are\n * established.\n *\n * Each primitive wraps the corresponding Phase 0 base ($crdtState, $crdtText,\n * $crdtCounter, $crdtList) with three additions:\n *\n * 1. The `primitive` label is hard-coded to \"meshState\" so the\n * primitive-registry collision detection knows which family the key\n * belongs to.\n *\n * 2. A handle factory that resolves the application's logical key to an\n * Automerge DocumentId by hashing the key into a deterministic,\n * content-addressable id. Every Repo backed by the same storage lands\n * on the same document without needing any extra state, and two devices\n * that have never met converge on the same id for the same key — which\n * also helps first-sync after pairing. (Prior to this change the factory\n * held an in-memory per-Repo `Map<string, DocumentId>`, which meant that\n * a lone-device reload — a very common onboarding state — produced a\n * fresh DocumentId for the same logical key, orphaned the document the\n * storage adapter still held on disk, and silently lost the user's data.)\n *\n * 3. Signing and encryption are mandatory, not optional. Where $peerState\n * accepts encrypt/sign as opt-in flags (currently throwing in Phase 1),\n * $meshState requires every operation to be signed by the originating\n * peer's key and encrypted under the document's symmetric key. The\n * mechanism lives in the wrapping MeshNetworkAdapter that the Repo\n * uses for transport.\n *\n * The Repo itself is supplied by the application via {@link configureMeshState}\n * or per-call via the `repo` option. In Phase 2 the production transport will\n * be a WebRTC mesh adapter wrapping signing+encryption around an in-process\n * RTCDataChannel; for tests and for the early Phase 2 cut, an in-memory\n * loopback adapter pair satisfies the same contract.\n */\n\nimport {\n Automerge,\n type BinaryDocumentId,\n type DocHandle,\n type DocumentId,\n interpretAsDocumentId,\n type Repo,\n} from \"@automerge/automerge-repo/slim\";\nimport nacl from \"tweetnacl\";\nimport type { Access } from \"./access\";\nimport {\n $crdtCounter,\n $crdtList,\n $crdtText,\n type CounterDoc,\n type ListDoc,\n type SpecialisedPrimitive,\n type TextDoc,\n} from \"./crdt-specialised\";\nimport { $crdtState, type CrdtPrimitive } from \"./crdt-state\";\nimport type { Migrations, VersionedDoc } from \"./schema-version\";\n\n/** Common option shape across all four $mesh* primitives. */\nexport interface MeshStateOptions {\n /** Override the default Repo for this primitive. The Repo must be\n * configured with the mesh transport (signing and encryption at the\n * network layer). */\n repo?: Repo;\n /** Schema version target for the application. Migrations run on load. */\n schemaVersion?: number;\n /** Migration table keyed by target version. Required if schemaVersion is set. */\n migrations?: Migrations;\n /** Declarative read/write access. The mesh transport compiles this into\n * a public-key set used by the signing layer to verify incoming ops. */\n access?: Access;\n}\n\nlet defaultRepo: Repo | undefined;\n\n/**\n * Set the default Repo that the $mesh* primitives use when no `repo` option\n * is supplied. Production code typically calls this once at application\n * startup with a Repo configured for the mesh transport. Tests call it\n * before each scenario with an in-memory or loopback Repo.\n */\nexport function configureMeshState(repo: Repo): void {\n defaultRepo = repo;\n}\n\n/**\n * Reset the mesh-state subsystem to its initial unconfigured state.\n * Intended for tests; production code should not call this.\n */\nexport function resetMeshState(): void {\n defaultRepo = undefined;\n}\n\nfunction resolveRepo(option: Repo | undefined): Repo {\n const repo = option ?? defaultRepo;\n if (!repo) {\n throw new Error(\n \"Polly $meshState: no Repo configured. Call configureMeshState(repo) at startup or pass { repo } in the primitive options.\"\n );\n }\n return repo;\n}\n\n/**\n * Domain-separated hash of an application key into a 16-byte\n * {@link BinaryDocumentId}. SHA-512 via tweetnacl (already a dep for signing);\n * the first 16 bytes give a DocumentId with uniform distribution across the\n * Automerge id space. The domain prefix pins the derivation to $meshState so\n * that the same logical key used in a different Polly subsystem would\n * produce a different id.\n */\nconst DOC_ID_DOMAIN = \"polly/meshState/v1\";\nconst keyEncoder = new TextEncoder();\n\nfunction deriveDocumentId(key: string): DocumentId {\n const digest = nacl.hash(keyEncoder.encode(`${DOC_ID_DOMAIN}:${key}`));\n const bytes = digest.slice(0, 16);\n return interpretAsDocumentId(bytes as unknown as BinaryDocumentId);\n}\n\n/**\n * Build a getHandle factory that resolves a logical key to a DocHandle on\n * the supplied Repo via a deterministic DocumentId. On the first call during\n * a process lifetime — whether the device has never written this key or has\n * written it before a prior reload — the factory short-circuits around\n * {@link Repo.find}'s network-request timeout: it peeks directly at the\n * Repo's storage subsystem, hydrates from storage if the bytes are there,\n * and otherwise seeds a fresh document at the deterministic id. Subsequent\n * calls in the same process return the cached handle.\n */\nfunction buildHandleFactory<D>(\n repo: Repo,\n key: string,\n initialDoc: D\n): () => Promise<DocHandle<D>> {\n const documentId = deriveDocumentId(key);\n return async () => {\n const cached = repo.handles[documentId];\n if (cached) {\n await cached.whenReady([\"ready\", \"unavailable\"]);\n if (cached.state === \"ready\") {\n return cached as unknown as DocHandle<D>;\n }\n }\n const stored = await repo.storageSubsystem?.loadDoc<D>(documentId);\n if (stored) {\n return repo.find<D>(documentId, { allowableStates: [\"ready\"] });\n }\n const seeded = Automerge.save(Automerge.from(initialDoc as unknown as Record<string, unknown>));\n const handle = repo.import<D>(seeded, { docId: documentId });\n handle.doneLoading();\n return handle;\n };\n}\n\n// ─── $meshState ─────────────────────────────────────────────────────────────\n\n/**\n * Create a peer-replicated state primitive backed by Automerge with a mesh\n * transport. Every device holds a full replica; no central server holds a\n * replica. Operations flow peer-to-peer through signed and encrypted\n * messages on the underlying transport.\n *\n * @example\n * ```ts\n * const journal = $meshState<Journal>(\"journal\", { entries: [] });\n * await journal.loaded;\n * journal.value = { entries: [\"my private thoughts\"] };\n * ```\n */\nexport function $meshState<T extends VersionedDoc>(\n key: string,\n initialValue: T,\n options: MeshStateOptions = {}\n): CrdtPrimitive<T> {\n const repo = resolveRepo(options.repo);\n return $crdtState<T>({\n key,\n primitive: \"meshState\",\n initialValue,\n getHandle: buildHandleFactory<T>(repo, key, initialValue),\n schemaVersion: options.schemaVersion,\n migrations: options.migrations,\n access: options.access,\n });\n}\n\n// ─── $meshText ──────────────────────────────────────────────────────────────\n\n/**\n * Create a peer-replicated text primitive backed by a mesh transport.\n * Concurrent character-level edits from peers merge cleanly via Automerge's\n * updateText splicing, and every operation is signed and encrypted before\n * leaving the originating peer.\n */\nexport function $meshText(\n key: string,\n initialValue: string,\n options: MeshStateOptions = {}\n): SpecialisedPrimitive<string> {\n const repo = resolveRepo(options.repo);\n return $crdtText(key, initialValue, {\n primitive: \"meshState\",\n getHandle: buildHandleFactory<TextDoc>(repo, key, { text: initialValue }),\n schemaVersion: options.schemaVersion,\n migrations: options.migrations,\n access: options.access,\n });\n}\n\n// ─── $meshCounter ───────────────────────────────────────────────────────────\n\n/**\n * Create a peer-replicated counter primitive backed by a mesh transport.\n * Concurrent increments commute, and every operation is signed and\n * encrypted before leaving the originating peer.\n */\nexport function $meshCounter(\n key: string,\n initialValue: number,\n options: MeshStateOptions = {}\n): SpecialisedPrimitive<number> {\n const repo = resolveRepo(options.repo);\n return $crdtCounter(key, initialValue, {\n primitive: \"meshState\",\n getHandle: buildHandleFactory<CounterDoc>(repo, key, {}),\n schemaVersion: options.schemaVersion,\n migrations: options.migrations,\n access: options.access,\n });\n}\n\n// ─── $meshList ──────────────────────────────────────────────────────────────\n\n/**\n * Create a peer-replicated list primitive backed by a mesh transport.\n * Phase 0 naive replacement applies to writes for now; Phase 1.1 will\n * refine with structural diff-to-splice for concurrent insert/remove\n * preservation.\n */\nexport function $meshList<T>(\n key: string,\n initialValue: T[],\n options: MeshStateOptions = {}\n): SpecialisedPrimitive<T[]> {\n const repo = resolveRepo(options.repo);\n return $crdtList<T>(key, initialValue, {\n primitive: \"meshState\",\n getHandle: buildHandleFactory<ListDoc<T>>(repo, key, { items: initialValue }),\n schemaVersion: options.schemaVersion,\n migrations: options.migrations,\n access: options.access,\n });\n}\n",
|
|
18
18
|
"/**\n * crdt-specialised — text, counter, and list variants for Polly's peer-first\n * state primitives.\n *\n * Where the base $crdtState binds a signal to a whole Automerge document with\n * naive top-level structural assignment, the specialised variants each own a\n * single field inside their document and use type-specific Automerge\n * operations to mutate it. This is the difference between \"your write\n * survives a concurrent edit\" and \"your write clobbers the other peer's\n * edit,\" and it matters most for text editing where every keystroke from a\n * concurrent peer would otherwise be lost.\n *\n * - **$crdtText** stores its value in `doc.text` and writes via\n * `Automerge.updateText`, which computes the minimal sequence of character\n * splices between the previous and new strings and records each one as a\n * CRDT operation. Concurrent text edits merge.\n *\n * - **$crdtCounter** stores its value in `doc.count` as an `Automerge.Counter`\n * instance and writes via `counter.increment(delta)`. Increments commute\n * across peers, so two clients each adding 1 to a counter at 5 produce a\n * counter at 7 after merging — last-write-wins semantics on a plain number\n * would lose one of the increments.\n *\n * - **$crdtList** stores its value in `doc.items` and, for the Phase 0 cut,\n * uses naive whole-array replacement on every write. This is correct for\n * single-writer scenarios and good enough to exercise the rest of the\n * pipeline. Phase 1 will replace the write path with proper diff-to-splice\n * logic so that concurrent inserts and removes preserve list ordering.\n *\n * All three variants share a single internal factory that handles the\n * primitive-registry guard, migration-registry guard, schema-version\n * migration, hydration promise, two-way binding with an `updating` flag,\n * and the {@link MigratableState} interface. Variants differ only in the\n * `extractValue` and `applyWrite` hooks they pass.\n */\n\nimport { Counter, type DocHandle, updateText } from \"@automerge/automerge-repo/slim\";\nimport { effect, signal } from \"@preact/signals\";\nimport type { Access } from \"./access\";\nimport { type MigratableState, MigrationError, migrationRegistry } from \"./migrate-primitive\";\nimport { type PrimitiveKind, primitiveRegistry } from \"./primitive-registry\";\nimport { type Migrations, runMigrations, setDocVersion, type VersionedDoc } from \"./schema-version\";\n\n/**\n * Public interface for a specialised primitive. The signal value type V is\n * not the same as the underlying Automerge document — for example, $crdtText\n * exposes a string signal whose value lives at `doc.text` inside the\n * document. Implements {@link MigratableState} so the cross-primitive\n * migration helper can consume it directly.\n */\nexport interface SpecialisedPrimitive<V> extends MigratableState<V> {\n readonly key: string;\n readonly primitive: PrimitiveKind;\n value: V;\n readonly loaded: Promise<void>;\n readonly handle: DocHandle<unknown> | undefined;\n}\n\n/** Internal config shape consumed by {@link createSpecialisedPrimitive}. */\ninterface SpecialisedConfig<V, D extends VersionedDoc> {\n key: string;\n primitive: PrimitiveKind;\n initialValue: V;\n getHandle: () => Promise<DocHandle<D>>;\n /** Read the typed signal value out of the Automerge document. Called once\n * on hydration and again on every remote change. */\n extractValue: (doc: D) => V;\n /** Apply a typed signal value to the Automerge document inside the\n * `handle.change` block. Called every time the local signal is reassigned. */\n applyWrite: (doc: D, value: V) => void;\n schemaVersion?: number;\n migrations?: Migrations;\n access?: Access;\n callSite?: string;\n}\n\n/**\n * Shared factory. Identical guard, hydration, and binding wiring across all\n * three specialised variants; the variants differ only in the extract and\n * apply hooks they supply.\n */\nfunction createSpecialisedPrimitive<V, D extends VersionedDoc>(\n config: SpecialisedConfig<V, D>\n): SpecialisedPrimitive<V> {\n if (migrationRegistry.isMarked(config.key, config.primitive)) {\n throw new MigrationError(\n `Cannot construct $${config.primitive}(\"${config.key}\"): this key has been marked as migrated. Migrations are one-way; use the destination primitive instead.`,\n \"already-migrated\",\n config.key,\n config.primitive\n );\n }\n primitiveRegistry.register(config.key, config.primitive, config.callSite);\n\n const inner = signal<V>(config.initialValue);\n let updating = false;\n let currentHandle: DocHandle<D> | undefined;\n\n const loaded = (async () => {\n const handle = await config.getHandle();\n await handle.whenReady();\n currentHandle = handle;\n\n if (config.schemaVersion !== undefined) {\n const targetVersion = config.schemaVersion;\n const migrations = config.migrations ?? {};\n handle.change((doc) => {\n runMigrations(doc as unknown as Record<string, unknown>, targetVersion, migrations);\n setDocVersion(doc as unknown as Record<string, unknown>, targetVersion);\n });\n }\n\n updating = true;\n try {\n inner.value = config.extractValue(handle.doc());\n } finally {\n updating = false;\n }\n\n handle.on(\"change\", (payload) => {\n if (updating) return;\n updating = true;\n try {\n inner.value = config.extractValue(payload.doc);\n } finally {\n updating = false;\n }\n });\n\n effect(() => {\n const value = inner.value;\n if (updating) return;\n if (!currentHandle) return;\n updating = true;\n try {\n currentHandle.change((doc) => {\n config.applyWrite(doc, value);\n });\n } finally {\n updating = false;\n }\n });\n })();\n\n return {\n key: config.key,\n primitive: config.primitive,\n get value() {\n return inner.value;\n },\n set value(next: V) {\n inner.value = next;\n },\n loaded,\n get handle() {\n return currentHandle as unknown as DocHandle<unknown> | undefined;\n },\n };\n}\n\n// ─── $crdtText ──────────────────────────────────────────────────────────────\n\n/** The Automerge document shape backing a $crdtText primitive. */\nexport type TextDoc = VersionedDoc & { text?: string };\n\n/** Options for {@link $crdtText}. */\nexport interface CrdtTextOptions {\n /** Primitive kind label. Defaults to \"peerState\"; Phase 2's $meshState\n * wrapper passes \"meshState\" instead. */\n primitive?: PrimitiveKind;\n /** Async factory that returns a ready DocHandle for the text document. */\n getHandle: () => Promise<DocHandle<TextDoc>>;\n schemaVersion?: number;\n migrations?: Migrations;\n access?: Access;\n callSite?: string;\n}\n\n/**\n * Create a CRDT-backed text primitive. The signal exposes a plain string;\n * writes are diffed into character-level splices via `Automerge.updateText`\n * so that concurrent edits from peers merge cleanly rather than clobbering\n * each other.\n */\nexport function $crdtText(\n key: string,\n initialValue: string,\n options: CrdtTextOptions\n): SpecialisedPrimitive<string> {\n return createSpecialisedPrimitive<string, TextDoc>({\n key,\n primitive: options.primitive ?? \"peerState\",\n initialValue,\n getHandle: options.getHandle,\n extractValue: (doc) => doc.text ?? \"\",\n applyWrite: (doc, value) => {\n if (doc.text === undefined) {\n // First write — seed the field. Subsequent writes will use updateText.\n (doc as unknown as TextDoc).text = value;\n } else {\n updateText(doc, [\"text\"], value);\n }\n },\n schemaVersion: options.schemaVersion,\n migrations: options.migrations,\n access: options.access,\n callSite: options.callSite,\n });\n}\n\n// ─── $crdtCounter ───────────────────────────────────────────────────────────\n\n/** The Automerge document shape backing a $crdtCounter primitive. */\nexport type CounterDoc = VersionedDoc & { count?: Counter };\n\n/** Options for {@link $crdtCounter}. */\nexport interface CrdtCounterOptions {\n primitive?: PrimitiveKind;\n getHandle: () => Promise<DocHandle<CounterDoc>>;\n schemaVersion?: number;\n migrations?: Migrations;\n access?: Access;\n callSite?: string;\n}\n\n/**\n * Create a CRDT-backed counter primitive. The signal exposes a plain number;\n * writes compute the delta from the document's current value and call\n * `counter.increment(delta)` on the underlying `Automerge.Counter`. Concurrent\n * increments from peers commute, so two clients each adding 1 to a counter at\n * 5 produce a counter at 7 after merging.\n *\n * Application code that wants to express increments idiomatically can write\n * `counter.value = counter.value + 1`; the signal's reactivity captures the\n * read-then-write pattern and the factory translates it into a proper CRDT\n * increment operation underneath.\n */\nexport function $crdtCounter(\n key: string,\n initialValue: number,\n options: CrdtCounterOptions\n): SpecialisedPrimitive<number> {\n return createSpecialisedPrimitive<number, CounterDoc>({\n key,\n primitive: options.primitive ?? \"peerState\",\n initialValue,\n getHandle: options.getHandle,\n extractValue: (doc) => {\n const c = doc.count;\n if (c === undefined) return 0;\n return c.value;\n },\n applyWrite: (doc, value) => {\n const existing = doc.count;\n if (existing === undefined) {\n (doc as unknown as CounterDoc).count = new Counter(value);\n } else {\n const delta = value - existing.value;\n if (delta !== 0) {\n existing.increment(delta);\n }\n }\n },\n schemaVersion: options.schemaVersion,\n migrations: options.migrations,\n access: options.access,\n callSite: options.callSite,\n });\n}\n\n// ─── $crdtList ──────────────────────────────────────────────────────────────\n\n/** The Automerge document shape backing a $crdtList primitive. */\nexport type ListDoc<T> = VersionedDoc & { items?: T[] };\n\n/** Options for {@link $crdtList}. */\nexport interface CrdtListOptions<T> {\n primitive?: PrimitiveKind;\n getHandle: () => Promise<DocHandle<ListDoc<T>>>;\n schemaVersion?: number;\n migrations?: Migrations;\n access?: Access;\n callSite?: string;\n}\n\n/**\n * Create a CRDT-backed list primitive. The signal exposes a plain array;\n * for the Phase 0 cut, writes replace the underlying array wholesale inside\n * an `Automerge.change` block. This is correct for single-writer scenarios\n * and is the simplest way to ship a working list primitive on the same\n * pipeline as text and counter.\n *\n * Phase 1 will replace the write path with proper structural diffing into\n * insert and remove operations so that concurrent edits from peers preserve\n * list ordering. Until then, applications using $crdtList in a multi-writer\n * setting should expect last-writer-wins semantics on the array as a whole.\n */\nexport function $crdtList<T>(\n key: string,\n initialValue: T[],\n options: CrdtListOptions<T>\n): SpecialisedPrimitive<T[]> {\n return createSpecialisedPrimitive<T[], ListDoc<T>>({\n key,\n primitive: options.primitive ?? \"peerState\",\n initialValue,\n getHandle: options.getHandle,\n extractValue: (doc) => (doc.items ? [...doc.items] : []),\n applyWrite: (doc, value) => {\n // Phase 0 naive replacement; see the function-level docstring for the\n // refinement plan.\n (doc as unknown as ListDoc<T>).items = [...value];\n },\n schemaVersion: options.schemaVersion,\n migrations: options.migrations,\n access: options.access,\n callSite: options.callSite,\n });\n}\n",
|
|
19
19
|
"/**\n * migrate-primitive — one-way cross-primitive data migration helper.\n *\n * Moving data from one Polly primitive to another ($sharedState to $peerState,\n * $peerState to $meshState, etc.) is a deliberate, one-time, application-authored\n * operation. The three primitive families serialise differently — LWW value plus\n * Lamport clock, plaintext Automerge ops, signed and encrypted Automerge ops —\n * and Polly never silently coerces between them. An application that wants to\n * move data explicitly reads the current value from the source, applies a\n * user-supplied transform, writes the result into the destination, and marks\n * the source as migrated so subsequent reads from it fail loudly rather than\n * returning stale data.\n *\n * This module provides the helper ({@link migratePrimitive}) and the migration\n * registry ({@link migrationRegistry}) that records which (key, primitive kind)\n * pairs have been migrated. Primitive read paths consult the registry at load\n * time and refuse to hydrate sources that have been marked. Migration is one-way\n * by design: there is no rollback, and running a migration twice throws.\n *\n * The registry is in-memory only. Persistence of the migrated flag across page\n * loads is each primitive's own responsibility at its storage boundary; Phase 1\n * and Phase 2 primitives will restore the registry state on startup from their\n * local stores.\n *\n * @example\n * ```ts\n * await migratePrimitive(\n * $sharedState<OldNotes>(\"notes\"),\n * $meshState<NewNotes>(\"notes\", { entries: [] }),\n * (old) => ({ entries: old.entries ?? [] }),\n * );\n * ```\n */\n\nimport type { PrimitiveKind } from \"./primitive-registry\";\n\n/**\n * Minimal interface that every migratable state primitive must satisfy. Real\n * primitive instances will implement this plus everything else their type\n * expects; tests construct plain objects.\n */\nexport interface MigratableState<T> {\n /** Stable logical key the primitive was registered under. */\n readonly key: string;\n /** The primitive kind owning this state. Used to identify entries in the\n * migration registry alongside the key. */\n readonly primitive: PrimitiveKind;\n /** Current value. Must be readable and writable. */\n value: T;\n /** Hydration promise. The migration helper awaits this on both source and\n * destination before reading the source value. */\n readonly loaded: Promise<void>;\n}\n\n/**\n * Error thrown by the migration subsystem. The {@link code} field distinguishes\n * the failure modes so callers can branch on them.\n */\nexport class MigrationError extends Error {\n readonly code: \"already-migrated\" | \"same-primitive-instance\";\n readonly key: string;\n readonly primitive: PrimitiveKind;\n\n constructor(\n message: string,\n code: MigrationError[\"code\"],\n key: string,\n primitive: PrimitiveKind\n ) {\n super(message);\n this.name = \"MigrationError\";\n this.code = code;\n this.key = key;\n this.primitive = primitive;\n }\n}\n\n/**\n * In-memory registry of migrated (key, primitive kind) pairs. Exported as a\n * class so tests can construct fresh instances; application code uses the\n * module-level {@link migrationRegistry} singleton.\n */\nexport class MigrationRegistry {\n private readonly marks = new Set<string>();\n\n private entryKey(key: string, primitive: PrimitiveKind): string {\n return `${primitive}:${key}`;\n }\n\n /** Mark a source primitive as migrated. Idempotent. */\n mark(key: string, primitive: PrimitiveKind): void {\n this.marks.add(this.entryKey(key, primitive));\n }\n\n /** Check whether a source primitive has been marked as migrated. */\n isMarked(key: string, primitive: PrimitiveKind): boolean {\n return this.marks.has(this.entryKey(key, primitive));\n }\n\n /** Drop every mark. Intended for tests; application code should not call this. */\n clear(): void {\n this.marks.clear();\n }\n\n /** Number of recorded marks. Intended for tests. */\n get size(): number {\n return this.marks.size;\n }\n}\n\n/**\n * The process-wide migration registry. Primitives and application migrations\n * both consult it: tests can reset it with {@link MigrationRegistry.clear}.\n */\nexport const migrationRegistry = new MigrationRegistry();\n\n/**\n * Migrate data from one Polly primitive to another. Reads the source's current\n * value, applies the caller's transform, writes the result to the destination,\n * and marks the source as migrated so subsequent reads fail loudly.\n *\n * The helper is one-way and one-time. Running it twice on the same source\n * throws a {@link MigrationError} with code `already-migrated`. Running it\n * with the same object as both source and destination throws with code\n * `same-primitive-instance`.\n *\n * Applications invoke this explicitly on upgrade, once per device, typically\n * inside a startup hook before the primitives that depend on the migrated data\n * are read. It is not a replacement for the schema-version migration protocol\n * inside a single primitive — that handles shape evolution within one primitive\n * family, whereas this helper handles moves between primitive families.\n */\nexport async function migratePrimitive<Source, Destination>(\n source: MigratableState<Source>,\n destination: MigratableState<Destination>,\n transform: (value: Source) => Destination\n): Promise<void> {\n if ((source as unknown as unknown) === (destination as unknown as unknown)) {\n throw new MigrationError(\n `Cannot migrate a primitive to itself: \"${source.key}\" under ${source.primitive}.`,\n \"same-primitive-instance\",\n source.key,\n source.primitive\n );\n }\n if (migrationRegistry.isMarked(source.key, source.primitive)) {\n throw new MigrationError(\n `Cannot migrate: source \"${source.key}\" under $${source.primitive} has already been migrated. Migrations are one-way and one-time.`,\n \"already-migrated\",\n source.key,\n source.primitive\n );\n }\n await source.loaded;\n await destination.loaded;\n const transformed = transform(source.value);\n destination.value = transformed;\n migrationRegistry.mark(source.key, source.primitive);\n}\n",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"/**\n * pairing — Phase 2 first-cut pairing flow for $meshState.\n *\n * Two devices that want to share a $meshState document must exchange three\n * things before sync can begin: the issuer's Ed25519 signing public key\n * (so the receiver can verify ops authored by the issuer), the symmetric\n * document encryption key (so both sides can encrypt and decrypt the\n * shared document), and the issuer's stable peer id (so the receiver\n * knows which entry in its keyring the public key belongs to). This\n * module packs all three into a {@link PairingToken}, serialises it to a\n * compact binary format suitable for QR codes or copy-paste, and provides\n * the matching parse-and-apply flow on the receiving side.\n *\n * Threat model: pairing tokens are transmitted over an out-of-band channel\n * that the user can authenticate visually — typically a QR code on the\n * issuer's device, scanned by the receiver. Because anyone with the token\n * can decrypt and impersonate, the OOB channel is the only authentication.\n * The token includes a TTL (default 10 minutes) so that a token displayed\n * briefly and then dismissed cannot be replayed by an attacker who later\n * gains access to a screenshot. A production deployment would layer a\n * Short Authentication String (SAS) on top — both devices display a code\n * derived from the shared state, and the user verifies they match — but\n * that is a follow-up.\n *\n * The pairing flow is one-way in the Phase 2 first cut. The issuer\n * generates a token and displays it; the receiver applies it and picks\n * up the issuer's keys. The receiver's own keys reach the issuer through\n * the access set: when the receiver sends its first signed op, the issuer\n * records the receiver's public key alongside its peer id and adds it to\n * the keyring. A bidirectional pairing flow that exchanges both sides'\n * keys in a single QR exchange is straightforward to add later but adds\n * UX surface area that is not needed for the mesh transport to work.\n */\n\nimport { KEY_BYTES as ENCRYPTION_KEY_BYTES, generateDocumentKey } from \"./encryption\";\nimport type { MeshKeyring } from \"./mesh-network-adapter\";\nimport {\n generateSigningKeyPair,\n PUBLIC_KEY_BYTES as SIGNING_PUBLIC_KEY_BYTES,\n type SigningKeyPair,\n} from \"./signing\";\n\n/** Current pairing-token format version. Bumped if the wire format changes. */\nexport const PAIRING_TOKEN_VERSION = 1;\n\n/** Magic header bytes for sanity-checking parsed tokens. ASCII \"PPT1\". */\nexport const PAIRING_TOKEN_MAGIC = new Uint8Array([0x50, 0x50, 0x54, 0x31]);\n\n/** Length of the random nonce embedded in every token. */\nexport const PAIRING_NONCE_BYTES = 16;\n\n/** Default TTL applied when {@link createPairingToken} is called without an\n * explicit `ttlMs` option. */\nexport const DEFAULT_PAIRING_TTL_MS = 10 * 60 * 1000; // 10 minutes\n\n/**\n * The contents of a pairing token. Both sides operate on this shape; the\n * binary serialisation is purely for transport.\n */\nexport interface PairingToken {\n /** Format version. {@link PAIRING_TOKEN_VERSION} at the time of writing. */\n version: number;\n /** Stable peer id of the issuing device. The receiver records this as\n * the lookup key for the issuer's public key in its keyring. */\n issuerPeerId: string;\n /** Issuer's Ed25519 signing public key (32 bytes). */\n issuerPublicKey: Uint8Array;\n /** Shared document encryption key (32 bytes). The receiver stores this\n * under {@link documentKeyId} in its keyring. */\n documentKey: Uint8Array;\n /** Identifier under which the receiver stores the document key. For the\n * Phase 2 first cut this is typically the well-known DEFAULT_MESH_KEY_ID\n * from mesh-network-adapter; per-document keys (one entry per Automerge\n * document) are a follow-up. */\n documentKeyId: string;\n /** Unix timestamp (milliseconds) after which the token is considered\n * expired and {@link applyPairingToken} refuses to use it. */\n expiresAt: number;\n /** 16-byte random nonce. Carried through serialisation so two tokens\n * with otherwise-identical contents are still distinguishable. */\n nonce: Uint8Array;\n}\n\n/** Errors thrown by the pairing subsystem. */\nexport class PairingError extends Error {\n readonly code:\n | \"expired\"\n | \"wrong-magic\"\n | \"unknown-version\"\n | \"truncated\"\n | \"invalid-public-key\"\n | \"invalid-document-key\"\n | \"invalid-nonce\";\n\n constructor(message: string, code: PairingError[\"code\"]) {\n super(message);\n this.name = \"PairingError\";\n this.code = code;\n }\n}\n\n/**\n * Options for {@link createPairingToken}. The signing identity and the\n * document key are required; everything else is optional with sensible\n * defaults.\n */\nexport interface CreatePairingTokenOptions {\n /** The issuing device's signing keypair. Only the public key ends up in\n * the token; the secret never leaves the issuer. */\n identity: SigningKeyPair;\n /** Stable peer id for the issuing device. */\n issuerPeerId: string;\n /** The symmetric document key the receiver should adopt. If omitted, a\n * fresh key is generated and the caller is responsible for using the\n * same key on the issuing side too. */\n documentKey?: Uint8Array;\n /** Identifier under which the receiver stores the document key. */\n documentKeyId: string;\n /** Time-to-live in milliseconds. Defaults to {@link DEFAULT_PAIRING_TTL_MS}. */\n ttlMs?: number;\n /** Override the current time. Intended for tests; production code should\n * not pass this. */\n now?: () => number;\n}\n\n/**\n * Generate a fresh {@link PairingToken}. The token is ready to be\n * serialised and displayed to the receiver via an OOB channel.\n */\nexport function createPairingToken(options: CreatePairingTokenOptions): PairingToken {\n const now = options.now ? options.now() : Date.now();\n const ttlMs = options.ttlMs ?? DEFAULT_PAIRING_TTL_MS;\n const documentKey = options.documentKey ?? generateDocumentKey();\n const nonce = randomBytes(PAIRING_NONCE_BYTES);\n\n return {\n version: PAIRING_TOKEN_VERSION,\n issuerPeerId: options.issuerPeerId,\n issuerPublicKey: options.identity.publicKey,\n documentKey,\n documentKeyId: options.documentKeyId,\n expiresAt: now + ttlMs,\n nonce,\n };\n}\n\n/**\n * Generate a fresh pairing token *and* a fresh signing keypair in one call.\n * Convenience for first-time setup where the device has no existing\n * identity yet. Returns both so the caller can persist the keypair and\n * then display the token.\n */\nexport function createPairingTokenWithFreshIdentity(args: {\n issuerPeerId: string;\n documentKeyId: string;\n ttlMs?: number;\n now?: () => number;\n}): { identity: SigningKeyPair; token: PairingToken } {\n const identity = generateSigningKeyPair();\n const token = createPairingToken({\n identity,\n issuerPeerId: args.issuerPeerId,\n documentKeyId: args.documentKeyId,\n ttlMs: args.ttlMs,\n now: args.now,\n });\n return { identity, token };\n}\n\n/**\n * Check whether a token has expired against the current wall-clock time\n * (or an injected `now`).\n */\nexport function isPairingTokenExpired(token: PairingToken, now?: () => number): boolean {\n const t = now ? now() : Date.now();\n return t >= token.expiresAt;\n}\n\n/**\n * Apply a parsed and validated token to a {@link MeshKeyring}. Mutates the\n * keyring in place: adds the issuer's public key to {@link MeshKeyring.knownPeers}\n * and the document key to {@link MeshKeyring.documentKeys}.\n *\n * Throws {@link PairingError} with code \"expired\" if the token's TTL has\n * elapsed. The receiver is expected to apply the token promptly after\n * scanning; rejecting expired tokens prevents replay of long-lived\n * captures.\n */\nexport function applyPairingToken(\n token: PairingToken,\n keyring: MeshKeyring,\n options: { now?: () => number } = {}\n): void {\n if (isPairingTokenExpired(token, options.now)) {\n throw new PairingError(\n `Pairing token from ${token.issuerPeerId} expired at ${new Date(token.expiresAt).toISOString()}.`,\n \"expired\"\n );\n }\n keyring.knownPeers.set(token.issuerPeerId, token.issuerPublicKey);\n keyring.documentKeys.set(token.documentKeyId, token.documentKey);\n}\n\n// ─── binary serialisation ──────────────────────────────────────────────────\n\n/**\n * Serialise a token to a binary blob. The wire format is:\n *\n * [4 bytes: magic \"PPT1\"]\n * [1 byte: version]\n * [4 bytes BE: issuer id byte length]\n * [N bytes: issuer id UTF-8]\n * [32 bytes: issuer public key]\n * [32 bytes: document key]\n * [4 bytes BE: document key id byte length]\n * [M bytes: document key id UTF-8]\n * [8 bytes BE: expiresAt (uint64 milliseconds)]\n * [16 bytes: nonce]\n *\n * Use {@link encodePairingToken} to round-trip through a base64 string.\n */\nexport function serialisePairingToken(token: PairingToken): Uint8Array {\n validateForSerialisation(token);\n const issuerBytes = new TextEncoder().encode(token.issuerPeerId);\n const keyIdBytes = new TextEncoder().encode(token.documentKeyId);\n\n const total =\n PAIRING_TOKEN_MAGIC.length +\n 1 + // version\n 4 + // issuer id length\n issuerBytes.length +\n SIGNING_PUBLIC_KEY_BYTES +\n ENCRYPTION_KEY_BYTES +\n 4 + // doc key id length\n keyIdBytes.length +\n 8 + // expiresAt\n PAIRING_NONCE_BYTES;\n\n const out = new Uint8Array(total);\n let offset = 0;\n\n out.set(PAIRING_TOKEN_MAGIC, offset);\n offset += PAIRING_TOKEN_MAGIC.length;\n\n out[offset] = token.version;\n offset += 1;\n\n const view = new DataView(out.buffer);\n view.setUint32(offset, issuerBytes.length, false);\n offset += 4;\n out.set(issuerBytes, offset);\n offset += issuerBytes.length;\n\n out.set(token.issuerPublicKey, offset);\n offset += SIGNING_PUBLIC_KEY_BYTES;\n\n out.set(token.documentKey, offset);\n offset += ENCRYPTION_KEY_BYTES;\n\n view.setUint32(offset, keyIdBytes.length, false);\n offset += 4;\n out.set(keyIdBytes, offset);\n offset += keyIdBytes.length;\n\n // Write expiresAt as uint64 BE. JavaScript numbers are float64 but the\n // value is an integer count of milliseconds, well within 53-bit safe\n // range for any practical timestamp.\n view.setBigUint64(offset, BigInt(token.expiresAt), false);\n offset += 8;\n\n out.set(token.nonce, offset);\n offset += PAIRING_NONCE_BYTES;\n\n return out;\n}\n\n/**\n * Inverse of {@link serialisePairingToken}. Throws {@link PairingError} on\n * malformed input.\n */\nexport function parsePairingToken(bytes: Uint8Array): PairingToken {\n let offset = 0;\n\n // Magic\n if (bytes.length < PAIRING_TOKEN_MAGIC.length) {\n throw new PairingError(`Pairing token too short: ${bytes.length} bytes.`, \"truncated\");\n }\n for (let i = 0; i < PAIRING_TOKEN_MAGIC.length; i++) {\n if (bytes[offset + i] !== PAIRING_TOKEN_MAGIC[i]) {\n throw new PairingError(\n `Pairing token magic mismatch: not a Polly pairing token.`,\n \"wrong-magic\"\n );\n }\n }\n offset += PAIRING_TOKEN_MAGIC.length;\n\n // Version\n if (bytes.length < offset + 1) {\n throw new PairingError(\"Pairing token truncated at version.\", \"truncated\");\n }\n const version = bytes[offset] as unknown as number;\n offset += 1;\n if (version !== PAIRING_TOKEN_VERSION) {\n throw new PairingError(\n `Unknown pairing token version: ${version}. This Polly build supports version ${PAIRING_TOKEN_VERSION}.`,\n \"unknown-version\"\n );\n }\n\n // Issuer id\n if (bytes.length < offset + 4) {\n throw new PairingError(\"Pairing token truncated at issuer id length.\", \"truncated\");\n }\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const issuerLen = view.getUint32(offset, false);\n offset += 4;\n if (bytes.length < offset + issuerLen) {\n throw new PairingError(\"Pairing token truncated at issuer id.\", \"truncated\");\n }\n const issuerPeerId = new TextDecoder().decode(bytes.subarray(offset, offset + issuerLen));\n offset += issuerLen;\n\n // Issuer public key\n if (bytes.length < offset + SIGNING_PUBLIC_KEY_BYTES) {\n throw new PairingError(\"Pairing token truncated at public key.\", \"truncated\");\n }\n const issuerPublicKey = bytes.slice(offset, offset + SIGNING_PUBLIC_KEY_BYTES);\n offset += SIGNING_PUBLIC_KEY_BYTES;\n\n // Document key\n if (bytes.length < offset + ENCRYPTION_KEY_BYTES) {\n throw new PairingError(\"Pairing token truncated at document key.\", \"truncated\");\n }\n const documentKey = bytes.slice(offset, offset + ENCRYPTION_KEY_BYTES);\n offset += ENCRYPTION_KEY_BYTES;\n\n // Document key id\n if (bytes.length < offset + 4) {\n throw new PairingError(\"Pairing token truncated at document key id length.\", \"truncated\");\n }\n const keyIdLen = view.getUint32(offset, false);\n offset += 4;\n if (bytes.length < offset + keyIdLen) {\n throw new PairingError(\"Pairing token truncated at document key id.\", \"truncated\");\n }\n const documentKeyId = new TextDecoder().decode(bytes.subarray(offset, offset + keyIdLen));\n offset += keyIdLen;\n\n // Expires at\n if (bytes.length < offset + 8) {\n throw new PairingError(\"Pairing token truncated at expiry.\", \"truncated\");\n }\n const expiresAtBig = view.getBigUint64(offset, false);\n offset += 8;\n const expiresAt = Number(expiresAtBig);\n\n // Nonce\n if (bytes.length < offset + PAIRING_NONCE_BYTES) {\n throw new PairingError(\"Pairing token truncated at nonce.\", \"truncated\");\n }\n const nonce = bytes.slice(offset, offset + PAIRING_NONCE_BYTES);\n offset += PAIRING_NONCE_BYTES;\n\n return {\n version,\n issuerPeerId,\n issuerPublicKey,\n documentKey,\n documentKeyId,\n expiresAt,\n nonce,\n };\n}\n\n/**\n * Serialise a token and base64-encode it for QR-code or copy-paste display.\n * The encoding uses the standard base64 alphabet (not URL-safe) because\n * QR codes encode bytes directly and do not care about URL safety.\n */\nexport function encodePairingToken(token: PairingToken): string {\n const bytes = serialisePairingToken(token);\n // btoa expects a binary string. Convert via String.fromCharCode per byte;\n // safe for the ~150-byte token size and avoids the spread-into-fromCharCode\n // pattern that runs into argument-count limits on large arrays.\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary);\n}\n\n/**\n * Decode a base64-encoded pairing token produced by {@link encodePairingToken}.\n * Throws {@link PairingError} on malformed input.\n */\nexport function decodePairingToken(encoded: string): PairingToken {\n let binary: string;\n try {\n binary = atob(encoded);\n } catch {\n throw new PairingError(\"Pairing token is not valid base64.\", \"wrong-magic\");\n }\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return parsePairingToken(bytes);\n}\n\n// ─── helpers ───────────────────────────────────────────────────────────────\n\nfunction validateForSerialisation(token: PairingToken): void {\n if (token.issuerPublicKey.length !== SIGNING_PUBLIC_KEY_BYTES) {\n throw new PairingError(\n `Issuer public key must be ${SIGNING_PUBLIC_KEY_BYTES} bytes, got ${token.issuerPublicKey.length}.`,\n \"invalid-public-key\"\n );\n }\n if (token.documentKey.length !== ENCRYPTION_KEY_BYTES) {\n throw new PairingError(\n `Document key must be ${ENCRYPTION_KEY_BYTES} bytes, got ${token.documentKey.length}.`,\n \"invalid-document-key\"\n );\n }\n if (token.nonce.length !== PAIRING_NONCE_BYTES) {\n throw new PairingError(\n `Nonce must be ${PAIRING_NONCE_BYTES} bytes, got ${token.nonce.length}.`,\n \"invalid-nonce\"\n );\n }\n}\n\nfunction randomBytes(n: number): Uint8Array {\n const out = new Uint8Array(n);\n crypto.getRandomValues(out);\n return out;\n}\n",
|
|
25
25
|
"/**\n * revocation — Phase 2 key-revocation flow for $meshState.\n *\n * A $meshState deployment is only as secure as the keys it trusts. When a\n * device is lost, stolen, or compromised, its public key needs to be\n * removed from every other peer's trust set so that any operations signed\n * by that key are refused. This module provides the primitive pieces for\n * that flow: a signed revocation record that names the revoked peer id,\n * carries the issuer's identity, and travels between peers through the\n * same channels as any other signed message.\n *\n * A RevocationRecord is produced by a peer that has decided to revoke\n * another peer (typically because the user told their device to do so).\n * It is then serialised to a binary envelope, broadcast to other peers\n * through whatever transport is available, and applied to each receiving\n * keyring via {@link applyRevocation}. Applying a revocation adds the\n * target peer id to the keyring's {@link MeshKeyring.revokedPeers} set;\n * the MeshNetworkAdapter then drops all further messages from that peer,\n * even though the public key is still present in the knownPeers map.\n *\n * Signature layer: every revocation is signed by the *issuer's* key. The\n * receiver verifies the signature against the issuer's public key before\n * applying. This prevents a peer with no authority from forging a\n * revocation, at least in the signature-level threat model — a compromised\n * peer could still forge revocations naming any other peer, which is why\n * production deployments layer an access-set check on top (\"who is\n * authorised to revoke whom\"). That layer is a follow-up; the first cut\n * is signature-only, and any signed revocation from a known peer is\n * accepted.\n *\n * Why revocations are signed but not encrypted: revocations are public\n * in the sense that they name \"peer X is no longer trusted.\" There is no\n * confidentiality requirement — anyone seeing a revocation learns only\n * that someone has been kicked out, which is already observable from\n * the absence of their operations. Encrypting them would add cost without\n * adding security, so the wire format is signed-only.\n */\n\nimport type { MeshKeyring } from \"./mesh-network-adapter\";\nimport {\n decodeSignedEnvelope,\n encodeSignedEnvelope,\n openEnvelope as openSignedEnvelope,\n type SigningKeyPair,\n signEnvelope,\n} from \"./signing\";\n\n/** Current revocation-record format version. */\nexport const REVOCATION_RECORD_VERSION = 1;\n\n/** Magic header bytes for sanity-checking parsed revocations. ASCII \"PRV1\". */\nexport const REVOCATION_MAGIC = new Uint8Array([0x50, 0x52, 0x56, 0x31]);\n\n/**\n * The payload carried inside a signed revocation envelope.\n */\nexport interface RevocationRecord {\n /** Format version. */\n version: number;\n /** The peer id doing the revoking. Becomes the `senderId` of the signed\n * envelope when the record is serialised. */\n issuerPeerId: string;\n /** The peer id being revoked. After a receiver applies this record, its\n * MeshNetworkAdapter will drop all further messages from this peer. */\n revokedPeerId: string;\n /** Unix timestamp (milliseconds) when the revocation was issued. Carried\n * for audit and for tie-breaking in case an issuer issues multiple\n * revocations targeting the same peer. */\n issuedAt: number;\n /** Optional human-readable reason. Not used by the enforcement layer;\n * applications can surface it in audit logs. */\n reason?: string;\n}\n\n/** Errors thrown by the revocation subsystem. */\nexport class RevocationError extends Error {\n readonly code:\n | \"unknown-issuer\"\n | \"unauthorised-issuer\"\n | \"signature-invalid\"\n | \"truncated\"\n | \"wrong-magic\"\n | \"unknown-version\"\n | \"not-signed-by-issuer\";\n\n constructor(message: string, code: RevocationError[\"code\"]) {\n super(message);\n this.name = \"RevocationError\";\n this.code = code;\n }\n}\n\n/** Options for {@link createRevocation}. */\nexport interface CreateRevocationOptions {\n /** Signing keypair of the issuer. The private key signs the record; the\n * public key is looked up by the receiver via `issuerPeerId`. */\n issuer: SigningKeyPair;\n /** Stable peer id of the issuer. */\n issuerPeerId: string;\n /** Peer id to revoke. */\n revokedPeerId: string;\n /** Optional human-readable reason. */\n reason?: string;\n /** Override the current time. Intended for tests. */\n now?: () => number;\n}\n\n/**\n * Build a fresh {@link RevocationRecord}. The returned record is plain\n * data; use {@link encodeRevocation} to wrap it in a signed envelope\n * suitable for transport.\n */\nexport function createRevocation(options: CreateRevocationOptions): RevocationRecord {\n const now = options.now ? options.now() : Date.now();\n return {\n version: REVOCATION_RECORD_VERSION,\n issuerPeerId: options.issuerPeerId,\n revokedPeerId: options.revokedPeerId,\n issuedAt: now,\n ...(options.reason === undefined ? {} : { reason: options.reason }),\n };\n}\n\n/**\n * Apply a verified revocation to a keyring. Mutates the keyring in place:\n * adds the target peer id to {@link MeshKeyring.revokedPeers}. The caller\n * must verify the revocation (via {@link decodeRevocation}) before\n * applying; this function does not revalidate the signature.\n */\nexport function applyRevocation(record: RevocationRecord, keyring: MeshKeyring): void {\n keyring.revokedPeers.add(record.revokedPeerId);\n}\n\n/**\n * Revoke a peer locally without producing a transportable record. Useful\n * for the common case where an application decides to drop a peer on this\n * device without propagating the decision elsewhere (tests, single-device\n * setups). Peers that want the revocation to spread to other devices\n * should use {@link createRevocation} + {@link encodeRevocation}.\n */\nexport function revokePeerLocally(peerId: string, keyring: MeshKeyring): void {\n keyring.revokedPeers.add(peerId);\n}\n\n// ─── binary serialisation ──────────────────────────────────────────────────\n\n/**\n * Serialise a {@link RevocationRecord} to a binary payload ready for\n * signing. The layout is:\n *\n * [4 bytes: magic \"PRV1\"]\n * [1 byte: version]\n * [4 bytes BE: issuer id byte length]\n * [N bytes: issuer id UTF-8]\n * [4 bytes BE: revoked peer id byte length]\n * [M bytes: revoked peer id UTF-8]\n * [8 bytes BE: issuedAt (uint64 milliseconds)]\n * [4 bytes BE: reason byte length]\n * [R bytes: reason UTF-8]\n */\nfunction serialiseRevocationPayload(record: RevocationRecord): Uint8Array {\n const issuerBytes = new TextEncoder().encode(record.issuerPeerId);\n const revokedBytes = new TextEncoder().encode(record.revokedPeerId);\n const reasonBytes = new TextEncoder().encode(record.reason ?? \"\");\n\n const total =\n REVOCATION_MAGIC.length +\n 1 + // version\n 4 +\n issuerBytes.length +\n 4 +\n revokedBytes.length +\n 8 + // issuedAt\n 4 +\n reasonBytes.length;\n\n const out = new Uint8Array(total);\n let offset = 0;\n\n out.set(REVOCATION_MAGIC, offset);\n offset += REVOCATION_MAGIC.length;\n\n out[offset] = record.version;\n offset += 1;\n\n const view = new DataView(out.buffer);\n view.setUint32(offset, issuerBytes.length, false);\n offset += 4;\n out.set(issuerBytes, offset);\n offset += issuerBytes.length;\n\n view.setUint32(offset, revokedBytes.length, false);\n offset += 4;\n out.set(revokedBytes, offset);\n offset += revokedBytes.length;\n\n view.setBigUint64(offset, BigInt(record.issuedAt), false);\n offset += 8;\n\n view.setUint32(offset, reasonBytes.length, false);\n offset += 4;\n out.set(reasonBytes, offset);\n\n return out;\n}\n\n/** Inverse of {@link serialiseRevocationPayload}. */\nfunction parseRevocationPayload(bytes: Uint8Array): RevocationRecord {\n let offset = 0;\n\n if (bytes.length < REVOCATION_MAGIC.length) {\n throw new RevocationError(\"Revocation record too short for magic.\", \"truncated\");\n }\n for (let i = 0; i < REVOCATION_MAGIC.length; i++) {\n if (bytes[offset + i] !== REVOCATION_MAGIC[i]) {\n throw new RevocationError(\"Revocation record magic mismatch.\", \"wrong-magic\");\n }\n }\n offset += REVOCATION_MAGIC.length;\n\n if (bytes.length < offset + 1) {\n throw new RevocationError(\"Revocation record truncated at version.\", \"truncated\");\n }\n const version = bytes[offset] as unknown as number;\n offset += 1;\n if (version !== REVOCATION_RECORD_VERSION) {\n throw new RevocationError(`Unknown revocation record version: ${version}.`, \"unknown-version\");\n }\n\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n\n if (bytes.length < offset + 4) {\n throw new RevocationError(\"Revocation record truncated at issuer length.\", \"truncated\");\n }\n const issuerLen = view.getUint32(offset, false);\n offset += 4;\n if (bytes.length < offset + issuerLen) {\n throw new RevocationError(\"Revocation record truncated at issuer id.\", \"truncated\");\n }\n const issuerPeerId = new TextDecoder().decode(bytes.subarray(offset, offset + issuerLen));\n offset += issuerLen;\n\n if (bytes.length < offset + 4) {\n throw new RevocationError(\"Revocation record truncated at revoked id length.\", \"truncated\");\n }\n const revokedLen = view.getUint32(offset, false);\n offset += 4;\n if (bytes.length < offset + revokedLen) {\n throw new RevocationError(\"Revocation record truncated at revoked id.\", \"truncated\");\n }\n const revokedPeerId = new TextDecoder().decode(bytes.subarray(offset, offset + revokedLen));\n offset += revokedLen;\n\n if (bytes.length < offset + 8) {\n throw new RevocationError(\"Revocation record truncated at issuedAt.\", \"truncated\");\n }\n const issuedAt = Number(view.getBigUint64(offset, false));\n offset += 8;\n\n if (bytes.length < offset + 4) {\n throw new RevocationError(\"Revocation record truncated at reason length.\", \"truncated\");\n }\n const reasonLen = view.getUint32(offset, false);\n offset += 4;\n if (bytes.length < offset + reasonLen) {\n throw new RevocationError(\"Revocation record truncated at reason.\", \"truncated\");\n }\n const reason = new TextDecoder().decode(bytes.subarray(offset, offset + reasonLen));\n offset += reasonLen;\n\n return {\n version,\n issuerPeerId,\n revokedPeerId,\n issuedAt,\n ...(reason ? { reason } : {}),\n };\n}\n\n/**\n * Produce a signed, transportable binary blob from a revocation record.\n * Wraps the serialised payload in a {@link SignedEnvelope} signed by the\n * issuer's keypair, then encodes the envelope to bytes.\n */\nexport function encodeRevocation(record: RevocationRecord, issuer: SigningKeyPair): Uint8Array {\n const payload = serialiseRevocationPayload(record);\n const envelope = signEnvelope(payload, record.issuerPeerId, issuer.secretKey);\n return encodeSignedEnvelope(envelope);\n}\n\n/**\n * Parse and verify a signed revocation blob. Returns the decoded record\n * on success; throws {@link RevocationError} on any failure.\n *\n * Verification requires the keyring to already know the issuer's public\n * key (because Polly does not have a global PKI). If the issuer is\n * unknown, the caller receives `unknown-issuer` and can decide whether\n * to cache the revocation for later verification or drop it outright.\n *\n * Authorisation: when the keyring has a non-empty\n * {@link MeshKeyring.revocationAuthority} set, only issuers inside that\n * set can have their revocations accepted. An issuer outside the set\n * produces `unauthorised-issuer`. When the authority set is undefined\n * or empty, any signed revocation from a known peer is accepted — that\n * is the Phase 2 first-cut default, preserved for backward compatibility.\n */\nexport function decodeRevocation(bytes: Uint8Array, keyring: MeshKeyring): RevocationRecord {\n const envelope = decodeSignedEnvelope(bytes);\n const issuerKey = keyring.knownPeers.get(envelope.senderId);\n if (!issuerKey) {\n throw new RevocationError(\n `Revocation issuer ${envelope.senderId} is not in the local keyring.`,\n \"unknown-issuer\"\n );\n }\n if (\n keyring.revocationAuthority !== undefined &&\n keyring.revocationAuthority.size > 0 &&\n !keyring.revocationAuthority.has(envelope.senderId)\n ) {\n throw new RevocationError(\n `Revocation issuer ${envelope.senderId} is not in the keyring's revocation authority set.`,\n \"unauthorised-issuer\"\n );\n }\n let payloadBytes: Uint8Array;\n try {\n payloadBytes = openSignedEnvelope(envelope, issuerKey);\n } catch {\n throw new RevocationError(\n `Revocation signature failed verification for issuer ${envelope.senderId}.`,\n \"signature-invalid\"\n );\n }\n\n const record = parseRevocationPayload(payloadBytes);\n // Paranoid cross-check: the payload's claimed issuer must match the\n // envelope's authenticated sender. Mismatch means a forged payload.\n if (record.issuerPeerId !== envelope.senderId) {\n throw new RevocationError(\n `Revocation payload claims issuer ${record.issuerPeerId} but the envelope was signed by ${envelope.senderId}.`,\n \"not-signed-by-issuer\"\n );\n }\n return record;\n}\n"
|
|
26
26
|
],
|
|
27
|
-
"mappings": "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",
|
|
28
|
-
"debugId": "
|
|
27
|
+
"mappings": "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",
|
|
28
|
+
"debugId": "D3C1A8646491034D64756E2164756E21",
|
|
29
29
|
"names": []
|
|
30
30
|
}
|
|
@@ -26,6 +26,19 @@ export interface SignalingMessage {
|
|
|
26
26
|
payload?: unknown;
|
|
27
27
|
reason?: "unknown-target" | "not-joined" | "malformed";
|
|
28
28
|
}
|
|
29
|
+
/** A frame whose `type` is outside the built-in {@link SignalingMessage}
|
|
30
|
+
* vocabulary. Consumers who want to layer application protocols on the
|
|
31
|
+
* signalling socket — pairing return tokens, presence pings, anything
|
|
32
|
+
* else that benefits from sharing the existing connection and its
|
|
33
|
+
* reconnect state — receive these through {@link MeshSignalingClientOptions.onCustomFrame}
|
|
34
|
+
* and produce them through {@link MeshSignalingClient.sendCustom}. Polly
|
|
35
|
+
* does not interpret the body; the signalling server routes it per its
|
|
36
|
+
* own conventions. The field `type` is always present; everything else
|
|
37
|
+
* is application-defined. */
|
|
38
|
+
export interface CustomSignalingFrame {
|
|
39
|
+
type: string;
|
|
40
|
+
[key: string]: unknown;
|
|
41
|
+
}
|
|
29
42
|
/** Options for constructing a {@link MeshSignalingClient}. */
|
|
30
43
|
export interface MeshSignalingClientOptions {
|
|
31
44
|
/** The signalling server URL (ws:// or wss://). */
|
|
@@ -53,6 +66,14 @@ export interface MeshSignalingClientOptions {
|
|
|
53
66
|
* (including graceful disconnect and abrupt drops detected by the
|
|
54
67
|
* server). Fires at most once per departure. */
|
|
55
68
|
onPeerLeft?: (peerId: string) => void;
|
|
69
|
+
/** Optional callback invoked for any frame whose `type` is outside the
|
|
70
|
+
* built-in {@link SignalingMessage} vocabulary. Consumers use this to
|
|
71
|
+
* layer their own protocol on top of the signalling socket — pairing
|
|
72
|
+
* return tokens, presence pings, anything else that benefits from
|
|
73
|
+
* sharing the existing connection and its reconnect state. A frame
|
|
74
|
+
* that arrives before the join handshake completes or that fails to
|
|
75
|
+
* parse as JSON is dropped silently, as with the built-in types. */
|
|
76
|
+
onCustomFrame?: (frame: CustomSignalingFrame) => void;
|
|
56
77
|
/** WebSocket constructor. Defaults to `globalThis.WebSocket`. Inject a
|
|
57
78
|
* different implementation (e.g. `ws` package's `WebSocket`) when running
|
|
58
79
|
* in an environment without a native WebSocket global, or to use a custom
|
|
@@ -69,6 +90,7 @@ export declare class MeshSignalingClient {
|
|
|
69
90
|
private readonly onPeersPresent?;
|
|
70
91
|
private readonly onPeerJoined?;
|
|
71
92
|
private readonly onPeerLeft?;
|
|
93
|
+
private readonly onCustomFrame?;
|
|
72
94
|
private socket;
|
|
73
95
|
private joined;
|
|
74
96
|
private stopping;
|
|
@@ -89,6 +111,7 @@ export declare class MeshSignalingClient {
|
|
|
89
111
|
* below the linter's cognitive-complexity ceiling.
|
|
90
112
|
*/
|
|
91
113
|
private dispatchFrame;
|
|
114
|
+
private builtInHandler;
|
|
92
115
|
/**
|
|
93
116
|
* Send a signal to another peer via the signalling server. The server
|
|
94
117
|
* validates the sender (replacing the claimed peerId with the
|
|
@@ -96,6 +119,17 @@ export declare class MeshSignalingClient {
|
|
|
96
119
|
* the message was sent, false if the connection is not open.
|
|
97
120
|
*/
|
|
98
121
|
sendSignal(targetPeerId: string, payload: unknown): boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Send a custom frame over the signalling socket. The frame is serialised
|
|
124
|
+
* as `{ type, ...payload }`. The server must be configured to route this
|
|
125
|
+
* frame type (polly does not interpret it). Returns true if the message
|
|
126
|
+
* was sent, false if the connection is not open.
|
|
127
|
+
*
|
|
128
|
+
* Intended for application-level protocols that want to share the
|
|
129
|
+
* existing signalling connection — for example, a pairing flow that
|
|
130
|
+
* delivers a reciprocal token from the scanner back to the issuer.
|
|
131
|
+
*/
|
|
132
|
+
sendCustom(type: string, payload?: Record<string, unknown>): boolean;
|
|
99
133
|
/**
|
|
100
134
|
* Close the underlying WebSocket connection. The server's close handler
|
|
101
135
|
* will evict this peer from its routing table. Also cancels any
|
|
@@ -27,6 +27,7 @@ import puppeteer from "puppeteer";
|
|
|
27
27
|
import { Elysia } from "elysia";
|
|
28
28
|
function signalingServer(options = {}) {
|
|
29
29
|
const path = options.path ?? "/polly/signaling";
|
|
30
|
+
const onCustomFrame = options.onCustomFrame;
|
|
30
31
|
const peerSockets = new Map;
|
|
31
32
|
const parseMessage = (raw) => {
|
|
32
33
|
try {
|
|
@@ -115,6 +116,13 @@ function signalingServer(options = {}) {
|
|
|
115
116
|
handleSignal(ws, msg);
|
|
116
117
|
return;
|
|
117
118
|
}
|
|
119
|
+
if (onCustomFrame !== undefined) {
|
|
120
|
+
const wsWithData = ws;
|
|
121
|
+
const senderId = wsWithData.data["peerId"];
|
|
122
|
+
const peerId = typeof senderId === "string" ? senderId : undefined;
|
|
123
|
+
onCustomFrame(wsWithData, msg, peerId);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
118
126
|
ws.send({ type: "error", reason: "malformed" });
|
|
119
127
|
},
|
|
120
128
|
close(ws) {
|
|
@@ -261,4 +269,4 @@ console.log(`
|
|
|
261
269
|
[browser-runner] ${totalPassed} passed, ${totalFailed} failed`);
|
|
262
270
|
process.exit(totalFailed > 0 ? 1 : 0);
|
|
263
271
|
|
|
264
|
-
//# debugId=
|
|
272
|
+
//# debugId=C5D6EF174C50CA8A64756E2164756E21
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"sources": ["../tools/test/src/browser/run.ts", "../src/elysia/signaling-server-plugin.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
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 from \"puppeteer\";\nimport { signalingServer } from \"../../../../src/elysia/signaling-server-plugin\";\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\nconst automergeBase64Path = resolve(\n process.cwd(),\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 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\nconst signalingPort = 39000 + Math.floor(Math.random() * 1000);\nconst signalingApp = new Elysia()\n .use(signalingServer({ path: \"/polly/signaling\" }))\n .listen(signalingPort);\nconsole.log(`[browser-runner] signaling server on ws://127.0.0.1:${signalingPort}/polly/signaling`);\n\n// ─── Launch browser ────────────────────────────────────────────────────────\n\nconst browser = await puppeteer.launch({\n headless,\n args: [\"--no-sandbox\", \"--disable-setuid-sandbox\"],\n});\n\nlet totalPassed = 0;\nlet totalFailed = 0;\n\nfor (const testFile of testFiles) {\n const shortName = testFile.replace(`${testDir}/`, \"\");\n console.log(`\\n[browser-runner] running ${shortName}`);\n\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 totalFailed += 1;\n continue;\n }\n\n const jsText = await buildResult.outputs[0]?.text();\n if (!jsText) {\n console.log(\" ❌ build produced no output\");\n totalFailed += 1;\n continue;\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 const page = await browser.newPage();\n page.on(\"console\", (msg) => {\n const text = msg.text();\n if (text.includes(\"[test]\")) {\n console.log(` ${text}`);\n }\n });\n page.on(\"pageerror\", (err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.log(` ❌ page error: ${msg}`);\n });\n\n await page.goto(`http://127.0.0.1:${server.port}/`, { waitUntil: \"domcontentloaded\" });\n\n const timeout = 15_000;\n const deadline = Date.now() + timeout;\n let finished = false;\n while (Date.now() < deadline) {\n finished = await page.evaluate(\n () => (window as unknown as Record<string, unknown>)[\"__done\"] === true\n );\n if (finished) break;\n await new Promise((r) => setTimeout(r, 100));\n }\n\n if (!finished) {\n console.log(` ❌ timed out after ${timeout}ms`);\n totalFailed += 1;\n await page.close();\n server.stop();\n continue;\n }\n\n const results = await page.evaluate(\n () =>\n (window as unknown as Record<string, unknown>)[\"__testResults\"] as unknown as Array<{\n name: string;\n passed: boolean;\n error?: string;\n }>\n );\n\n for (const r of results ?? []) {\n if (r.passed) {\n console.log(` ✅ ${r.name}`);\n totalPassed += 1;\n } else {\n console.log(` ❌ ${r.name}: ${r.error}`);\n totalFailed += 1;\n }\n }\n\n await page.close();\n server.stop();\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
|
-
"// @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\nexport interface SignalingServerOptions {\n /** WebSocket route path. Defaults to \"/polly/signaling\". */\n path?: string;\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 // 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 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"
|
|
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
7
|
],
|
|
8
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AA2BA;AACA;AACA,mBAAS;AACT;;;ACsBA;
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "C5D6EF174C50CA8A64756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fairfox/polly",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Multi-execution-context framework with reactive state and cross-context messaging for Chrome extensions, PWAs, and worker-based applications",
|