statewire 0.13.0 → 0.14.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.
Files changed (43) hide show
  1. package/README.md +2 -0
  2. package/dist/client/connection.d.ts +5 -2
  3. package/dist/client/connection.d.ts.map +1 -1
  4. package/dist/client/connection.js +54 -19
  5. package/dist/client/connection.js.map +1 -1
  6. package/dist/client/core.d.ts +2 -2
  7. package/dist/client/core.d.ts.map +1 -1
  8. package/dist/client/core.js +5 -4
  9. package/dist/client/core.js.map +1 -1
  10. package/dist/client/session.d.ts.map +1 -1
  11. package/dist/client/session.js +6 -2
  12. package/dist/client/session.js.map +1 -1
  13. package/dist/host/http.d.ts +2 -1
  14. package/dist/host/http.d.ts.map +1 -1
  15. package/dist/host/http.js +36 -3
  16. package/dist/host/http.js.map +1 -1
  17. package/dist/host/socket.d.ts +11 -2
  18. package/dist/host/socket.d.ts.map +1 -1
  19. package/dist/host/socket.js +135 -6
  20. package/dist/host/socket.js.map +1 -1
  21. package/dist/host-internal.d.ts +9 -1
  22. package/dist/host-internal.d.ts.map +1 -1
  23. package/dist/statewire.d.ts +16 -11
  24. package/dist/statewire.d.ts.map +1 -1
  25. package/dist/statewire.js +2 -2
  26. package/dist/statewire.js.map +1 -1
  27. package/dist/transports/sse.d.ts +2 -0
  28. package/dist/transports/sse.d.ts.map +1 -1
  29. package/dist/transports/sse.js +4 -0
  30. package/dist/transports/sse.js.map +1 -1
  31. package/dist/transports/ws.d.ts.map +1 -1
  32. package/dist/transports/ws.js +4 -0
  33. package/dist/transports/ws.js.map +1 -1
  34. package/package.json +1 -1
  35. package/src/client/connection.ts +67 -20
  36. package/src/client/core.ts +4 -3
  37. package/src/client/session.ts +10 -2
  38. package/src/host/http.ts +40 -2
  39. package/src/host/socket.ts +220 -6
  40. package/src/host-internal.ts +14 -1
  41. package/src/statewire.ts +23 -10
  42. package/src/transports/sse.ts +6 -0
  43. package/src/transports/ws.ts +4 -0
@@ -407,6 +407,128 @@ const message = (h, conn, data) => {
407
407
  const admission = admitFrame(h, rec, frame);
408
408
  if (admission.type === "refused") sendTo(h, conn, JSON.stringify(admission.syn));
409
409
  };
410
+ const closePending = (h, pending, code, reason) => {
411
+ if (!pending.open) return;
412
+ pending.open = false;
413
+ h.pendingConns.delete(pending);
414
+ if (pending.timer !== null) clearTimeout(pending.timer);
415
+ try {
416
+ pending.socket.close(code, reason);
417
+ } catch {}
418
+ };
419
+ const sendPending = (pending, data) => {
420
+ if (!pending.open) return false;
421
+ try {
422
+ pending.socket.send(data);
423
+ return true;
424
+ } catch {
425
+ return false;
426
+ }
427
+ };
428
+ const rejectPendingAuthorization = (h, pending, error) => {
429
+ const response = error instanceof Response ? error : null;
430
+ const unauthorized = response?.status === 401 || response?.status === 403;
431
+ const status = response?.status;
432
+ const message = unauthorized ? "unauthorized" : response?.statusText || (status === void 0 ? "authorization failed" : `HTTP ${status}`);
433
+ sendPending(pending, JSON.stringify({ fin: {
434
+ reason: unauthorized ? "unauthorized" : "error",
435
+ message,
436
+ ...status !== void 0 && { status }
437
+ } }));
438
+ closePending(h, pending, unauthorized ? 1008 : 1011, message);
439
+ };
440
+ const normalizedHeaders = (headers) => Object.fromEntries(new Headers(headers));
441
+ const connectAuthorized = (h, clientId, socket, options) => {
442
+ const authorize = h.authorize;
443
+ if (authorize === void 0 || options.authorized === true) return register(h, clientId, socket, options.authorized === true)?.connection ?? null;
444
+ const refuse = (code, reason) => {
445
+ try {
446
+ socket.close(code, reason);
447
+ } catch {}
448
+ return null;
449
+ };
450
+ if (h.disposed) return refuse(1001, "disposed");
451
+ if (!CLIENT_ID_RE.test(clientId)) return refuse(1008, "invalid client id");
452
+ flush(h);
453
+ if (h.finished !== null) {
454
+ try {
455
+ socket.send(JSON.stringify({ fin: h.finished }));
456
+ } catch {}
457
+ return refuse(1e3, "finished");
458
+ }
459
+ const pending = {
460
+ socket,
461
+ open: true,
462
+ authorizing: false,
463
+ timer: null,
464
+ connection: null
465
+ };
466
+ h.pendingConns.add(pending);
467
+ pending.timer = setTimeout(() => rejectPendingAuthorization(h, pending, new Response(null, { status: 401 })), h.wsInitTimeoutMs);
468
+ pending.timer.unref?.();
469
+ return {
470
+ clientId,
471
+ message: (data) => {
472
+ if (pending.connection !== null) {
473
+ pending.connection.message(data);
474
+ return;
475
+ }
476
+ if (!pending.open || h.disposed || h.finished !== null) return;
477
+ if (pending.authorizing) {
478
+ closePending(h, pending, 1008, "authorization pending");
479
+ return;
480
+ }
481
+ let frame;
482
+ try {
483
+ frame = parseFrame(data, true);
484
+ } catch (error) {
485
+ const reason = violationReason(error);
486
+ if (reason === null) throw error;
487
+ sendPending(pending, JSON.stringify({ fin: {
488
+ reason: "error",
489
+ message: `protocol violation: ${reason}`
490
+ } }));
491
+ closePending(h, pending, 1008, reason);
492
+ return;
493
+ }
494
+ if (frame.headers === null) {
495
+ rejectPendingAuthorization(h, pending, new Response(null, { status: 401 }));
496
+ return;
497
+ }
498
+ let headers;
499
+ try {
500
+ headers = normalizedHeaders(frame.headers);
501
+ } catch {
502
+ sendPending(pending, JSON.stringify({ fin: {
503
+ reason: "error",
504
+ message: "protocol violation: malformed headers"
505
+ } }));
506
+ closePending(h, pending, 1008, "malformed headers");
507
+ return;
508
+ }
509
+ pending.authorizing = true;
510
+ Promise.resolve().then(() => authorize({ headers })).then(() => {
511
+ if (!pending.open || h.disposed || h.finished !== null) return;
512
+ options.onAuthorized?.();
513
+ pending.open = false;
514
+ h.pendingConns.delete(pending);
515
+ if (pending.timer !== null) clearTimeout(pending.timer);
516
+ const registration = register(h, clientId, socket, true);
517
+ if (registration === null) return;
518
+ pending.connection = registration.connection;
519
+ if (frame.ctx.length === 0 && frame.cmd.length === 0) return;
520
+ const admission = admitFrame(h, registration.rec, frame);
521
+ if (admission.type === "refused") sendTo(h, registration.conn, JSON.stringify(admission.syn));
522
+ }).catch((error) => {
523
+ if (pending.open) rejectPendingAuthorization(h, pending, error);
524
+ });
525
+ },
526
+ close: () => {
527
+ if (pending.connection !== null) pending.connection.close();
528
+ else closePending(h, pending);
529
+ }
530
+ };
531
+ };
410
532
  const gcClients = (h) => {
411
533
  let excess = h.clients.size - h.clientRecordLimit;
412
534
  if (excess <= 0) return;
@@ -419,7 +541,7 @@ const gcClients = (h) => {
419
541
  excess -= 1;
420
542
  }
421
543
  };
422
- const register = (h, clientId, socket) => {
544
+ const register = (h, clientId, socket, sawFrame = false) => {
423
545
  const refuse = (code, reason) => {
424
546
  try {
425
547
  socket.close(code, reason);
@@ -454,7 +576,7 @@ const register = (h, clientId, socket) => {
454
576
  clientId,
455
577
  socket,
456
578
  open: true,
457
- sawFrame: false,
579
+ sawFrame,
458
580
  lastSentAt: 0,
459
581
  lease: null
460
582
  };
@@ -486,12 +608,16 @@ const register = (h, clientId, socket) => {
486
608
  }
487
609
  };
488
610
  };
489
- const connect = (h, clientId, socket) => {
490
- return register(h, clientId, socket)?.connection ?? null;
611
+ const connect = (h, clientId, socket, options = {}) => {
612
+ return connectAuthorized(h, clientId, socket, options);
491
613
  };
492
614
  const finish = (h, fin) => {
493
615
  if (h.finished !== null || h.disposed) return;
494
616
  h.finished = fin;
617
+ for (const pending of [...h.pendingConns]) {
618
+ sendPending(pending, JSON.stringify({ fin }));
619
+ closePending(h, pending, 1e3, fin.reason);
620
+ }
495
621
  flush(h, fin);
496
622
  };
497
623
  const resume = (h) => {
@@ -510,11 +636,13 @@ const useSocketHost = (transport, options) => {
510
636
  const [h] = useState(() => {
511
637
  const host = {
512
638
  heartbeatMs: 15e3,
639
+ wsInitTimeoutMs: 5e3,
513
640
  clientRecordLimit: CLIENT_RECORD_LIMIT,
514
641
  finOnIdle: false,
515
642
  authorize: void 0,
516
643
  clients: /* @__PURE__ */ new Map(),
517
644
  conns: /* @__PURE__ */ new Set(),
645
+ pendingConns: /* @__PURE__ */ new Set(),
518
646
  pendingOps: [],
519
647
  pendingApplied: /* @__PURE__ */ new Map(),
520
648
  pendingCmds: /* @__PURE__ */ new Map(),
@@ -530,7 +658,7 @@ const useSocketHost = (transport, options) => {
530
658
  host.flushScheduled = false;
531
659
  flush(host);
532
660
  }),
533
- connect: (clientId, socket) => connect(host, clientId, socket),
661
+ connect: (clientId, socket, connectOptions) => connect(host, clientId, socket, connectOptions),
534
662
  finish: (fin) => finish(host, fin),
535
663
  stream: (request) => stream(host, request),
536
664
  frames: (request_0) => frames(host, request_0)
@@ -538,6 +666,7 @@ const useSocketHost = (transport, options) => {
538
666
  return host;
539
667
  });
540
668
  setHeartbeatMs(h, options?.heartbeatIntervalMs ?? 15e3);
669
+ h.wsInitTimeoutMs = options?.wsInitTimeoutMs ?? 5e3;
541
670
  h.clientRecordLimit = options?.clientRecordLimit ?? CLIENT_RECORD_LIMIT;
542
671
  h.finOnIdle = options?.finOnIdle ?? false;
543
672
  h.authorize = options?.authorize;
@@ -567,7 +696,7 @@ const StatewireSocketHost = (transport, options) => {
567
696
  const root = createTapRoot(SocketHostRoot);
568
697
  let disposed = false;
569
698
  return {
570
- connect: (clientId, socket) => flushTapSync(() => root.getValue().connect(clientId, socket)),
699
+ connect: (clientId, socket, connectOptions) => flushTapSync(() => root.getValue().connect(clientId, socket, connectOptions)),
571
700
  stream: (request) => flushTapSync(() => root.getValue().stream(request)),
572
701
  frames: (request) => flushTapSync(() => root.getValue().frames(request)),
573
702
  finish: (fin) => flushTapSync(() => root.getValue().finish(fin)),
@@ -1 +1 @@
1
- {"version":3,"file":"socket.js","names":["useEffect","useState","createTapRoot","flushTapSync","useResource","ResourceElement","getCommandsHost","getStateHost","CommandsHost","CommandsOutcome","StatewireSendError","Statewire","StatewireHost","StatewireHostInternal","encodeValue","reviveValue","createMacrotaskPoster","StatewireMetaEntry","StatewirePath","StatewireCmd","StatewireEnvelope","frames","serveFrames","stream","serveStream","CLIENT_ID_RE","RESULT_TTL_MS","RESULT_LIMIT","CLIENT_RECORD_LIMIT","WireOp","op","path","value","meta","Admission","seq","method","applied","appliedSent","settled","ClientRec","id","lastSeq","ctxSeq","touched","context","Record","results","Map","ts","cmd","inflight","Conn","clientId","socket","Socket","open","sawFrame","lastSentAt","lease","violation","reason","Object","assign","Error","name","violationReason","error","message","CtxStatement","CmdStatement","params","ParsedFrame","headers","ctx","isPlainObject","Array","isArray","parseLane","length","statements","prev","statement","Number","isInteger","push","contextValue","ops","undefined","rejectUnknown","parseFrameValue","frame","first","keys","unknown","filter","key","sort","raw","values","some","parseFrame","JSON","parse","encodePayload","payload","cmdOf","adm","outcome","type","failure","fate","code","String","SocketHostState","heartbeatMs","clientRecordLimit","finOnIdle","authorize","SocketHostOptions","clients","conns","Set","pendingOps","pendingApplied","pendingCmds","idleWire","finished","Fin","disposed","flushScheduled","heartbeatTimer","ReturnType","setInterval","stateHost","StateHost","commandsHost","current","post","connect","SocketConnection","finish","fin","request","Request","Promise","Response","scheduleFlush","h","recordOp","attach","next","nextState","state","nextCommands","commands","submit","setOnOp","closeConn","conn","delete","close","size","clearInterval","sendTo","data","Date","now","send","ensureHeartbeat","unref","setHeartbeatMs","ms","idleLevel","rec","flush","takeChanged","queueApplied","level","edge","cmds","appliedEntries","get","map","packet","idle","stringify","verdicts","list","set","queueCmd","retain","newest","Math","max","entry","min","admittedThrough","reemit","cached","settleCmd","settleWire","callerOf","Caller","isConnected","rejectStatement","admitCmd","names","methods","caller","onApplied","onSettle","catch","FrameAdmission","syn","admitFrame","through","ctxNew","s","cmdNew","at","dur","admission","gcClients","excess","live","oldest","a","b","has","Registration","connection","register","refuse","test","known","created","add","snapshot","hello","registration","resume","suspend","useSocketHost","transport","options","Pick","SocketHost","host","heartbeatIntervalMs","StatewireSocketHost","SocketHostRoot","root","getValue","dispose","unmount"],"sources":["../../src/host/socket.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { createTapRoot, flushTapSync, useResource } from \"@assistant-ui/tap\";\nimport type { ResourceElement } from \"@assistant-ui/tap\";\nimport { getCommandsHost, getStateHost } from \"./host\";\nimport type { CommandsHost, CommandsOutcome } from \"./host\";\nimport { StatewireSendError } from \"../types\";\nimport type { Statewire } from \"../types\";\nimport type { StatewireHost } from \"../host\";\nimport type { StatewireHostInternal } from \"../host-internal\";\nimport { encodeValue, reviveValue } from \"../wire/meta\";\nimport { createMacrotaskPoster } from \"../util/macrotask\";\nimport type { StatewireMetaEntry } from \"../wire/meta\";\nimport type { StatewirePath } from \"../wire/ops\";\nimport type { StatewireCmd, StatewireEnvelope } from \"../client/connection\";\nimport { frames as serveFrames, stream as serveStream } from \"./http\";\n\nexport const CLIENT_ID_RE = /^[A-Za-z0-9._~-]{1,256}$/;\nconst RESULT_TTL_MS = 30_000;\nconst RESULT_LIMIT = 256;\nconst CLIENT_RECORD_LIMIT = 1024;\n\ntype WireOp = {\n op: string;\n path?: StatewirePath;\n value?: unknown;\n meta?: StatewireMetaEntry[];\n};\n\ntype Admission = {\n seq: number;\n method: string;\n applied: boolean;\n appliedSent: boolean;\n settled: boolean;\n};\n\nexport type ClientRec = {\n id: string;\n lastSeq: number;\n ctxSeq: number;\n touched: number;\n context: Record<string, unknown> | null;\n results: Map<number, { ts: number; cmd: StatewireCmd }>;\n inflight: Map<number, Admission>;\n};\n\nexport type Conn = {\n clientId: string;\n socket: StatewireHostInternal.Socket;\n open: boolean;\n sawFrame: boolean;\n lastSentAt: number;\n lease: string | null;\n};\n\n// ─── frame parsing ──────────────────────────────────────\n\nconst violation = (reason: string): never => {\n throw Object.assign(new Error(reason), { name: \"StatewireViolation\" });\n};\n\nconst violationReason = (error: unknown): string | null =>\n error instanceof Error && error.name === \"StatewireViolation\"\n ? error.message\n : null;\n\ntype CtxStatement = { seq: number; value: Record<string, unknown> };\ntype CmdStatement = {\n seq: number;\n method: string;\n params: unknown;\n meta?: unknown;\n};\n\nexport type ParsedFrame = {\n headers: Record<string, string> | null;\n ctx: CtxStatement[];\n cmd: CmdStatement[];\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst parseLane = (value: unknown): Record<string, unknown>[] => {\n if (!Array.isArray(value)) return violation(\"malformed frame\");\n if (value.length === 0) return violation(\"empty lane\");\n const statements: Record<string, unknown>[] = [];\n let prev: number | null = null;\n for (const statement of value) {\n if (!isPlainObject(statement)) return violation(\"malformed statement\");\n const seq = statement[\"seq\"];\n if (typeof seq !== \"number\" || !Number.isInteger(seq) || seq < 1) {\n return violation(\"malformed statement\");\n }\n if (prev !== null && seq !== prev + 1) return violation(\"malformed frame\");\n prev = seq;\n statements.push(statement);\n }\n return statements;\n};\n\n/** v1 ctx statements state the context whole: one root replace with an object value. */\nconst contextValue = (ops: unknown): Record<string, unknown> => {\n if (!Array.isArray(ops) || ops.length !== 1) {\n throw new Error(\"context must be a single-op array\");\n }\n const op = ops[0] as Record<string, unknown> | null;\n if (\n !isPlainObject(op) ||\n op[\"op\"] !== \"replace\" ||\n !Array.isArray(op[\"path\"]) ||\n op[\"path\"].length !== 0\n ) {\n throw new Error(\"context op must be a root replace\");\n }\n const value =\n op[\"meta\"] !== undefined\n ? reviveValue(op[\"value\"], op[\"meta\"], { rejectUnknown: true })\n : op[\"value\"];\n if (!isPlainObject(value)) {\n throw new Error(\"context value must be an object\");\n }\n return value;\n};\n\nexport const parseFrameValue = (\n frame: unknown,\n first: boolean,\n): ParsedFrame => {\n if (!isPlainObject(frame)) return violation(\"malformed frame\");\n const keys = Object.keys(frame);\n if (keys.length === 0) return violation(\"malformed frame\");\n const unknown = keys\n .filter((key) => key !== \"headers\" && key !== \"ctx\" && key !== \"cmd\")\n .sort();\n if (unknown.length > 0)\n return violation(`unknown frame key: '${unknown[0]}'`);\n let headers: Record<string, string> | null = null;\n if (frame[\"headers\"] !== undefined) {\n if (!first) return violation(\"mid-session headers\");\n const raw = frame[\"headers\"];\n if (\n !isPlainObject(raw) ||\n Object.values(raw).some((value) => typeof value !== \"string\")\n ) {\n return violation(\"malformed headers\");\n }\n headers = raw as Record<string, string>;\n }\n const ctx: CtxStatement[] = [];\n if (frame[\"ctx\"] !== undefined) {\n for (const statement of parseLane(frame[\"ctx\"])) {\n try {\n ctx.push({\n seq: statement[\"seq\"] as number,\n value: contextValue(statement[\"ops\"]),\n });\n } catch {\n return violation(\"invalid-context\");\n }\n }\n }\n const cmd: CmdStatement[] = [];\n if (frame[\"cmd\"] !== undefined) {\n for (const statement of parseLane(frame[\"cmd\"])) {\n const method = statement[\"method\"];\n if (typeof method !== \"string\" || !(\"params\" in statement)) {\n return violation(\"malformed statement\");\n }\n cmd.push({\n seq: statement[\"seq\"] as number,\n method,\n params: statement[\"params\"],\n ...(statement[\"meta\"] !== undefined && { meta: statement[\"meta\"] }),\n });\n }\n }\n return { headers, ctx, cmd };\n};\n\nexport const parseFrame = (raw: string, first: boolean): ParsedFrame => {\n let frame: unknown;\n try {\n frame = JSON.parse(raw);\n } catch {\n return violation(\"malformed frame\");\n }\n return parseFrameValue(frame, first);\n};\n\n// ─── verdict encoding ───────────────────────────────────\n\nconst encodePayload = (\n payload: unknown,\n): { payload?: unknown; meta?: StatewireMetaEntry[] } => {\n if (payload === undefined) return {};\n const { value, meta } = encodeValue(payload);\n return { payload: value, ...(meta !== undefined && { meta }) };\n};\n\nconst cmdOf = (adm: Admission, outcome: CommandsOutcome): StatewireCmd => {\n if (outcome.type === \"accepted\") {\n return { seq: adm.seq, type: \"result\", ...encodePayload(outcome.payload) };\n }\n const failure =\n outcome.error instanceof StatewireSendError ? outcome.error.failure : null;\n switch (failure?.fate) {\n case \"failed\":\n return {\n seq: adm.seq,\n type: \"failed\",\n ...(failure.message !== undefined && { message: failure.message }),\n };\n case \"rejected\": {\n if (failure.code !== undefined) {\n const message =\n failure.code === \"unknown-command\"\n ? `unknown method: '${adm.method}'`\n : failure.message;\n return {\n seq: adm.seq,\n type: \"rejected\",\n code: failure.code,\n ...(message !== undefined && { message }),\n };\n }\n return {\n seq: adm.seq,\n type: \"rejected\",\n ...(failure.message !== undefined && { message: failure.message }),\n ...encodePayload(failure.payload),\n };\n }\n default:\n return {\n seq: adm.seq,\n type: \"failed\",\n message:\n outcome.error instanceof Error\n ? outcome.error.message\n : String(outcome.error),\n };\n }\n};\n\n// ─── host ───────────────────────────────────────────────\n\nexport type SocketHostState = {\n heartbeatMs: number;\n clientRecordLimit: number;\n finOnIdle: boolean;\n authorize: StatewireHostInternal.SocketHostOptions[\"authorize\"];\n clients: Map<string, ClientRec>;\n conns: Set<Conn>;\n pendingOps: WireOp[];\n pendingApplied: Map<string, number[]>;\n pendingCmds: Map<string, StatewireCmd[]>;\n idleWire: boolean;\n finished: StatewireHost.Fin | null;\n disposed: boolean;\n flushScheduled: boolean;\n heartbeatTimer: ReturnType<typeof setInterval> | null;\n stateHost: StatewireHost.StateHost | null;\n commandsHost: CommandsHost | null;\n current: Statewire<unknown> | null;\n post: () => void;\n connect: (\n clientId: string,\n socket: StatewireHostInternal.Socket,\n ) => StatewireHostInternal.SocketConnection | null;\n finish: (fin: StatewireHost.Fin) => void;\n stream: (request: Request) => Promise<Response>;\n frames: (request: Request) => Promise<Response>;\n};\n\nconst scheduleFlush = (h: SocketHostState) => {\n if (h.flushScheduled || h.disposed) return;\n h.flushScheduled = true;\n h.post();\n};\n\nconst recordOp = (\n h: SocketHostState,\n op: {\n op: string;\n path?: StatewirePath;\n value?: unknown;\n },\n) => {\n if (op.op === \"replace\" || op.op === \"add\") {\n const { value, meta } = encodeValue(op.value);\n h.pendingOps.push({ ...op, value, ...(meta !== undefined && { meta }) });\n } else {\n h.pendingOps.push(op);\n }\n scheduleFlush(h);\n};\n\nconst attach = (h: SocketHostState, next: Statewire<unknown>) => {\n if (next === h.current) return;\n h.current = next;\n const nextState =\n typeof next.state === \"object\" && next.state !== null\n ? getStateHost(next.state)\n : undefined;\n const nextCommands = getCommandsHost(next.commands);\n if (!nextState || !nextCommands?.submit) {\n throw new Error(\n \"StatewireSocketHost requires a statewire/host transport (useStatewireState with object state, useStatewireCommands)\",\n );\n }\n if (nextState !== h.stateHost) {\n h.stateHost?.setOnOp(null);\n h.stateHost = nextState;\n h.stateHost.setOnOp((op) => recordOp(h, op));\n }\n h.commandsHost = nextCommands;\n};\n\nexport const closeConn = (\n h: SocketHostState,\n conn: Conn,\n code?: number,\n reason?: string,\n) => {\n if (!conn.open) return;\n conn.open = false;\n h.conns.delete(conn);\n try {\n conn.socket.close(code, reason);\n } catch {\n /* peer already gone */\n }\n if (h.conns.size === 0 && h.heartbeatTimer !== null) {\n clearInterval(h.heartbeatTimer);\n h.heartbeatTimer = null;\n }\n};\n\nexport const sendTo = (h: SocketHostState, conn: Conn, data: string) => {\n if (!conn.open) return;\n conn.lastSentAt = Date.now();\n try {\n conn.socket.send(data);\n } catch {\n closeConn(h, conn);\n }\n};\n\nconst ensureHeartbeat = (h: SocketHostState) => {\n if (h.heartbeatTimer !== null || h.heartbeatMs <= 0) return;\n h.heartbeatTimer = setInterval(() => {\n const now = Date.now();\n for (const conn of [...h.conns]) {\n if (now - conn.lastSentAt >= h.heartbeatMs) sendTo(h, conn, \"{}\");\n }\n }, h.heartbeatMs);\n (h.heartbeatTimer as unknown as { unref?: () => void }).unref?.();\n};\n\nconst setHeartbeatMs = (h: SocketHostState, ms: number) => {\n if (ms === h.heartbeatMs) return;\n h.heartbeatMs = ms;\n if (h.heartbeatTimer !== null) {\n clearInterval(h.heartbeatTimer);\n h.heartbeatTimer = null;\n ensureHeartbeat(h);\n }\n};\n\nconst idleLevel = (h: SocketHostState): boolean => {\n for (const rec of h.clients.values()) {\n if (rec.inflight.size > 0) return false;\n }\n return true;\n};\n\nexport const flush = (h: SocketHostState, fin?: StatewireHost.Fin) => {\n flushTapSync(() => {});\n h.stateHost?.takeChanged();\n for (const rec of h.clients.values()) {\n for (const adm of rec.inflight.values()) {\n if (adm.applied && !adm.settled && !adm.appliedSent) {\n adm.appliedSent = true;\n queueApplied(h, rec.id, adm.seq);\n }\n }\n }\n const level = idleLevel(h);\n const edge = level !== h.idleWire;\n if (\n h.pendingOps.length === 0 &&\n h.pendingApplied.size === 0 &&\n h.pendingCmds.size === 0 &&\n fin === undefined &&\n !edge\n ) {\n return;\n }\n h.idleWire = level;\n if (fin === undefined && edge && level && h.finOnIdle) {\n fin = { reason: \"idle\" };\n }\n const ops = h.pendingOps;\n const applied = h.pendingApplied;\n const cmds = h.pendingCmds;\n h.pendingOps = [];\n h.pendingApplied = new Map();\n h.pendingCmds = new Map();\n // Applied entries anchor to their effects: piggybacked on the ops packet\n // when one is flushing, standalone otherwise. Terminal verdicts ride their\n // own packet.\n for (const conn of [...h.conns]) {\n const appliedEntries: StatewireCmd[] = (\n applied.get(conn.clientId) ?? []\n ).map((seq) => ({ seq, type: \"applied\" }));\n if (ops.length > 0) {\n const packet: StatewireEnvelope = {\n ops,\n ...(appliedEntries.length > 0 && { cmd: appliedEntries }),\n ...(edge && { idle: level }),\n };\n sendTo(h, conn, JSON.stringify(packet));\n } else if (appliedEntries.length > 0) {\n sendTo(h, conn, JSON.stringify({ cmd: appliedEntries }));\n }\n const verdicts = cmds.get(conn.clientId) ?? [];\n if (verdicts.length > 0) {\n sendTo(h, conn, JSON.stringify({ cmd: verdicts }));\n }\n if (edge && ops.length === 0) {\n sendTo(h, conn, JSON.stringify({ idle: level }));\n }\n if (fin !== undefined) {\n sendTo(h, conn, JSON.stringify({ fin }));\n closeConn(h, conn);\n }\n }\n};\n\nconst queueApplied = (h: SocketHostState, clientId: string, seq: number) => {\n const list = h.pendingApplied.get(clientId);\n if (list) list.push(seq);\n else h.pendingApplied.set(clientId, [seq]);\n scheduleFlush(h);\n};\n\nconst queueCmd = (h: SocketHostState, clientId: string, cmd: StatewireCmd) => {\n const list = h.pendingCmds.get(clientId);\n if (list) list.push(cmd);\n else h.pendingCmds.set(clientId, [cmd]);\n scheduleFlush(h);\n};\n\nconst retain = (rec: ClientRec, cmd: StatewireCmd) => {\n const now = Date.now();\n rec.results.set(cmd.seq, { ts: now, cmd });\n const newest = Math.max(...rec.results.keys());\n for (const [seq, entry] of rec.results) {\n if (seq !== newest && now - entry.ts > RESULT_TTL_MS) {\n rec.results.delete(seq);\n }\n }\n while (rec.results.size > RESULT_LIMIT) {\n rec.results.delete(Math.min(...rec.results.keys()));\n }\n};\n\n/** Cmd-lane watermark: the last statement admitted, settled or not. */\nconst admittedThrough = (rec: ClientRec): number =>\n Math.max(rec.lastSeq, ...rec.inflight.keys());\n\n// A re-asked seq never re-runs: the stored verdict re-emits, an applied\n// inflight run re-answers applied; one not yet applied answers nothing (its\n// answers ride the stream when ready), an evicted verdict answers expired.\nconst reemit = (h: SocketHostState, rec: ClientRec, seq: number) => {\n const cached = rec.results.get(seq);\n if (cached) {\n const newest = Math.max(...rec.results.keys());\n if (seq === newest || Date.now() - cached.ts <= RESULT_TTL_MS) {\n queueCmd(h, rec.id, cached.cmd);\n return;\n }\n rec.results.delete(seq);\n }\n const adm = rec.inflight.get(seq);\n if (adm) {\n if (adm.applied) queueApplied(h, rec.id, seq);\n return;\n }\n queueCmd(h, rec.id, { seq, type: \"expired\" });\n};\n\nconst settleCmd = (\n h: SocketHostState,\n rec: ClientRec,\n adm: Admission,\n cmd: StatewireCmd,\n) => {\n if (adm.settled) return;\n adm.settled = true;\n rec.inflight.delete(adm.seq);\n retain(rec, cmd);\n rec.lastSeq = Math.max(rec.lastSeq, adm.seq);\n adm.applied = true;\n queueCmd(h, rec.id, cmd);\n};\n\nconst settleWire = (\n h: SocketHostState,\n rec: ClientRec,\n adm: Admission,\n outcome: CommandsOutcome,\n) => settleCmd(h, rec, adm, cmdOf(adm, outcome));\n\nconst callerOf = (\n h: SocketHostState,\n rec: ClientRec,\n): StatewireHost.Caller => ({\n clientId: rec.id,\n get context() {\n return rec.context;\n },\n get isConnected() {\n if (h.clients.get(rec.id) !== rec) return false;\n for (const conn of h.conns) {\n if (conn.clientId === rec.id && conn.open) return true;\n }\n return false;\n },\n});\n\nconst rejectStatement = (\n h: SocketHostState,\n rec: ClientRec,\n adm: Admission,\n message: string,\n) =>\n settleCmd(h, rec, adm, {\n seq: adm.seq,\n type: \"rejected\",\n code: \"invalid-params\",\n message,\n });\n\nconst admitCmd = (\n h: SocketHostState,\n rec: ClientRec,\n statement: CmdStatement,\n) => {\n const adm: Admission = {\n seq: statement.seq,\n method: statement.method,\n applied: false,\n appliedSent: false,\n settled: false,\n };\n rec.inflight.set(statement.seq, adm);\n if (!Array.isArray(statement.params)) {\n rejectStatement(h, rec, adm, \"params must be an array\");\n return;\n }\n let params = statement.params;\n if (statement.meta !== undefined) {\n try {\n params = reviveValue(params, statement.meta, {\n rejectUnknown: true,\n }) as unknown[];\n } catch (error) {\n rejectStatement(\n h,\n rec,\n adm,\n `invalid params: ${(error as Error).message}`,\n );\n return;\n }\n }\n if (statement.method === \"statewire/commands\") {\n if (params.length > 0) {\n rejectStatement(h, rec, adm, \"statewire/commands takes no params\");\n return;\n }\n const names = [\n ...(h.commandsHost?.methods?.() ?? []),\n \"statewire/commands\",\n ].sort();\n settleCmd(h, rec, adm, { seq: adm.seq, type: \"result\", payload: names });\n return;\n }\n h.commandsHost!.submit!({\n method: statement.method,\n params,\n clientId: rec.id,\n caller: callerOf(h, rec),\n onApplied: () => {\n if (adm.settled || adm.applied) return;\n adm.applied = true;\n rec.lastSeq = Math.max(rec.lastSeq, adm.seq);\n scheduleFlush(h);\n },\n onSettle: (outcome) => settleWire(h, rec, adm, outcome),\n }).catch((error: unknown) => {\n if (!adm.settled) settleWire(h, rec, adm, { type: \"rejected\", error });\n });\n};\n\n// One admission law, both lanes: absorbed statements answer from the record,\n// then the new suffix is admitted whole or the frame is refused whole via a\n// {syn} stating both watermarks, nothing consumed. A gap is never a close.\nexport type FrameAdmission =\n | { type: \"ok\" }\n | { type: \"refused\"; syn: { syn: { seq: number; ctxSeq: number } } };\n\nexport const admitFrame = (\n h: SocketHostState,\n rec: ClientRec,\n frame: ParsedFrame,\n): FrameAdmission => {\n rec.touched = Date.now();\n const through = admittedThrough(rec);\n for (const statement of frame.cmd) {\n if (statement.seq <= through) reemit(h, rec, statement.seq);\n }\n const ctxNew = frame.ctx.filter((s) => s.seq > rec.ctxSeq);\n const cmdNew = frame.cmd.filter((s) => s.seq > through);\n if (\n (ctxNew.length > 0 && ctxNew[0]!.seq !== rec.ctxSeq + 1) ||\n (cmdNew.length > 0 && cmdNew[0]!.seq !== through + 1)\n ) {\n return {\n type: \"refused\",\n syn: { syn: { seq: through, ctxSeq: rec.ctxSeq } },\n };\n }\n for (const statement of ctxNew) {\n rec.context = statement.value;\n rec.ctxSeq = statement.seq;\n }\n for (const statement of cmdNew) admitCmd(h, rec, statement);\n if (cmdNew.length > 0) {\n // Memory host: admitted means retained — dur rides the admitting flush.\n queueCmd(h, rec.id, { seq: cmdNew.at(-1)!.seq, dur: true });\n }\n scheduleFlush(h);\n return { type: \"ok\" };\n};\n\nconst message = (h: SocketHostState, conn: Conn, data: string) => {\n if (!conn.open || h.disposed || h.finished !== null) return;\n const first = !conn.sawFrame;\n conn.sawFrame = true;\n let frame: ParsedFrame;\n try {\n frame = parseFrame(data, first);\n } catch (error) {\n const reason = violationReason(error);\n if (reason === null) throw error;\n closeConn(h, conn, 1008, reason);\n return;\n }\n if (frame.ctx.length === 0 && frame.cmd.length === 0) return;\n const rec = h.clients.get(conn.clientId)!;\n const admission = admitFrame(h, rec, frame);\n if (admission.type === \"refused\") {\n sendTo(h, conn, JSON.stringify(admission.syn));\n }\n};\n\nconst gcClients = (h: SocketHostState) => {\n let excess = h.clients.size - h.clientRecordLimit;\n if (excess <= 0) return;\n const live = new Set([...h.conns].map((conn) => conn.clientId));\n const oldest = [...h.clients.values()].sort((a, b) => a.touched - b.touched);\n for (const rec of oldest) {\n if (excess <= 0) return;\n if (live.has(rec.id) || rec.inflight.size > 0) continue;\n h.clients.delete(rec.id);\n excess -= 1;\n }\n};\n\nexport type Registration = {\n rec: ClientRec;\n conn: Conn;\n connection: StatewireHostInternal.SocketConnection;\n};\n\nexport const register = (\n h: SocketHostState,\n clientId: string,\n socket: StatewireHostInternal.Socket,\n): Registration | null => {\n const refuse = (code: number, reason: string) => {\n try {\n socket.close(code, reason);\n } catch {\n /* peer already gone */\n }\n return null;\n };\n if (h.disposed) return refuse(1001, \"disposed\");\n if (!CLIENT_ID_RE.test(clientId)) return refuse(1008, \"invalid client id\");\n flush(h);\n if (h.finished !== null) {\n try {\n socket.send(JSON.stringify({ fin: h.finished }));\n } catch {\n /* peer already gone */\n }\n refuse(1000, \"finished\");\n return null;\n }\n const known = h.clients.has(clientId);\n const rec = known\n ? h.clients.get(clientId)!\n : (() => {\n const created: ClientRec = {\n id: clientId,\n lastSeq: 0,\n ctxSeq: 0,\n touched: Date.now(),\n context: null,\n results: new Map(),\n inflight: new Map(),\n };\n h.clients.set(clientId, created);\n return created;\n })();\n rec.touched = Date.now();\n const conn: Conn = {\n clientId,\n socket,\n open: true,\n sawFrame: false,\n lastSentAt: 0,\n lease: null,\n };\n h.conns.add(conn);\n gcClients(h);\n ensureHeartbeat(h);\n const { value, meta } = encodeValue(h.stateHost!.snapshot());\n const hello: StatewireEnvelope = {\n ops: [\n {\n op: \"replace\",\n path: [],\n value,\n ...(meta !== undefined && { meta }),\n },\n ],\n syn: {\n seq: admittedThrough(rec),\n ctxSeq: rec.ctxSeq,\n ...(h.idleWire && { idle: true }),\n },\n };\n sendTo(h, conn, JSON.stringify(hello));\n const connection: StatewireHostInternal.SocketConnection = {\n clientId,\n message: (data) => message(h, conn, data),\n close: () => closeConn(h, conn),\n };\n return { rec, conn, connection };\n};\n\nconst connect = (\n h: SocketHostState,\n clientId: string,\n socket: StatewireHostInternal.Socket,\n): StatewireHostInternal.SocketConnection | null => {\n const registration = register(h, clientId, socket);\n return registration?.connection ?? null;\n};\n\nconst finish = (h: SocketHostState, fin: StatewireHost.Fin) => {\n if (h.finished !== null || h.disposed) return;\n h.finished = fin;\n flush(h, fin);\n};\n\nconst resume = (h: SocketHostState) => {\n h.disposed = false;\n h.stateHost?.setOnOp((op) => recordOp(h, op));\n};\n\nconst suspend = (h: SocketHostState) => {\n h.disposed = true;\n if (h.heartbeatTimer !== null) {\n clearInterval(h.heartbeatTimer);\n h.heartbeatTimer = null;\n }\n h.stateHost?.setOnOp(null);\n};\n\nconst useSocketHost = (\n transport: ResourceElement<Statewire>,\n options?: StatewireHostInternal.SocketHostOptions,\n): Pick<\n StatewireHostInternal.SocketHost,\n \"connect\" | \"finish\" | \"stream\" | \"frames\"\n> => {\n const [h] = useState((): SocketHostState => {\n const host: SocketHostState = {\n heartbeatMs: 15_000,\n clientRecordLimit: CLIENT_RECORD_LIMIT,\n finOnIdle: false,\n authorize: undefined,\n clients: new Map(),\n conns: new Set(),\n pendingOps: [],\n pendingApplied: new Map(),\n pendingCmds: new Map(),\n idleWire: true,\n finished: null,\n disposed: false,\n flushScheduled: false,\n heartbeatTimer: null,\n stateHost: null,\n commandsHost: null,\n current: null,\n post: createMacrotaskPoster(() => {\n host.flushScheduled = false;\n flush(host);\n }),\n connect: (clientId, socket) => connect(host, clientId, socket),\n finish: (fin) => finish(host, fin),\n stream: (request) => serveStream(host, request),\n frames: (request) => serveFrames(host, request),\n };\n return host;\n });\n setHeartbeatMs(h, options?.heartbeatIntervalMs ?? 15_000);\n h.clientRecordLimit = options?.clientRecordLimit ?? CLIENT_RECORD_LIMIT;\n h.finOnIdle = options?.finOnIdle ?? false;\n h.authorize = options?.authorize;\n const value = useResource(transport) as Statewire<unknown>;\n attach(h, value);\n useEffect(() => {\n attach(h, value);\n });\n useEffect(() => {\n resume(h);\n return () => suspend(h);\n }, [h]);\n return h;\n};\n\n/**\n * Transport-agnostic WS binding over a statewire/host transport:\n * feed it sockets (anything with `send`/`close`) and raw text frames, and it\n * speaks the Statewire packet protocol — snapshot-first hello with `syn`,\n * statement-lane client frames under one admission law, `{cmd}` answer\n * arrays fanned out to every attach of a client id, idle edges, and `fin` on\n * finish.\n */\nexport const StatewireSocketHost = (\n transport: ResourceElement<Statewire>,\n options?: StatewireHostInternal.SocketHostOptions,\n): StatewireHostInternal.SocketHost => {\n const SocketHostRoot = () => useSocketHost(transport, options);\n const root = createTapRoot(SocketHostRoot);\n let disposed = false;\n return {\n connect: (clientId, socket) =>\n flushTapSync(() => root.getValue().connect(clientId, socket)),\n stream: (request) => flushTapSync(() => root.getValue().stream(request)),\n frames: (request) => flushTapSync(() => root.getValue().frames(request)),\n finish: (fin) => flushTapSync(() => root.getValue().finish(fin)),\n dispose: () => {\n if (disposed) return;\n disposed = true;\n flushTapSync(() => root.getValue().finish({ reason: \"evicted\" }));\n root.unmount();\n },\n };\n};\n"],"mappings":";;;;;;;;AAgBA,MAAayB,eAAe;AAC5B,MAAMC,gBAAgB;AACtB,MAAMC,eAAe;AACrB,MAAMC,sBAAsB;AAsC5B,MAAMgC,aAAaC,WAA0B;CAC3C,MAAMC,OAAOC,OAAO,IAAIC,MAAMH,MAAM,GAAG,EAAEI,MAAM,qBAAqB,CAAC;AACvE;AAEA,MAAMC,mBAAmBC,UACvBA,iBAAiBH,SAASG,MAAMF,SAAS,uBACrCE,MAAMC,UACN;AAgBN,MAAMO,iBAAiB3C,UACrB,OAAOA,UAAU,YAAYA,UAAU,QAAQ,CAAC4C,MAAMC,QAAQ7C,KAAK;AAErE,MAAM8C,aAAa9C,UAA8C;CAC/D,IAAI,CAAC4C,MAAMC,QAAQ7C,KAAK,GAAG,OAAO4B,UAAU,iBAAiB;CAC7D,IAAI5B,MAAM+C,WAAW,GAAG,OAAOnB,UAAU,YAAY;CACrD,MAAMoB,aAAwC,CAAA;CAC9C,IAAIC,OAAsB;CAC1B,KAAK,MAAMC,aAAalD,OAAO;EAC7B,IAAI,CAAC2C,cAAcO,SAAS,GAAG,OAAOtB,UAAU,qBAAqB;EACrE,MAAMzB,MAAM+C,UAAU;EACtB,IAAI,OAAO/C,QAAQ,YAAY,CAACgD,OAAOC,UAAUjD,GAAG,KAAKA,MAAM,GAC7D,OAAOyB,UAAU,qBAAqB;EAExC,IAAIqB,SAAS,QAAQ9C,QAAQ8C,OAAO,GAAG,OAAOrB,UAAU,iBAAiB;EACzEqB,OAAO9C;EACP6C,WAAWK,KAAKH,SAAS;CAC3B;CACA,OAAOF;AACT;;AAGA,MAAMM,gBAAgBC,QAA0C;CAC9D,IAAI,CAACX,MAAMC,QAAQU,GAAG,KAAKA,IAAIR,WAAW,GACxC,MAAM,IAAIf,MAAM,mCAAmC;CAErD,MAAMlC,KAAKyD,IAAI;CACf,IACE,CAACZ,cAAc7C,EAAE,KACjBA,GAAG,UAAU,aACb,CAAC8C,MAAMC,QAAQ/C,GAAG,OAAO,KACzBA,GAAG,OAAO,CAACiD,WAAW,GAEtB,MAAM,IAAIf,MAAM,mCAAmC;CAErD,MAAMhC,QACJF,GAAG,YAAY0D,KAAAA,IACXzE,YAAYe,GAAG,UAAUA,GAAG,SAAS,EAAE2D,eAAe,KAAK,CAAC,IAC5D3D,GAAG;CACT,IAAI,CAAC6C,cAAc3C,KAAK,GACtB,MAAM,IAAIgC,MAAM,iCAAiC;CAEnD,OAAOhC;AACT;AAEA,MAAa0D,mBACXC,OACAC,UACgB;CAChB,IAAI,CAACjB,cAAcgB,KAAK,GAAG,OAAO/B,UAAU,iBAAiB;CAC7D,MAAMiC,OAAO/B,OAAO+B,KAAKF,KAAK;CAC9B,IAAIE,KAAKd,WAAW,GAAG,OAAOnB,UAAU,iBAAiB;CACzD,MAAMkC,UAAUD,KACbE,QAAQC,QAAQA,QAAQ,aAAaA,QAAQ,SAASA,QAAQ,KAAK,CAAC,CACpEC,KAAK;CACR,IAAIH,QAAQf,SAAS,GACnB,OAAOnB,UAAU,uBAAuBkC,QAAQ,GAAE,EAAG;CACvD,IAAIrB,UAAyC;CAC7C,IAAIkB,MAAM,eAAeH,KAAAA,GAAW;EAClC,IAAI,CAACI,OAAO,OAAOhC,UAAU,qBAAqB;EAClD,MAAMsC,MAAMP,MAAM;EAClB,IACE,CAAChB,cAAcuB,GAAG,KAClBpC,OAAOqC,OAAOD,GAAG,CAAC,CAACE,MAAMpE,UAAU,OAAOA,UAAU,QAAQ,GAE5D,OAAO4B,UAAU,mBAAmB;EAEtCa,UAAUyB;CACZ;CACA,MAAMxB,MAAsB,CAAA;CAC5B,IAAIiB,MAAM,WAAWH,KAAAA,GACnB,KAAK,MAAMN,aAAaJ,UAAUa,MAAM,MAAM,GAC5C,IAAI;EACFjB,IAAIW,KAAK;GACPlD,KAAK+C,UAAU;GACflD,OAAOsD,aAAaJ,UAAU,MAAM;EACtC,CAAC;CACH,QAAQ;EACN,OAAOtB,UAAU,iBAAiB;CACpC;CAGJ,MAAMV,MAAsB,CAAA;CAC5B,IAAIyC,MAAM,WAAWH,KAAAA,GACnB,KAAK,MAAMN,aAAaJ,UAAUa,MAAM,MAAM,GAAG;EAC/C,MAAMvD,SAAS8C,UAAU;EACzB,IAAI,OAAO9C,WAAW,YAAY,EAAE,YAAY8C,YAC9C,OAAOtB,UAAU,qBAAqB;EAExCV,IAAImC,KAAK;GACPlD,KAAK+C,UAAU;GACf9C;GACAmC,QAAQW,UAAU;GAClB,GAAIA,UAAU,YAAYM,KAAAA,KAAa,EAAEvD,MAAMiD,UAAU,QAAQ;EACnE,CAAC;CACH;CAEF,OAAO;EAAET;EAASC;EAAKxB;CAAI;AAC7B;AAEA,MAAamD,cAAcH,KAAaN,UAAgC;CACtE,IAAID;CACJ,IAAI;EACFA,QAAQW,KAAKC,MAAML,GAAG;CACxB,QAAQ;EACN,OAAOtC,UAAU,iBAAiB;CACpC;CACA,OAAO8B,gBAAgBC,OAAOC,KAAK;AACrC;AAIA,MAAMY,iBACJC,YACuD;CACvD,IAAIA,YAAYjB,KAAAA,GAAW,OAAO,CAAC;CACnC,MAAM,EAAExD,OAAOC,SAASnB,YAAY2F,OAAO;CAC3C,OAAO;EAAEA,SAASzE;EAAO,GAAIC,SAASuD,KAAAA,KAAa,EAAEvD,KAAK;CAAG;AAC/D;AAEA,MAAMyE,SAASC,KAAgBC,YAA2C;CACxE,IAAIA,QAAQC,SAAS,YACnB,OAAO;EAAE1E,KAAKwE,IAAIxE;EAAK0E,MAAM;EAAU,GAAGL,cAAcI,QAAQH,OAAO;CAAE;CAE3E,MAAMK,UACJF,QAAQzC,iBAAiBzD,qBAAqBkG,QAAQzC,MAAM2C,UAAU;CACxE,QAAQA,SAASC,MAAjB;EACE,KAAK,UACH,OAAO;GACL5E,KAAKwE,IAAIxE;GACT0E,MAAM;GACN,GAAIC,QAAQ1C,YAAYoB,KAAAA,KAAa,EAAEpB,SAAS0C,QAAQ1C,QAAQ;EAClE;EACF,KAAK;GACH,IAAI0C,QAAQE,SAASxB,KAAAA,GAAW;IAC9B,MAAMpB,UACJ0C,QAAQE,SAAS,oBACb,oBAAoBL,IAAIvE,OAAM,KAC9B0E,QAAQ1C;IACd,OAAO;KACLjC,KAAKwE,IAAIxE;KACT0E,MAAM;KACNG,MAAMF,QAAQE;KACd,GAAI5C,YAAYoB,KAAAA,KAAa,EAAEpB,QAAQ;IACzC;GACF;GACA,OAAO;IACLjC,KAAKwE,IAAIxE;IACT0E,MAAM;IACN,GAAIC,QAAQ1C,YAAYoB,KAAAA,KAAa,EAAEpB,SAAS0C,QAAQ1C,QAAQ;IAChE,GAAGoC,cAAcM,QAAQL,OAAO;GAClC;EAEF,SACE,OAAO;GACLtE,KAAKwE,IAAIxE;GACT0E,MAAM;GACNzC,SACEwC,QAAQzC,iBAAiBH,QACrB4C,QAAQzC,MAAMC,UACd6C,OAAOL,QAAQzC,KAAK;EAC5B;CACJ;AACF;AAgCA,MAAMgF,iBAAiBC,MAAuB;CAC5C,IAAIA,EAAElB,kBAAkBkB,EAAEnB,UAAU;CACpCmB,EAAElB,iBAAiB;CACnBkB,EAAEV,KAAK;AACT;AAEA,MAAMW,YACJD,GACAtH,OAKG;CACH,IAAIA,GAAGA,OAAO,aAAaA,GAAGA,OAAO,OAAO;EAC1C,MAAM,EAAEE,OAAOC,SAASnB,YAAYgB,GAAGE,KAAK;EAC5CoH,EAAEzB,WAAWtC,KAAK;GAAE,GAAGvD;GAAIE;GAAO,GAAIC,SAASuD,KAAAA,KAAa,EAAEvD,KAAK;EAAG,CAAC;CACzE,OACEmH,EAAEzB,WAAWtC,KAAKvD,EAAE;CAEtBqH,cAAcC,CAAC;AACjB;AAEA,MAAME,UAAUF,GAAoBG,SAA6B;CAC/D,IAAIA,SAASH,EAAEX,SAAS;CACxBW,EAAEX,UAAUc;CACZ,MAAMC,YACJ,OAAOD,KAAKE,UAAU,YAAYF,KAAKE,UAAU,OAC7ClJ,aAAagJ,KAAKE,KAAK,IACvBjE,KAAAA;CACN,MAAMkE,eAAepJ,gBAAgBiJ,KAAKI,QAAQ;CAClD,IAAI,CAACH,aAAa,CAACE,cAAcE,QAC/B,MAAM,IAAI5F,MACR,qHACF;CAEF,IAAIwF,cAAcJ,EAAEd,WAAW;EAC7Bc,EAAEd,WAAWuB,QAAQ,IAAI;EACzBT,EAAEd,YAAYkB;EACdJ,EAAEd,UAAUuB,SAAS/H,OAAOuH,SAASD,GAAGtH,EAAE,CAAC;CAC7C;CACAsH,EAAEZ,eAAekB;AACnB;AAEA,MAAaI,aACXV,GACAW,MACA/C,MACAnD,WACG;CACH,IAAI,CAACkG,KAAKvG,MAAM;CAChBuG,KAAKvG,OAAO;CACZ4F,EAAE3B,MAAMuC,OAAOD,IAAI;CACnB,IAAI;EACFA,KAAKzG,OAAO2G,MAAMjD,MAAMnD,MAAM;CAChC,QAAQ,CACN;CAEF,IAAIuF,EAAE3B,MAAMyC,SAAS,KAAKd,EAAEjB,mBAAmB,MAAM;EACnDgC,cAAcf,EAAEjB,cAAc;EAC9BiB,EAAEjB,iBAAiB;CACrB;AACF;AAEA,MAAaiC,UAAUhB,GAAoBW,MAAYM,SAAiB;CACtE,IAAI,CAACN,KAAKvG,MAAM;CAChBuG,KAAKrG,aAAa4G,KAAKC,IAAI;CAC3B,IAAI;EACFR,KAAKzG,OAAOkH,KAAKH,IAAI;CACvB,QAAQ;EACNP,UAAUV,GAAGW,IAAI;CACnB;AACF;AAEA,MAAMU,mBAAmBrB,MAAuB;CAC9C,IAAIA,EAAEjB,mBAAmB,QAAQiB,EAAEjC,eAAe,GAAG;CACrDiC,EAAEjB,iBAAiBE,kBAAkB;EACnC,MAAMkC,MAAMD,KAAKC,IAAI;EACrB,KAAK,MAAMR,QAAQ,CAAC,GAAGX,EAAE3B,KAAK,GAC5B,IAAI8C,MAAMR,KAAKrG,cAAc0F,EAAEjC,aAAaiD,OAAOhB,GAAGW,MAAM,IAAI;CAEpE,GAAGX,EAAEjC,WAAW;CAChB,EAAGgB,eAAqDuC,QAAQ;AAClE;AAEA,MAAMC,kBAAkBvB,GAAoBwB,OAAe;CACzD,IAAIA,OAAOxB,EAAEjC,aAAa;CAC1BiC,EAAEjC,cAAcyD;CAChB,IAAIxB,EAAEjB,mBAAmB,MAAM;EAC7BgC,cAAcf,EAAEjB,cAAc;EAC9BiB,EAAEjB,iBAAiB;EACnBsC,gBAAgBrB,CAAC;CACnB;AACF;AAEA,MAAMyB,aAAazB,MAAgC;CACjD,KAAK,MAAM0B,OAAO1B,EAAE5B,QAAQrB,OAAO,GACjC,IAAI2E,IAAI3H,SAAS+G,OAAO,GAAG,OAAO;CAEpC,OAAO;AACT;AAEA,MAAaa,SAAS3B,GAAoBN,QAA4B;CACpE3I,mBAAmB,CAAC,CAAC;CACrBiJ,EAAEd,WAAW0C,YAAY;CACzB,KAAK,MAAMF,OAAO1B,EAAE5B,QAAQrB,OAAO,GACjC,KAAK,MAAMQ,OAAOmE,IAAI3H,SAASgD,OAAO,GACpC,IAAIQ,IAAItE,WAAW,CAACsE,IAAIpE,WAAW,CAACoE,IAAIrE,aAAa;EACnDqE,IAAIrE,cAAc;EAClB2I,aAAa7B,GAAG0B,IAAIrI,IAAIkE,IAAIxE,GAAG;CACjC;CAGJ,MAAM+I,QAAQL,UAAUzB,CAAC;CACzB,MAAM+B,OAAOD,UAAU9B,EAAEtB;CACzB,IACEsB,EAAEzB,WAAW5C,WAAW,KACxBqE,EAAExB,eAAesC,SAAS,KAC1Bd,EAAEvB,YAAYqC,SAAS,KACvBpB,QAAQtD,KAAAA,KACR,CAAC2F,MAED;CAEF/B,EAAEtB,WAAWoD;CACb,IAAIpC,QAAQtD,KAAAA,KAAa2F,QAAQD,SAAS9B,EAAE/B,WAC1CyB,MAAM,EAAEjF,QAAQ,OAAO;CAEzB,MAAM0B,MAAM6D,EAAEzB;CACd,MAAMtF,UAAU+G,EAAExB;CAClB,MAAMwD,OAAOhC,EAAEvB;CACfuB,EAAEzB,aAAa,CAAA;CACfyB,EAAExB,iCAAiB,IAAI5E,IAAI;CAC3BoG,EAAEvB,8BAAc,IAAI7E,IAAI;CAIxB,KAAK,MAAM+G,QAAQ,CAAC,GAAGX,EAAE3B,KAAK,GAAG;EAC/B,MAAM4D,kBACJhJ,QAAQiJ,IAAIvB,KAAK1G,QAAQ,KAAK,CAAA,EAAA,CAC9BkI,KAAKpJ,SAAS;GAAEA;GAAK0E,MAAM;EAAU,EAAE;EACzC,IAAItB,IAAIR,SAAS,GAAG;GAClB,MAAMyG,SAA4B;IAChCjG;IACA,GAAI8F,eAAetG,SAAS,KAAK,EAAE7B,KAAKmI,eAAe;IACvD,GAAIF,QAAQ,EAAEM,MAAMP,MAAM;GAC5B;GACAd,OAAOhB,GAAGW,MAAMzD,KAAKoF,UAAUF,MAAM,CAAC;EACxC,OAAO,IAAIH,eAAetG,SAAS,GACjCqF,OAAOhB,GAAGW,MAAMzD,KAAKoF,UAAU,EAAExI,KAAKmI,eAAe,CAAC,CAAC;EAEzD,MAAMM,WAAWP,KAAKE,IAAIvB,KAAK1G,QAAQ,KAAK,CAAA;EAC5C,IAAIsI,SAAS5G,SAAS,GACpBqF,OAAOhB,GAAGW,MAAMzD,KAAKoF,UAAU,EAAExI,KAAKyI,SAAS,CAAC,CAAC;EAEnD,IAAIR,QAAQ5F,IAAIR,WAAW,GACzBqF,OAAOhB,GAAGW,MAAMzD,KAAKoF,UAAU,EAAED,MAAMP,MAAM,CAAC,CAAC;EAEjD,IAAIpC,QAAQtD,KAAAA,GAAW;GACrB4E,OAAOhB,GAAGW,MAAMzD,KAAKoF,UAAU,EAAE5C,IAAI,CAAC,CAAC;GACvCgB,UAAUV,GAAGW,IAAI;EACnB;CACF;AACF;AAEA,MAAMkB,gBAAgB7B,GAAoB/F,UAAkBlB,QAAgB;CAC1E,MAAMyJ,OAAOxC,EAAExB,eAAe0D,IAAIjI,QAAQ;CAC1C,IAAIuI,MAAMA,KAAKvG,KAAKlD,GAAG;MAClBiH,EAAExB,eAAeiE,IAAIxI,UAAU,CAAClB,GAAG,CAAC;CACzCgH,cAAcC,CAAC;AACjB;AAEA,MAAM0C,YAAY1C,GAAoB/F,UAAkBH,QAAsB;CAC5E,MAAM0I,OAAOxC,EAAEvB,YAAYyD,IAAIjI,QAAQ;CACvC,IAAIuI,MAAMA,KAAKvG,KAAKnC,GAAG;MAClBkG,EAAEvB,YAAYgE,IAAIxI,UAAU,CAACH,GAAG,CAAC;CACtCiG,cAAcC,CAAC;AACjB;AAEA,MAAM2C,UAAUjB,KAAgB5H,QAAsB;CACpD,MAAMqH,MAAMD,KAAKC,IAAI;CACrBO,IAAI/H,QAAQ8I,IAAI3I,IAAIf,KAAK;EAAEc,IAAIsH;EAAKrH;CAAI,CAAC;CACzC,MAAM8I,SAASC,KAAKC,IAAI,GAAGpB,IAAI/H,QAAQ8C,KAAK,CAAC;CAC7C,KAAK,MAAM,CAAC1D,KAAKgK,UAAUrB,IAAI/H,SAC7B,IAAIZ,QAAQ6J,UAAUzB,MAAM4B,MAAMlJ,KAAKvB,eACrCoJ,IAAI/H,QAAQiH,OAAO7H,GAAG;CAG1B,OAAO2I,IAAI/H,QAAQmH,OAAOvI,cACxBmJ,IAAI/H,QAAQiH,OAAOiC,KAAKG,IAAI,GAAGtB,IAAI/H,QAAQ8C,KAAK,CAAC,CAAC;AAEtD;;AAGA,MAAMwG,mBAAmBvB,QACvBmB,KAAKC,IAAIpB,IAAIpI,SAAS,GAAGoI,IAAI3H,SAAS0C,KAAK,CAAC;AAK9C,MAAMyG,UAAUlD,GAAoB0B,KAAgB3I,QAAgB;CAClE,MAAMoK,SAASzB,IAAI/H,QAAQuI,IAAInJ,GAAG;CAClC,IAAIoK,QAAQ;EAEV,IAAIpK,QADW8J,KAAKC,IAAI,GAAGpB,IAAI/H,QAAQ8C,KAAK,CAChCmG,KAAU1B,KAAKC,IAAI,IAAIgC,OAAOtJ,MAAMvB,eAAe;GAC7DoK,SAAS1C,GAAG0B,IAAIrI,IAAI8J,OAAOrJ,GAAG;GAC9B;EACF;EACA4H,IAAI/H,QAAQiH,OAAO7H,GAAG;CACxB;CACA,MAAMwE,MAAMmE,IAAI3H,SAASmI,IAAInJ,GAAG;CAChC,IAAIwE,KAAK;EACP,IAAIA,IAAItE,SAAS4I,aAAa7B,GAAG0B,IAAIrI,IAAIN,GAAG;EAC5C;CACF;CACA2J,SAAS1C,GAAG0B,IAAIrI,IAAI;EAAEN;EAAK0E,MAAM;CAAU,CAAC;AAC9C;AAEA,MAAM2F,aACJpD,GACA0B,KACAnE,KACAzD,QACG;CACH,IAAIyD,IAAIpE,SAAS;CACjBoE,IAAIpE,UAAU;CACduI,IAAI3H,SAAS6G,OAAOrD,IAAIxE,GAAG;CAC3B4J,OAAOjB,KAAK5H,GAAG;CACf4H,IAAIpI,UAAUuJ,KAAKC,IAAIpB,IAAIpI,SAASiE,IAAIxE,GAAG;CAC3CwE,IAAItE,UAAU;CACdyJ,SAAS1C,GAAG0B,IAAIrI,IAAIS,GAAG;AACzB;AAEA,MAAMuJ,cACJrD,GACA0B,KACAnE,KACAC,YACG4F,UAAUpD,GAAG0B,KAAKnE,KAAKD,MAAMC,KAAKC,OAAO,CAAC;AAE/C,MAAM8F,YACJtD,GACA0B,SAC0B;CAC1BzH,UAAUyH,IAAIrI;CACd,IAAII,UAAU;EACZ,OAAOiI,IAAIjI;CACb;CACA,IAAI+J,cAAc;EAChB,IAAIxD,EAAE5B,QAAQ8D,IAAIR,IAAIrI,EAAE,MAAMqI,KAAK,OAAO;EAC1C,KAAK,MAAMf,QAAQX,EAAE3B,OACnB,IAAIsC,KAAK1G,aAAayH,IAAIrI,MAAMsH,KAAKvG,MAAM,OAAO;EAEpD,OAAO;CACT;AACF;AAEA,MAAMqJ,mBACJzD,GACA0B,KACAnE,KACAvC,YAEAoI,UAAUpD,GAAG0B,KAAKnE,KAAK;CACrBxE,KAAKwE,IAAIxE;CACT0E,MAAM;CACNG,MAAM;CACN5C;AACF,CAAC;AAEH,MAAM0I,YACJ1D,GACA0B,KACA5F,cACG;CACH,MAAMyB,MAAiB;EACrBxE,KAAK+C,UAAU/C;EACfC,QAAQ8C,UAAU9C;EAClBC,SAAS;EACTC,aAAa;EACbC,SAAS;CACX;CACAuI,IAAI3H,SAAS0I,IAAI3G,UAAU/C,KAAKwE,GAAG;CACnC,IAAI,CAAC/B,MAAMC,QAAQK,UAAUX,MAAM,GAAG;EACpCsI,gBAAgBzD,GAAG0B,KAAKnE,KAAK,yBAAyB;EACtD;CACF;CACA,IAAIpC,SAASW,UAAUX;CACvB,IAAIW,UAAUjD,SAASuD,KAAAA,GACrB,IAAI;EACFjB,SAASxD,YAAYwD,QAAQW,UAAUjD,MAAM,EAC3CwD,eAAe,KACjB,CAAC;CACH,SAAStB,OAAO;EACd0I,gBACEzD,GACA0B,KACAnE,KACA,mBAAoBxC,MAAgBC,SACtC;EACA;CACF;CAEF,IAAIc,UAAU9C,WAAW,sBAAsB;EAC7C,IAAImC,OAAOQ,SAAS,GAAG;GACrB8H,gBAAgBzD,GAAG0B,KAAKnE,KAAK,oCAAoC;GACjE;EACF;EACA,MAAMoG,QAAQ,CACZ,GAAI3D,EAAEZ,cAAcwE,UAAU,KAAK,CAAA,GACnC,oBAAoB,CACrB,CAAC/G,KAAK;EACPuG,UAAUpD,GAAG0B,KAAKnE,KAAK;GAAExE,KAAKwE,IAAIxE;GAAK0E,MAAM;GAAUJ,SAASsG;EAAM,CAAC;EACvE;CACF;CACA3D,EAAEZ,aAAcoB,OAAQ;EACtBxH,QAAQ8C,UAAU9C;EAClBmC;EACAlB,UAAUyH,IAAIrI;EACdwK,QAAQP,SAAStD,GAAG0B,GAAG;EACvBoC,iBAAiB;GACf,IAAIvG,IAAIpE,WAAWoE,IAAItE,SAAS;GAChCsE,IAAItE,UAAU;GACdyI,IAAIpI,UAAUuJ,KAAKC,IAAIpB,IAAIpI,SAASiE,IAAIxE,GAAG;GAC3CgH,cAAcC,CAAC;EACjB;EACA+D,WAAWvG,YAAY6F,WAAWrD,GAAG0B,KAAKnE,KAAKC,OAAO;CACxD,CAAC,CAAC,CAACwG,OAAOjJ,UAAmB;EAC3B,IAAI,CAACwC,IAAIpE,SAASkK,WAAWrD,GAAG0B,KAAKnE,KAAK;GAAEE,MAAM;GAAY1C;EAAM,CAAC;CACvE,CAAC;AACH;AASA,MAAaoJ,cACXnE,GACA0B,KACAnF,UACmB;CACnBmF,IAAIlI,UAAU0H,KAAKC,IAAI;CACvB,MAAMiD,UAAUnB,gBAAgBvB,GAAG;CACnC,KAAK,MAAM5F,aAAaS,MAAMzC,KAC5B,IAAIgC,UAAU/C,OAAOqL,SAASlB,OAAOlD,GAAG0B,KAAK5F,UAAU/C,GAAG;CAE5D,MAAMsL,SAAS9H,MAAMjB,IAAIqB,QAAQ2H,MAAMA,EAAEvL,MAAM2I,IAAInI,MAAM;CACzD,MAAMgL,SAAShI,MAAMzC,IAAI6C,QAAQ2H,MAAMA,EAAEvL,MAAMqL,OAAO;CACtD,IACGC,OAAO1I,SAAS,KAAK0I,OAAO,EAAE,CAAEtL,QAAQ2I,IAAInI,SAAS,KACrDgL,OAAO5I,SAAS,KAAK4I,OAAO,EAAE,CAAExL,QAAQqL,UAAU,GAEnD,OAAO;EACL3G,MAAM;EACNyG,KAAK,EAAEA,KAAK;GAAEnL,KAAKqL;GAAS7K,QAAQmI,IAAInI;EAAO,EAAE;CACnD;CAEF,KAAK,MAAMuC,aAAauI,QAAQ;EAC9B3C,IAAIjI,UAAUqC,UAAUlD;EACxB8I,IAAInI,SAASuC,UAAU/C;CACzB;CACA,KAAK,MAAM+C,aAAayI,QAAQb,SAAS1D,GAAG0B,KAAK5F,SAAS;CAC1D,IAAIyI,OAAO5I,SAAS,GAElB+G,SAAS1C,GAAG0B,IAAIrI,IAAI;EAAEN,KAAKwL,OAAOC,GAAG,EAAE,CAAC,CAAEzL;EAAK0L,KAAK;CAAK,CAAC;CAE5D1E,cAAcC,CAAC;CACf,OAAO,EAAEvC,MAAM,KAAK;AACtB;AAEA,MAAMzC,WAAWgF,GAAoBW,MAAYM,SAAiB;CAChE,IAAI,CAACN,KAAKvG,QAAQ4F,EAAEnB,YAAYmB,EAAErB,aAAa,MAAM;CACrD,MAAMnC,QAAQ,CAACmE,KAAKtG;CACpBsG,KAAKtG,WAAW;CAChB,IAAIkC;CACJ,IAAI;EACFA,QAAQU,WAAWgE,MAAMzE,KAAK;CAChC,SAASzB,OAAO;EACd,MAAMN,SAASK,gBAAgBC,KAAK;EACpC,IAAIN,WAAW,MAAM,MAAMM;EAC3B2F,UAAUV,GAAGW,MAAM,MAAMlG,MAAM;EAC/B;CACF;CACA,IAAI8B,MAAMjB,IAAIK,WAAW,KAAKY,MAAMzC,IAAI6B,WAAW,GAAG;CACtD,MAAM+F,MAAM1B,EAAE5B,QAAQ8D,IAAIvB,KAAK1G,QAAQ;CACvC,MAAMyK,YAAYP,WAAWnE,GAAG0B,KAAKnF,KAAK;CAC1C,IAAImI,UAAUjH,SAAS,WACrBuD,OAAOhB,GAAGW,MAAMzD,KAAKoF,UAAUoC,UAAUR,GAAG,CAAC;AAEjD;AAEA,MAAMS,aAAa3E,MAAuB;CACxC,IAAI4E,SAAS5E,EAAE5B,QAAQ0C,OAAOd,EAAEhC;CAChC,IAAI4G,UAAU,GAAG;CACjB,MAAMC,OAAO,IAAIvG,IAAI,CAAC,GAAG0B,EAAE3B,KAAK,CAAC,CAAC8D,KAAKxB,SAASA,KAAK1G,QAAQ,CAAC;CAC9D,MAAM6K,SAAS,CAAC,GAAG9E,EAAE5B,QAAQrB,OAAO,CAAC,CAAC,CAACF,MAAMkI,GAAGC,MAAMD,EAAEvL,UAAUwL,EAAExL,OAAO;CAC3E,KAAK,MAAMkI,OAAOoD,QAAQ;EACxB,IAAIF,UAAU,GAAG;EACjB,IAAIC,KAAKI,IAAIvD,IAAIrI,EAAE,KAAKqI,IAAI3H,SAAS+G,OAAO,GAAG;EAC/Cd,EAAE5B,QAAQwC,OAAOc,IAAIrI,EAAE;EACvBuL,UAAU;CACZ;AACF;AAQA,MAAaQ,YACXpF,GACA/F,UACAC,WACwB;CACxB,MAAMmL,UAAUzH,MAAcnD,WAAmB;EAC/C,IAAI;GACFP,OAAO2G,MAAMjD,MAAMnD,MAAM;EAC3B,QAAQ,CACN;EAEF,OAAO;CACT;CACA,IAAIuF,EAAEnB,UAAU,OAAOwG,OAAO,MAAM,UAAU;CAC9C,IAAI,CAAChN,aAAaiN,KAAKrL,QAAQ,GAAG,OAAOoL,OAAO,MAAM,mBAAmB;CACzE1D,MAAM3B,CAAC;CACP,IAAIA,EAAErB,aAAa,MAAM;EACvB,IAAI;GACFzE,OAAOkH,KAAKlE,KAAKoF,UAAU,EAAE5C,KAAKM,EAAErB,SAAS,CAAC,CAAC;EACjD,QAAQ,CACN;EAEF0G,OAAO,KAAM,UAAU;EACvB,OAAO;CACT;CAEA,MAAM3D,MADQ1B,EAAE5B,QAAQ6G,IAAIhL,QAChBsL,IACRvF,EAAE5B,QAAQ8D,IAAIjI,QAAQ,WACf;EACL,MAAMuL,UAAqB;GACzBnM,IAAIY;GACJX,SAAS;GACTC,QAAQ;GACRC,SAAS0H,KAAKC,IAAI;GAClB1H,SAAS;GACTE,yBAAS,IAAIC,IAAI;GACjBG,0BAAU,IAAIH,IAAI;EACpB;EACAoG,EAAE5B,QAAQqE,IAAIxI,UAAUuL,OAAO;EAC/B,OAAOA;CACT,EAAA,CAAG;CACP9D,IAAIlI,UAAU0H,KAAKC,IAAI;CACvB,MAAMR,OAAa;EACjB1G;EACAC;EACAE,MAAM;EACNC,UAAU;EACVC,YAAY;EACZC,OAAO;CACT;CACAyF,EAAE3B,MAAMoH,IAAI9E,IAAI;CAChBgE,UAAU3E,CAAC;CACXqB,gBAAgBrB,CAAC;CACjB,MAAM,EAAEpH,OAAOC,SAASnB,YAAYsI,EAAEd,UAAWwG,SAAS,CAAC;CAC3D,MAAMC,QAA2B;EAC/BxJ,KAAK,CACH;GACEzD,IAAI;GACJC,MAAM,CAAA;GACNC;GACA,GAAIC,SAASuD,KAAAA,KAAa,EAAEvD,KAAK;EACnC,CAAC;EAEHqL,KAAK;GACHnL,KAAKkK,gBAAgBvB,GAAG;GACxBnI,QAAQmI,IAAInI;GACZ,GAAIyG,EAAEtB,YAAY,EAAE2D,MAAM,KAAK;EACjC;CACF;CACArB,OAAOhB,GAAGW,MAAMzD,KAAKoF,UAAUqD,KAAK,CAAC;CAMrC,OAAO;EAAEjE;EAAKf;EAAMwE,YAAAA;GAJlBlL;GACAe,UAAUiG,SAASjG,QAAQgF,GAAGW,MAAMM,IAAI;GACxCJ,aAAaH,UAAUV,GAAGW,IAAI;EAEZwE;CAAW;AACjC;AAEA,MAAM5F,WACJS,GACA/F,UACAC,WACkD;CAElD,OADqBkL,SAASpF,GAAG/F,UAAUC,MACpC0L,CAAY,EAAET,cAAc;AACrC;AAEA,MAAM1F,UAAUO,GAAoBN,QAA2B;CAC7D,IAAIM,EAAErB,aAAa,QAAQqB,EAAEnB,UAAU;CACvCmB,EAAErB,WAAWe;CACbiC,MAAM3B,GAAGN,GAAG;AACd;AAEA,MAAMmG,UAAU7F,MAAuB;CACrCA,EAAEnB,WAAW;CACbmB,EAAEd,WAAWuB,SAAS/H,OAAOuH,SAASD,GAAGtH,EAAE,CAAC;AAC9C;AAEA,MAAMoN,WAAW9F,MAAuB;CACtCA,EAAEnB,WAAW;CACb,IAAImB,EAAEjB,mBAAmB,MAAM;EAC7BgC,cAAcf,EAAEjB,cAAc;EAC9BiB,EAAEjB,iBAAiB;CACrB;CACAiB,EAAEd,WAAWuB,QAAQ,IAAI;AAC3B;AAEA,MAAMsF,iBACJC,WACAC,YAIG;CACH,MAAM,CAACjG,KAAKnJ,eAAgC;EAC1C,MAAMuP,OAAwB;GAC5BrI,aAAa;GACbC,mBAAmBxF;GACnByF,WAAW;GACXC,WAAW9B,KAAAA;GACXgC,yBAAS,IAAIxE,IAAI;GACjByE,uBAAO,IAAIC,IAAI;GACfC,YAAY,CAAA;GACZC,gCAAgB,IAAI5E,IAAI;GACxB6E,6BAAa,IAAI7E,IAAI;GACrB8E,UAAU;GACVC,UAAU;GACVE,UAAU;GACVC,gBAAgB;GAChBC,gBAAgB;GAChBG,WAAW;GACXE,cAAc;GACdC,SAAS;GACTC,MAAM1H,4BAA4B;IAChCwO,KAAKtH,iBAAiB;IACtB6C,MAAMyE,IAAI;GACZ,CAAC;GACD7G,UAAUtF,UAAUC,WAAWqF,QAAQ6G,MAAMnM,UAAUC,MAAM;GAC7DuF,SAASC,QAAQD,OAAO2G,MAAM1G,GAAG;GACjCvH,SAASwH,YAAYvH,OAAYgO,MAAMzG,OAAO;GAC9C1H,SAAS0H,cAAYzH,OAAYkO,MAAMzG,SAAO;EAChD;EACA,OAAOyG;CACT,CAAC;CACD7E,eAAevB,GAAGiG,SAASI,uBAAuB,IAAM;CACxDrG,EAAEhC,oBAAoBiI,SAASjI,qBAAqBxF;CACpDwH,EAAE/B,YAAYgI,SAAShI,aAAa;CACpC+B,EAAE9B,YAAY+H,SAAS/H;CACvB,MAAMtF,QAAQ5B,YAAYgP,SAAS;CACnC9F,OAAOF,GAAGpH,KAAK;CACfhC,gBAAgB;EACdsJ,OAAOF,GAAGpH,KAAK;CACjB,CAAC;CACDhC,gBAAgB;EACdiP,OAAO7F,CAAC;EACR,aAAa8F,QAAQ9F,CAAC;CACxB,GAAG,CAACA,CAAC,CAAC;CACN,OAAOA;AACT;;;;;;;;;AAUA,MAAasG,uBACXN,WACAC,YACqC;CACrC,MAAMM,uBAAiB;EAAA,OAAMR,cAAcC,WAAWC,OAAO;CAAC;CAC9D,MAAMO,OAAO1P,cAAcyP,cAAc;CACzC,IAAI1H,WAAW;CACf,OAAO;EACLU,UAAUtF,UAAUC,WAClBnD,mBAAmByP,KAAKC,SAAS,CAAC,CAAClH,QAAQtF,UAAUC,MAAM,CAAC;EAC9D/B,SAASwH,YAAY5I,mBAAmByP,KAAKC,SAAS,CAAC,CAACtO,OAAOwH,OAAO,CAAC;EACvE1H,SAAS0H,YAAY5I,mBAAmByP,KAAKC,SAAS,CAAC,CAACxO,OAAO0H,OAAO,CAAC;EACvEF,SAASC,QAAQ3I,mBAAmByP,KAAKC,SAAS,CAAC,CAAChH,OAAOC,GAAG,CAAC;EAC/DgH,eAAe;GACb,IAAI7H,UAAU;GACdA,WAAW;GACX9H,mBAAmByP,KAAKC,SAAS,CAAC,CAAChH,OAAO,EAAEhF,QAAQ,UAAU,CAAC,CAAC;GAChE+L,KAAKG,QAAQ;EACf;CACF;AACF"}
1
+ {"version":3,"file":"socket.js","names":["useEffect","useState","createTapRoot","flushTapSync","useResource","ResourceElement","getCommandsHost","getStateHost","CommandsHost","CommandsOutcome","StatewireSendError","Statewire","StatewireHost","StatewireHostInternal","encodeValue","reviveValue","createMacrotaskPoster","StatewireMetaEntry","StatewirePath","StatewireCmd","StatewireEnvelope","frames","serveFrames","stream","serveStream","CLIENT_ID_RE","RESULT_TTL_MS","RESULT_LIMIT","CLIENT_RECORD_LIMIT","WireOp","op","path","value","meta","Admission","seq","method","applied","appliedSent","settled","ClientRec","id","lastSeq","ctxSeq","touched","context","Record","results","Map","ts","cmd","inflight","Conn","clientId","socket","Socket","open","sawFrame","lastSentAt","lease","PendingConn","authorizing","timer","ReturnType","setTimeout","connection","SocketConnection","violation","reason","Object","assign","Error","name","violationReason","error","message","CtxStatement","CmdStatement","params","ParsedFrame","headers","ctx","isPlainObject","Array","isArray","parseLane","length","statements","prev","statement","Number","isInteger","push","contextValue","ops","undefined","rejectUnknown","parseFrameValue","frame","first","keys","unknown","filter","key","sort","raw","values","some","parseFrame","JSON","parse","encodePayload","payload","cmdOf","adm","outcome","type","failure","fate","code","String","SocketHostState","heartbeatMs","wsInitTimeoutMs","clientRecordLimit","finOnIdle","authorize","SocketHostOptions","clients","conns","Set","pendingConns","pendingOps","pendingApplied","pendingCmds","idleWire","finished","Fin","disposed","flushScheduled","heartbeatTimer","setInterval","stateHost","StateHost","commandsHost","current","post","connect","options","SocketConnectOptions","finish","fin","request","Request","Promise","Response","scheduleFlush","h","recordOp","attach","next","nextState","state","nextCommands","commands","submit","setOnOp","closeConn","conn","delete","close","size","clearInterval","sendTo","data","Date","now","send","ensureHeartbeat","unref","setHeartbeatMs","ms","idleLevel","rec","flush","takeChanged","queueApplied","level","edge","cmds","appliedEntries","get","map","packet","idle","stringify","verdicts","list","set","queueCmd","retain","newest","Math","max","entry","min","admittedThrough","reemit","cached","settleCmd","settleWire","callerOf","Caller","isConnected","rejectStatement","admitCmd","names","methods","caller","onApplied","onSettle","catch","FrameAdmission","syn","admitFrame","through","ctxNew","s","cmdNew","at","dur","admission","closePending","pending","clearTimeout","sendPending","rejectPendingAuthorization","response","unauthorized","status","statusText","normalizedHeaders","fromEntries","Headers","connectAuthorized","authorized","registration","register","refuse","test","add","resolve","then","onAuthorized","gcClients","excess","live","oldest","a","b","has","Registration","known","created","snapshot","hello","resume","suspend","useSocketHost","transport","Pick","SocketHost","host","connectOptions","heartbeatIntervalMs","StatewireSocketHost","SocketHostRoot","root","getValue","dispose","unmount"],"sources":["../../src/host/socket.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { createTapRoot, flushTapSync, useResource } from \"@assistant-ui/tap\";\nimport type { ResourceElement } from \"@assistant-ui/tap\";\nimport { getCommandsHost, getStateHost } from \"./host\";\nimport type { CommandsHost, CommandsOutcome } from \"./host\";\nimport { StatewireSendError } from \"../types\";\nimport type { Statewire } from \"../types\";\nimport type { StatewireHost } from \"../host\";\nimport type { StatewireHostInternal } from \"../host-internal\";\nimport { encodeValue, reviveValue } from \"../wire/meta\";\nimport { createMacrotaskPoster } from \"../util/macrotask\";\nimport type { StatewireMetaEntry } from \"../wire/meta\";\nimport type { StatewirePath } from \"../wire/ops\";\nimport type { StatewireCmd, StatewireEnvelope } from \"../client/connection\";\nimport { frames as serveFrames, stream as serveStream } from \"./http\";\n\nexport const CLIENT_ID_RE = /^[A-Za-z0-9._~-]{1,256}$/;\nconst RESULT_TTL_MS = 30_000;\nconst RESULT_LIMIT = 256;\nconst CLIENT_RECORD_LIMIT = 1024;\n\ntype WireOp = {\n op: string;\n path?: StatewirePath;\n value?: unknown;\n meta?: StatewireMetaEntry[];\n};\n\ntype Admission = {\n seq: number;\n method: string;\n applied: boolean;\n appliedSent: boolean;\n settled: boolean;\n};\n\nexport type ClientRec = {\n id: string;\n lastSeq: number;\n ctxSeq: number;\n touched: number;\n context: Record<string, unknown> | null;\n results: Map<number, { ts: number; cmd: StatewireCmd }>;\n inflight: Map<number, Admission>;\n};\n\nexport type Conn = {\n clientId: string;\n socket: StatewireHostInternal.Socket;\n open: boolean;\n sawFrame: boolean;\n lastSentAt: number;\n lease: string | null;\n};\n\ntype PendingConn = {\n socket: StatewireHostInternal.Socket;\n open: boolean;\n authorizing: boolean;\n timer: ReturnType<typeof setTimeout> | null;\n connection: StatewireHostInternal.SocketConnection | null;\n};\n\n// ─── frame parsing ──────────────────────────────────────\n\nconst violation = (reason: string): never => {\n throw Object.assign(new Error(reason), { name: \"StatewireViolation\" });\n};\n\nconst violationReason = (error: unknown): string | null =>\n error instanceof Error && error.name === \"StatewireViolation\"\n ? error.message\n : null;\n\ntype CtxStatement = { seq: number; value: Record<string, unknown> };\ntype CmdStatement = {\n seq: number;\n method: string;\n params: unknown;\n meta?: unknown;\n};\n\nexport type ParsedFrame = {\n headers: Record<string, string> | null;\n ctx: CtxStatement[];\n cmd: CmdStatement[];\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst parseLane = (value: unknown): Record<string, unknown>[] => {\n if (!Array.isArray(value)) return violation(\"malformed frame\");\n if (value.length === 0) return violation(\"empty lane\");\n const statements: Record<string, unknown>[] = [];\n let prev: number | null = null;\n for (const statement of value) {\n if (!isPlainObject(statement)) return violation(\"malformed statement\");\n const seq = statement[\"seq\"];\n if (typeof seq !== \"number\" || !Number.isInteger(seq) || seq < 1) {\n return violation(\"malformed statement\");\n }\n if (prev !== null && seq !== prev + 1) return violation(\"malformed frame\");\n prev = seq;\n statements.push(statement);\n }\n return statements;\n};\n\n/** v1 ctx statements state the context whole: one root replace with an object value. */\nconst contextValue = (ops: unknown): Record<string, unknown> => {\n if (!Array.isArray(ops) || ops.length !== 1) {\n throw new Error(\"context must be a single-op array\");\n }\n const op = ops[0] as Record<string, unknown> | null;\n if (\n !isPlainObject(op) ||\n op[\"op\"] !== \"replace\" ||\n !Array.isArray(op[\"path\"]) ||\n op[\"path\"].length !== 0\n ) {\n throw new Error(\"context op must be a root replace\");\n }\n const value =\n op[\"meta\"] !== undefined\n ? reviveValue(op[\"value\"], op[\"meta\"], { rejectUnknown: true })\n : op[\"value\"];\n if (!isPlainObject(value)) {\n throw new Error(\"context value must be an object\");\n }\n return value;\n};\n\nexport const parseFrameValue = (\n frame: unknown,\n first: boolean,\n): ParsedFrame => {\n if (!isPlainObject(frame)) return violation(\"malformed frame\");\n const keys = Object.keys(frame);\n if (keys.length === 0) return violation(\"malformed frame\");\n const unknown = keys\n .filter((key) => key !== \"headers\" && key !== \"ctx\" && key !== \"cmd\")\n .sort();\n if (unknown.length > 0)\n return violation(`unknown frame key: '${unknown[0]}'`);\n let headers: Record<string, string> | null = null;\n if (frame[\"headers\"] !== undefined) {\n if (!first) return violation(\"mid-session headers\");\n const raw = frame[\"headers\"];\n if (\n !isPlainObject(raw) ||\n Object.values(raw).some((value) => typeof value !== \"string\")\n ) {\n return violation(\"malformed headers\");\n }\n headers = raw as Record<string, string>;\n }\n const ctx: CtxStatement[] = [];\n if (frame[\"ctx\"] !== undefined) {\n for (const statement of parseLane(frame[\"ctx\"])) {\n try {\n ctx.push({\n seq: statement[\"seq\"] as number,\n value: contextValue(statement[\"ops\"]),\n });\n } catch {\n return violation(\"invalid-context\");\n }\n }\n }\n const cmd: CmdStatement[] = [];\n if (frame[\"cmd\"] !== undefined) {\n for (const statement of parseLane(frame[\"cmd\"])) {\n const method = statement[\"method\"];\n if (typeof method !== \"string\" || !(\"params\" in statement)) {\n return violation(\"malformed statement\");\n }\n cmd.push({\n seq: statement[\"seq\"] as number,\n method,\n params: statement[\"params\"],\n ...(statement[\"meta\"] !== undefined && { meta: statement[\"meta\"] }),\n });\n }\n }\n return { headers, ctx, cmd };\n};\n\nexport const parseFrame = (raw: string, first: boolean): ParsedFrame => {\n let frame: unknown;\n try {\n frame = JSON.parse(raw);\n } catch {\n return violation(\"malformed frame\");\n }\n return parseFrameValue(frame, first);\n};\n\n// ─── verdict encoding ───────────────────────────────────\n\nconst encodePayload = (\n payload: unknown,\n): { payload?: unknown; meta?: StatewireMetaEntry[] } => {\n if (payload === undefined) return {};\n const { value, meta } = encodeValue(payload);\n return { payload: value, ...(meta !== undefined && { meta }) };\n};\n\nconst cmdOf = (adm: Admission, outcome: CommandsOutcome): StatewireCmd => {\n if (outcome.type === \"accepted\") {\n return { seq: adm.seq, type: \"result\", ...encodePayload(outcome.payload) };\n }\n const failure =\n outcome.error instanceof StatewireSendError ? outcome.error.failure : null;\n switch (failure?.fate) {\n case \"failed\":\n return {\n seq: adm.seq,\n type: \"failed\",\n ...(failure.message !== undefined && { message: failure.message }),\n };\n case \"rejected\": {\n if (failure.code !== undefined) {\n const message =\n failure.code === \"unknown-command\"\n ? `unknown method: '${adm.method}'`\n : failure.message;\n return {\n seq: adm.seq,\n type: \"rejected\",\n code: failure.code,\n ...(message !== undefined && { message }),\n };\n }\n return {\n seq: adm.seq,\n type: \"rejected\",\n ...(failure.message !== undefined && { message: failure.message }),\n ...encodePayload(failure.payload),\n };\n }\n default:\n return {\n seq: adm.seq,\n type: \"failed\",\n message:\n outcome.error instanceof Error\n ? outcome.error.message\n : String(outcome.error),\n };\n }\n};\n\n// ─── host ───────────────────────────────────────────────\n\nexport type SocketHostState = {\n heartbeatMs: number;\n wsInitTimeoutMs: number;\n clientRecordLimit: number;\n finOnIdle: boolean;\n authorize: StatewireHostInternal.SocketHostOptions[\"authorize\"];\n clients: Map<string, ClientRec>;\n conns: Set<Conn>;\n pendingConns: Set<PendingConn>;\n pendingOps: WireOp[];\n pendingApplied: Map<string, number[]>;\n pendingCmds: Map<string, StatewireCmd[]>;\n idleWire: boolean;\n finished: StatewireHost.Fin | null;\n disposed: boolean;\n flushScheduled: boolean;\n heartbeatTimer: ReturnType<typeof setInterval> | null;\n stateHost: StatewireHost.StateHost | null;\n commandsHost: CommandsHost | null;\n current: Statewire<unknown> | null;\n post: () => void;\n connect: (\n clientId: string,\n socket: StatewireHostInternal.Socket,\n options?: StatewireHostInternal.SocketConnectOptions,\n ) => StatewireHostInternal.SocketConnection | null;\n finish: (fin: StatewireHost.Fin) => void;\n stream: (request: Request) => Promise<Response>;\n frames: (request: Request) => Promise<Response>;\n};\n\nconst scheduleFlush = (h: SocketHostState) => {\n if (h.flushScheduled || h.disposed) return;\n h.flushScheduled = true;\n h.post();\n};\n\nconst recordOp = (\n h: SocketHostState,\n op: {\n op: string;\n path?: StatewirePath;\n value?: unknown;\n },\n) => {\n if (op.op === \"replace\" || op.op === \"add\") {\n const { value, meta } = encodeValue(op.value);\n h.pendingOps.push({ ...op, value, ...(meta !== undefined && { meta }) });\n } else {\n h.pendingOps.push(op);\n }\n scheduleFlush(h);\n};\n\nconst attach = (h: SocketHostState, next: Statewire<unknown>) => {\n if (next === h.current) return;\n h.current = next;\n const nextState =\n typeof next.state === \"object\" && next.state !== null\n ? getStateHost(next.state)\n : undefined;\n const nextCommands = getCommandsHost(next.commands);\n if (!nextState || !nextCommands?.submit) {\n throw new Error(\n \"StatewireSocketHost requires a statewire/host transport (useStatewireState with object state, useStatewireCommands)\",\n );\n }\n if (nextState !== h.stateHost) {\n h.stateHost?.setOnOp(null);\n h.stateHost = nextState;\n h.stateHost.setOnOp((op) => recordOp(h, op));\n }\n h.commandsHost = nextCommands;\n};\n\nexport const closeConn = (\n h: SocketHostState,\n conn: Conn,\n code?: number,\n reason?: string,\n) => {\n if (!conn.open) return;\n conn.open = false;\n h.conns.delete(conn);\n try {\n conn.socket.close(code, reason);\n } catch {\n /* peer already gone */\n }\n if (h.conns.size === 0 && h.heartbeatTimer !== null) {\n clearInterval(h.heartbeatTimer);\n h.heartbeatTimer = null;\n }\n};\n\nexport const sendTo = (h: SocketHostState, conn: Conn, data: string) => {\n if (!conn.open) return;\n conn.lastSentAt = Date.now();\n try {\n conn.socket.send(data);\n } catch {\n closeConn(h, conn);\n }\n};\n\nconst ensureHeartbeat = (h: SocketHostState) => {\n if (h.heartbeatTimer !== null || h.heartbeatMs <= 0) return;\n h.heartbeatTimer = setInterval(() => {\n const now = Date.now();\n for (const conn of [...h.conns]) {\n if (now - conn.lastSentAt >= h.heartbeatMs) sendTo(h, conn, \"{}\");\n }\n }, h.heartbeatMs);\n (h.heartbeatTimer as unknown as { unref?: () => void }).unref?.();\n};\n\nconst setHeartbeatMs = (h: SocketHostState, ms: number) => {\n if (ms === h.heartbeatMs) return;\n h.heartbeatMs = ms;\n if (h.heartbeatTimer !== null) {\n clearInterval(h.heartbeatTimer);\n h.heartbeatTimer = null;\n ensureHeartbeat(h);\n }\n};\n\nconst idleLevel = (h: SocketHostState): boolean => {\n for (const rec of h.clients.values()) {\n if (rec.inflight.size > 0) return false;\n }\n return true;\n};\n\nexport const flush = (h: SocketHostState, fin?: StatewireHost.Fin) => {\n flushTapSync(() => {});\n h.stateHost?.takeChanged();\n for (const rec of h.clients.values()) {\n for (const adm of rec.inflight.values()) {\n if (adm.applied && !adm.settled && !adm.appliedSent) {\n adm.appliedSent = true;\n queueApplied(h, rec.id, adm.seq);\n }\n }\n }\n const level = idleLevel(h);\n const edge = level !== h.idleWire;\n if (\n h.pendingOps.length === 0 &&\n h.pendingApplied.size === 0 &&\n h.pendingCmds.size === 0 &&\n fin === undefined &&\n !edge\n ) {\n return;\n }\n h.idleWire = level;\n if (fin === undefined && edge && level && h.finOnIdle) {\n fin = { reason: \"idle\" };\n }\n const ops = h.pendingOps;\n const applied = h.pendingApplied;\n const cmds = h.pendingCmds;\n h.pendingOps = [];\n h.pendingApplied = new Map();\n h.pendingCmds = new Map();\n // Applied entries anchor to their effects: piggybacked on the ops packet\n // when one is flushing, standalone otherwise. Terminal verdicts ride their\n // own packet.\n for (const conn of [...h.conns]) {\n const appliedEntries: StatewireCmd[] = (\n applied.get(conn.clientId) ?? []\n ).map((seq) => ({ seq, type: \"applied\" }));\n if (ops.length > 0) {\n const packet: StatewireEnvelope = {\n ops,\n ...(appliedEntries.length > 0 && { cmd: appliedEntries }),\n ...(edge && { idle: level }),\n };\n sendTo(h, conn, JSON.stringify(packet));\n } else if (appliedEntries.length > 0) {\n sendTo(h, conn, JSON.stringify({ cmd: appliedEntries }));\n }\n const verdicts = cmds.get(conn.clientId) ?? [];\n if (verdicts.length > 0) {\n sendTo(h, conn, JSON.stringify({ cmd: verdicts }));\n }\n if (edge && ops.length === 0) {\n sendTo(h, conn, JSON.stringify({ idle: level }));\n }\n if (fin !== undefined) {\n sendTo(h, conn, JSON.stringify({ fin }));\n closeConn(h, conn);\n }\n }\n};\n\nconst queueApplied = (h: SocketHostState, clientId: string, seq: number) => {\n const list = h.pendingApplied.get(clientId);\n if (list) list.push(seq);\n else h.pendingApplied.set(clientId, [seq]);\n scheduleFlush(h);\n};\n\nconst queueCmd = (h: SocketHostState, clientId: string, cmd: StatewireCmd) => {\n const list = h.pendingCmds.get(clientId);\n if (list) list.push(cmd);\n else h.pendingCmds.set(clientId, [cmd]);\n scheduleFlush(h);\n};\n\nconst retain = (rec: ClientRec, cmd: StatewireCmd) => {\n const now = Date.now();\n rec.results.set(cmd.seq, { ts: now, cmd });\n const newest = Math.max(...rec.results.keys());\n for (const [seq, entry] of rec.results) {\n if (seq !== newest && now - entry.ts > RESULT_TTL_MS) {\n rec.results.delete(seq);\n }\n }\n while (rec.results.size > RESULT_LIMIT) {\n rec.results.delete(Math.min(...rec.results.keys()));\n }\n};\n\n/** Cmd-lane watermark: the last statement admitted, settled or not. */\nconst admittedThrough = (rec: ClientRec): number =>\n Math.max(rec.lastSeq, ...rec.inflight.keys());\n\n// A re-asked seq never re-runs: the stored verdict re-emits, an applied\n// inflight run re-answers applied; one not yet applied answers nothing (its\n// answers ride the stream when ready), an evicted verdict answers expired.\nconst reemit = (h: SocketHostState, rec: ClientRec, seq: number) => {\n const cached = rec.results.get(seq);\n if (cached) {\n const newest = Math.max(...rec.results.keys());\n if (seq === newest || Date.now() - cached.ts <= RESULT_TTL_MS) {\n queueCmd(h, rec.id, cached.cmd);\n return;\n }\n rec.results.delete(seq);\n }\n const adm = rec.inflight.get(seq);\n if (adm) {\n if (adm.applied) queueApplied(h, rec.id, seq);\n return;\n }\n queueCmd(h, rec.id, { seq, type: \"expired\" });\n};\n\nconst settleCmd = (\n h: SocketHostState,\n rec: ClientRec,\n adm: Admission,\n cmd: StatewireCmd,\n) => {\n if (adm.settled) return;\n adm.settled = true;\n rec.inflight.delete(adm.seq);\n retain(rec, cmd);\n rec.lastSeq = Math.max(rec.lastSeq, adm.seq);\n adm.applied = true;\n queueCmd(h, rec.id, cmd);\n};\n\nconst settleWire = (\n h: SocketHostState,\n rec: ClientRec,\n adm: Admission,\n outcome: CommandsOutcome,\n) => settleCmd(h, rec, adm, cmdOf(adm, outcome));\n\nconst callerOf = (\n h: SocketHostState,\n rec: ClientRec,\n): StatewireHost.Caller => ({\n clientId: rec.id,\n get context() {\n return rec.context;\n },\n get isConnected() {\n if (h.clients.get(rec.id) !== rec) return false;\n for (const conn of h.conns) {\n if (conn.clientId === rec.id && conn.open) return true;\n }\n return false;\n },\n});\n\nconst rejectStatement = (\n h: SocketHostState,\n rec: ClientRec,\n adm: Admission,\n message: string,\n) =>\n settleCmd(h, rec, adm, {\n seq: adm.seq,\n type: \"rejected\",\n code: \"invalid-params\",\n message,\n });\n\nconst admitCmd = (\n h: SocketHostState,\n rec: ClientRec,\n statement: CmdStatement,\n) => {\n const adm: Admission = {\n seq: statement.seq,\n method: statement.method,\n applied: false,\n appliedSent: false,\n settled: false,\n };\n rec.inflight.set(statement.seq, adm);\n if (!Array.isArray(statement.params)) {\n rejectStatement(h, rec, adm, \"params must be an array\");\n return;\n }\n let params = statement.params;\n if (statement.meta !== undefined) {\n try {\n params = reviveValue(params, statement.meta, {\n rejectUnknown: true,\n }) as unknown[];\n } catch (error) {\n rejectStatement(\n h,\n rec,\n adm,\n `invalid params: ${(error as Error).message}`,\n );\n return;\n }\n }\n if (statement.method === \"statewire/commands\") {\n if (params.length > 0) {\n rejectStatement(h, rec, adm, \"statewire/commands takes no params\");\n return;\n }\n const names = [\n ...(h.commandsHost?.methods?.() ?? []),\n \"statewire/commands\",\n ].sort();\n settleCmd(h, rec, adm, { seq: adm.seq, type: \"result\", payload: names });\n return;\n }\n h.commandsHost!.submit!({\n method: statement.method,\n params,\n clientId: rec.id,\n caller: callerOf(h, rec),\n onApplied: () => {\n if (adm.settled || adm.applied) return;\n adm.applied = true;\n rec.lastSeq = Math.max(rec.lastSeq, adm.seq);\n scheduleFlush(h);\n },\n onSettle: (outcome) => settleWire(h, rec, adm, outcome),\n }).catch((error: unknown) => {\n if (!adm.settled) settleWire(h, rec, adm, { type: \"rejected\", error });\n });\n};\n\n// One admission law, both lanes: absorbed statements answer from the record,\n// then the new suffix is admitted whole or the frame is refused whole via a\n// {syn} stating both watermarks, nothing consumed. A gap is never a close.\nexport type FrameAdmission =\n | { type: \"ok\" }\n | { type: \"refused\"; syn: { syn: { seq: number; ctxSeq: number } } };\n\nexport const admitFrame = (\n h: SocketHostState,\n rec: ClientRec,\n frame: ParsedFrame,\n): FrameAdmission => {\n rec.touched = Date.now();\n const through = admittedThrough(rec);\n for (const statement of frame.cmd) {\n if (statement.seq <= through) reemit(h, rec, statement.seq);\n }\n const ctxNew = frame.ctx.filter((s) => s.seq > rec.ctxSeq);\n const cmdNew = frame.cmd.filter((s) => s.seq > through);\n if (\n (ctxNew.length > 0 && ctxNew[0]!.seq !== rec.ctxSeq + 1) ||\n (cmdNew.length > 0 && cmdNew[0]!.seq !== through + 1)\n ) {\n return {\n type: \"refused\",\n syn: { syn: { seq: through, ctxSeq: rec.ctxSeq } },\n };\n }\n for (const statement of ctxNew) {\n rec.context = statement.value;\n rec.ctxSeq = statement.seq;\n }\n for (const statement of cmdNew) admitCmd(h, rec, statement);\n if (cmdNew.length > 0) {\n // Memory host: admitted means retained — dur rides the admitting flush.\n queueCmd(h, rec.id, { seq: cmdNew.at(-1)!.seq, dur: true });\n }\n scheduleFlush(h);\n return { type: \"ok\" };\n};\n\nconst message = (h: SocketHostState, conn: Conn, data: string) => {\n if (!conn.open || h.disposed || h.finished !== null) return;\n const first = !conn.sawFrame;\n conn.sawFrame = true;\n let frame: ParsedFrame;\n try {\n frame = parseFrame(data, first);\n } catch (error) {\n const reason = violationReason(error);\n if (reason === null) throw error;\n closeConn(h, conn, 1008, reason);\n return;\n }\n if (frame.ctx.length === 0 && frame.cmd.length === 0) return;\n const rec = h.clients.get(conn.clientId)!;\n const admission = admitFrame(h, rec, frame);\n if (admission.type === \"refused\") {\n sendTo(h, conn, JSON.stringify(admission.syn));\n }\n};\n\nconst closePending = (\n h: SocketHostState,\n pending: PendingConn,\n code?: number,\n reason?: string,\n) => {\n if (!pending.open) return;\n pending.open = false;\n h.pendingConns.delete(pending);\n if (pending.timer !== null) clearTimeout(pending.timer);\n try {\n pending.socket.close(code, reason);\n } catch {\n /* peer already gone */\n }\n};\n\nconst sendPending = (pending: PendingConn, data: string): boolean => {\n if (!pending.open) return false;\n try {\n pending.socket.send(data);\n return true;\n } catch {\n return false;\n }\n};\n\nconst rejectPendingAuthorization = (\n h: SocketHostState,\n pending: PendingConn,\n error: unknown,\n) => {\n const response = error instanceof Response ? error : null;\n const unauthorized = response?.status === 401 || response?.status === 403;\n const status = response?.status;\n const message = unauthorized\n ? \"unauthorized\"\n : response?.statusText ||\n (status === undefined ? \"authorization failed\" : `HTTP ${status}`);\n sendPending(\n pending,\n JSON.stringify({\n fin: {\n reason: unauthorized ? \"unauthorized\" : \"error\",\n message,\n ...(status !== undefined && { status }),\n },\n }),\n );\n closePending(h, pending, unauthorized ? 1008 : 1011, message);\n};\n\nconst normalizedHeaders = (\n headers: Record<string, string>,\n): Record<string, string> => Object.fromEntries(new Headers(headers));\n\nconst connectAuthorized = (\n h: SocketHostState,\n clientId: string,\n socket: StatewireHostInternal.Socket,\n options: StatewireHostInternal.SocketConnectOptions,\n): StatewireHostInternal.SocketConnection | null => {\n const authorize = h.authorize;\n if (authorize === undefined || options.authorized === true) {\n const registration = register(\n h,\n clientId,\n socket,\n options.authorized === true,\n );\n return registration?.connection ?? null;\n }\n const refuse = (code: number, reason: string) => {\n try {\n socket.close(code, reason);\n } catch {\n /* peer already gone */\n }\n return null;\n };\n if (h.disposed) return refuse(1001, \"disposed\");\n if (!CLIENT_ID_RE.test(clientId)) return refuse(1008, \"invalid client id\");\n flush(h);\n if (h.finished !== null) {\n try {\n socket.send(JSON.stringify({ fin: h.finished }));\n } catch {\n /* peer already gone */\n }\n return refuse(1000, \"finished\");\n }\n const pending: PendingConn = {\n socket,\n open: true,\n authorizing: false,\n timer: null,\n connection: null,\n };\n h.pendingConns.add(pending);\n pending.timer = setTimeout(\n () =>\n rejectPendingAuthorization(\n h,\n pending,\n new Response(null, { status: 401 }),\n ),\n h.wsInitTimeoutMs,\n );\n (pending.timer as unknown as { unref?: () => void }).unref?.();\n return {\n clientId,\n message: (data) => {\n if (pending.connection !== null) {\n pending.connection.message(data);\n return;\n }\n if (!pending.open || h.disposed || h.finished !== null) return;\n if (pending.authorizing) {\n closePending(h, pending, 1008, \"authorization pending\");\n return;\n }\n let frame: ParsedFrame;\n try {\n frame = parseFrame(data, true);\n } catch (error) {\n const reason = violationReason(error);\n if (reason === null) throw error;\n sendPending(\n pending,\n JSON.stringify({\n fin: {\n reason: \"error\",\n message: `protocol violation: ${reason}`,\n },\n }),\n );\n closePending(h, pending, 1008, reason);\n return;\n }\n if (frame.headers === null) {\n rejectPendingAuthorization(\n h,\n pending,\n new Response(null, { status: 401 }),\n );\n return;\n }\n let headers: Record<string, string>;\n try {\n headers = normalizedHeaders(frame.headers);\n } catch {\n sendPending(\n pending,\n JSON.stringify({\n fin: {\n reason: \"error\",\n message: \"protocol violation: malformed headers\",\n },\n }),\n );\n closePending(h, pending, 1008, \"malformed headers\");\n return;\n }\n pending.authorizing = true;\n Promise.resolve()\n .then(() => authorize({ headers }))\n .then(() => {\n if (!pending.open || h.disposed || h.finished !== null) return;\n options.onAuthorized?.();\n pending.open = false;\n h.pendingConns.delete(pending);\n if (pending.timer !== null) clearTimeout(pending.timer);\n const registration = register(h, clientId, socket, true);\n if (registration === null) return;\n pending.connection = registration.connection;\n if (frame.ctx.length === 0 && frame.cmd.length === 0) return;\n const admission = admitFrame(h, registration.rec, frame);\n if (admission.type === \"refused\") {\n sendTo(h, registration.conn, JSON.stringify(admission.syn));\n }\n })\n .catch((error: unknown) => {\n if (pending.open) rejectPendingAuthorization(h, pending, error);\n });\n },\n close: () => {\n if (pending.connection !== null) pending.connection.close();\n else closePending(h, pending);\n },\n };\n};\n\nconst gcClients = (h: SocketHostState) => {\n let excess = h.clients.size - h.clientRecordLimit;\n if (excess <= 0) return;\n const live = new Set([...h.conns].map((conn) => conn.clientId));\n const oldest = [...h.clients.values()].sort((a, b) => a.touched - b.touched);\n for (const rec of oldest) {\n if (excess <= 0) return;\n if (live.has(rec.id) || rec.inflight.size > 0) continue;\n h.clients.delete(rec.id);\n excess -= 1;\n }\n};\n\nexport type Registration = {\n rec: ClientRec;\n conn: Conn;\n connection: StatewireHostInternal.SocketConnection;\n};\n\nexport const register = (\n h: SocketHostState,\n clientId: string,\n socket: StatewireHostInternal.Socket,\n sawFrame = false,\n): Registration | null => {\n const refuse = (code: number, reason: string) => {\n try {\n socket.close(code, reason);\n } catch {\n /* peer already gone */\n }\n return null;\n };\n if (h.disposed) return refuse(1001, \"disposed\");\n if (!CLIENT_ID_RE.test(clientId)) return refuse(1008, \"invalid client id\");\n flush(h);\n if (h.finished !== null) {\n try {\n socket.send(JSON.stringify({ fin: h.finished }));\n } catch {\n /* peer already gone */\n }\n refuse(1000, \"finished\");\n return null;\n }\n const known = h.clients.has(clientId);\n const rec = known\n ? h.clients.get(clientId)!\n : (() => {\n const created: ClientRec = {\n id: clientId,\n lastSeq: 0,\n ctxSeq: 0,\n touched: Date.now(),\n context: null,\n results: new Map(),\n inflight: new Map(),\n };\n h.clients.set(clientId, created);\n return created;\n })();\n rec.touched = Date.now();\n const conn: Conn = {\n clientId,\n socket,\n open: true,\n sawFrame,\n lastSentAt: 0,\n lease: null,\n };\n h.conns.add(conn);\n gcClients(h);\n ensureHeartbeat(h);\n const { value, meta } = encodeValue(h.stateHost!.snapshot());\n const hello: StatewireEnvelope = {\n ops: [\n {\n op: \"replace\",\n path: [],\n value,\n ...(meta !== undefined && { meta }),\n },\n ],\n syn: {\n seq: admittedThrough(rec),\n ctxSeq: rec.ctxSeq,\n ...(h.idleWire && { idle: true }),\n },\n };\n sendTo(h, conn, JSON.stringify(hello));\n const connection: StatewireHostInternal.SocketConnection = {\n clientId,\n message: (data) => message(h, conn, data),\n close: () => closeConn(h, conn),\n };\n return { rec, conn, connection };\n};\n\nconst connect = (\n h: SocketHostState,\n clientId: string,\n socket: StatewireHostInternal.Socket,\n options: StatewireHostInternal.SocketConnectOptions = {},\n): StatewireHostInternal.SocketConnection | null => {\n return connectAuthorized(h, clientId, socket, options);\n};\n\nconst finish = (h: SocketHostState, fin: StatewireHost.Fin) => {\n if (h.finished !== null || h.disposed) return;\n h.finished = fin;\n for (const pending of [...h.pendingConns]) {\n sendPending(pending, JSON.stringify({ fin }));\n closePending(h, pending, 1000, fin.reason);\n }\n flush(h, fin);\n};\n\nconst resume = (h: SocketHostState) => {\n h.disposed = false;\n h.stateHost?.setOnOp((op) => recordOp(h, op));\n};\n\nconst suspend = (h: SocketHostState) => {\n h.disposed = true;\n if (h.heartbeatTimer !== null) {\n clearInterval(h.heartbeatTimer);\n h.heartbeatTimer = null;\n }\n h.stateHost?.setOnOp(null);\n};\n\nconst useSocketHost = (\n transport: ResourceElement<Statewire>,\n options?: StatewireHostInternal.SocketHostOptions,\n): Pick<\n StatewireHostInternal.SocketHost,\n \"connect\" | \"finish\" | \"stream\" | \"frames\"\n> => {\n const [h] = useState((): SocketHostState => {\n const host: SocketHostState = {\n heartbeatMs: 15_000,\n wsInitTimeoutMs: 5_000,\n clientRecordLimit: CLIENT_RECORD_LIMIT,\n finOnIdle: false,\n authorize: undefined,\n clients: new Map(),\n conns: new Set(),\n pendingConns: new Set(),\n pendingOps: [],\n pendingApplied: new Map(),\n pendingCmds: new Map(),\n idleWire: true,\n finished: null,\n disposed: false,\n flushScheduled: false,\n heartbeatTimer: null,\n stateHost: null,\n commandsHost: null,\n current: null,\n post: createMacrotaskPoster(() => {\n host.flushScheduled = false;\n flush(host);\n }),\n connect: (clientId, socket, connectOptions) =>\n connect(host, clientId, socket, connectOptions),\n finish: (fin) => finish(host, fin),\n stream: (request) => serveStream(host, request),\n frames: (request) => serveFrames(host, request),\n };\n return host;\n });\n setHeartbeatMs(h, options?.heartbeatIntervalMs ?? 15_000);\n h.wsInitTimeoutMs = options?.wsInitTimeoutMs ?? 5_000;\n h.clientRecordLimit = options?.clientRecordLimit ?? CLIENT_RECORD_LIMIT;\n h.finOnIdle = options?.finOnIdle ?? false;\n h.authorize = options?.authorize;\n const value = useResource(transport) as Statewire<unknown>;\n attach(h, value);\n useEffect(() => {\n attach(h, value);\n });\n useEffect(() => {\n resume(h);\n return () => suspend(h);\n }, [h]);\n return h;\n};\n\n/**\n * Transport-agnostic WS binding over a statewire/host transport:\n * feed it sockets (anything with `send`/`close`) and raw text frames, and it\n * speaks the Statewire packet protocol — snapshot-first hello with `syn`,\n * statement-lane client frames under one admission law, `{cmd}` answer\n * arrays fanned out to every attach of a client id, idle edges, and `fin` on\n * finish.\n */\nexport const StatewireSocketHost = (\n transport: ResourceElement<Statewire>,\n options?: StatewireHostInternal.SocketHostOptions,\n): StatewireHostInternal.SocketHost => {\n const SocketHostRoot = () => useSocketHost(transport, options);\n const root = createTapRoot(SocketHostRoot);\n let disposed = false;\n return {\n connect: (clientId, socket, connectOptions) =>\n flushTapSync(() =>\n root.getValue().connect(clientId, socket, connectOptions),\n ),\n stream: (request) => flushTapSync(() => root.getValue().stream(request)),\n frames: (request) => flushTapSync(() => root.getValue().frames(request)),\n finish: (fin) => flushTapSync(() => root.getValue().finish(fin)),\n dispose: () => {\n if (disposed) return;\n disposed = true;\n flushTapSync(() => root.getValue().finish({ reason: \"evicted\" }));\n root.unmount();\n },\n };\n};\n"],"mappings":"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"}
@@ -12,9 +12,15 @@ declare namespace StatewireHostInternal {
12
12
  message: (data: string) => void;
13
13
  close: () => void;
14
14
  };
15
+ type SocketConnectOptions = {
16
+ /** The adapter restored this socket from an already-authorized session. */
17
+ authorized?: boolean;
18
+ /** Persist authorization before the first snapshot is released. */
19
+ onAuthorized?: () => void;
20
+ };
15
21
  type SocketHost = {
16
22
  /** Null means refused: the socket was told (fin and/or close) and is dead. */
17
- connect: (clientId: string, socket: Socket) => SocketConnection | null;
23
+ connect: (clientId: string, socket: Socket, options?: SocketConnectOptions) => SocketConnection | null;
18
24
  stream: (request: Request) => Promise<Response>;
19
25
  frames: (request: Request) => Promise<Response>;
20
26
  finish: (fin: StatewireHost.Fin) => void;
@@ -24,6 +30,8 @@ declare namespace StatewireHostInternal {
24
30
  authorize?: (ctx: {
25
31
  headers: Record<string, string>;
26
32
  }) => void | Promise<void>;
33
+ /** Time allowed to complete WebSocket initialization and authorization. */
34
+ wsInitTimeoutMs?: number;
27
35
  heartbeatIntervalMs?: number;
28
36
  /** LRU cap on stored client records; live or in-flight records are exempt. */
29
37
  clientRecordLimit?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"host-internal.d.ts","names":[],"sources":["../src/host-internal.ts"],"mappings":";;;;kBAIiB;OACH;IACV,OAAO;IACP,QAAQ,eAAe;;OAGb;aACD;IACT,UAAU;IACV;;OAGU;;IAEV,UAAU,kBAAkB,QAAQ,WAAW;IAC/C,SAAS,SAAS,YAAY,QAAQ;IACtC,SAAS,SAAS,YAAY,QAAQ;IACtC,SAAS,KAAK,cAAc;IAC5B;;OAGU;IACV,aAAa;MACX,SAAS;iBACE;IACb;;IAEA;;IAEA;;OAGU,MAAM,cAAc"}
1
+ {"version":3,"file":"host-internal.d.ts","names":[],"sources":["../src/host-internal.ts"],"mappings":";;;;kBAIiB;OACH;IACV,OAAO;IACP,QAAQ,eAAe;;OAGb;aACD;IACT,UAAU;IACV;;OAGU;;IAEV;;IAEA;;OAGU;;IAEV,UACE,kBACA,QAAQ,QACR,UAAU,yBACP;IACL,SAAS,SAAS,YAAY,QAAQ;IACtC,SAAS,SAAS,YAAY,QAAQ;IACtC,SAAS,KAAK,cAAc;IAC5B;;OAGU;IACV,aAAa;MACX,SAAS;iBACE;;IAEb;IACA;;IAEA;;IAEA;;OAGU,MAAM,cAAc"}
@@ -58,26 +58,27 @@ declare namespace StatewireClient {
58
58
  /** Removes the entry. */
59
59
  discardFailed: (entry: FailedCommand) => void;
60
60
  };
61
+ /** `cause`/`nextRetryAt`/`lastError` are present only while waiting out the backoff timer; a dial in flight carries `attempt` alone. */
61
62
  type ConnectionState = {
62
- status: "connecting";
63
- } | {
64
- status: "live";
65
- } | {
66
- status: "idle";
63
+ status: "disconnected";
64
+ reason: "deferred" | "idle" | "gone";
65
+ message?: string;
66
+ payload?: unknown;
67
67
  } | {
68
- status: "reconnecting";
69
- cause: "dropped" | "evicted" | "error" | "unauthorized";
68
+ status: "connecting";
69
+ /** 0 = the episode's first dial, >0 = retry. */
70
70
  attempt: number;
71
- nextRetryAt: number;
71
+ cause?: "dropped" | "evicted" | "error" | "unauthorized";
72
+ nextRetryAt?: number;
72
73
  lastError?: string;
73
74
  message?: string;
74
75
  } | {
75
- status: "gone";
76
- message?: string;
77
- payload?: unknown;
76
+ status: "connected";
78
77
  };
79
78
  type Connection = ConnectionState & {
80
79
  reconnect: () => void;
80
+ /** True while retrying (`connecting` with `attempt > 0`) or parked `gone`. */
81
+ degraded: boolean;
81
82
  };
82
83
  type ConnectionStatus = Connection["status"];
83
84
  /**
@@ -192,6 +193,8 @@ declare namespace StatewireClient {
192
193
  type SSEOptions = {
193
194
  sessionStore?: SessionStorage | undefined;
194
195
  url: string;
196
+ /** The session does not exist on the server yet: the first attach waits for the first command send (or an explicit `reconnect()`). */
197
+ isNew?: boolean;
195
198
  headers?: HeadersOption;
196
199
  fetch?: typeof globalThis.fetch;
197
200
  onSessionLost?: OnSessionLost;
@@ -202,6 +205,8 @@ declare namespace StatewireClient {
202
205
  type WSOptions = {
203
206
  sessionStore?: SessionStorage | undefined;
204
207
  url: string;
208
+ /** The session does not exist on the server yet: the first attach waits for the first command send (or an explicit `reconnect()`). */
209
+ isNew?: boolean;
205
210
  headers?: HeadersOption;
206
211
  protocols?: string | string[];
207
212
  query?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
@@ -1 +1 @@
1
- {"version":3,"file":"statewire.d.ts","names":[],"sources":["../src/statewire.ts"],"mappings":";;;;cAgCa,eACX,QACA,kBAAkB,UAAU,WAAW,UAAU,UAEjD,SAAS,gBAAgB,QAAQ,QAAQ,eACxC,gBAAgB,QAAQ,QAAQ;cA6DtB,oBACX,QACA,kBAAkB,UAAU,WAAW,UAAU,UAEjD,SAAS,gBAAgB,QAAQ,QAAQ,eACxC,gBAAgB,gBAAgB,QAAQ,QAAQ;cAGtC,gBACX,QACA,kBAAkB,UAAU,WAAW,UAAU;mBAEhC;UACT;EAEI,YAAA,SAAS,gBAAgB,QAAQ,QAAQ;MAKjD,SAAS;MAIT,cAAc,gBAAgB;MAI9B,YAAY,UAAU,cAAc;MAIpC;EAIJ,WAAW,OAAO;MAId,mBAAmB,gBAAgB;EAIvC,YAAY,OAAO,gBAAgB,gBAAgB;EAInD,cAAc,OAAO,gBAAgB;EAIrC,UAAU;EAIV;;kBAOe;OACH,QACV,QACA,kBAAkB,UAAU,WAAW,UAAU;IAEjD,WAAW,gBAAgB,UAAU,QAAQ;;IAE7C;MACM,UAAU,gBAAgB;;;IAGhC,eAAe;IACf,aAAa,WAAW,YAAY,SAAS;IAC7C,cAAc,YAAY,YAAY;IACtC,iBACE,OAAO,YAAY,SACnB;MAAO,SAAS,UAAU;;IAE5B,mBACE,QAAQ,UAAU,cAAc,YAChC;MAAO,OAAO,YAAY;;IAE5B,sBAAsB,YAAY;;IAElC,kBACE,OAAO,YAAY,SACnB,OAAO;;OAIC,QACV,QACA,kBAAkB,UAAU,WAAW,UAAU;;IAGjD,OAAO;;IAEP,gBAAgB;IAChB,YAAY;IACZ,UAAU,UAAU,cAAc;;IAElC;;IAEA,aAAa,OAAO;;IAEpB,iBAAiB;;IAEjB,cAAc,OAAO,kBAAkB;;IAEvC,gBAAgB,OAAO;;OAGb;IACN;;IACA;;IACA;;IAEA;IACA;IACA;IACA;IACA;IACA;;IAEA;IAAgB;IAAkB;;OAC5B,aAAa;IAAoB;;OACjC,mBAAmB;;;;;OAMnB,WACV,QACA,kBAAkB,UAAU,WAAW,UAAU,aAEjD,OAAO,QACP,SAAS,UAAU,QAAQ,YAC3B,KAAK;OAGK;IACV;IACA;IACA;;;;;;;OAQU,YAAY,WAAW,OAAO;;;;;;;;;;;;;OAc9B;IAEN;IACA;IACA;IACA;IACA;;IAEA;IAAgB;IAAiB;;IACjC;IAAiB;;IACjB;IAAiB;;IAEjB;IACA;IACA;;IAGA;IACA;;;OAIM,iBACV,SAAS;IACP;IACA;IACA;IACA;IACA;;;OAKQ;aACD;aACA;aACA;aACA,SAAS;aACT;aACA;;;OAIC;IACV;IACA;IACA;IACA;;;OAIU;IACV;IACA;IACA;IACA,mBAAmB;;IAEnB,oBAAoB;;IAEpB,kBAAkB;;;OAIR;IACV;IACA,cAAc;IACd;IACA;IACA;IACA;;;OAIU;IACV,YAAY;IACZ,OAAO,QAAQ;;IAEf,QAAQ,GAAG,UAAU,IAAI,QAAQ,OAAO,QAAQ;;IAEhD,aAAa;;;OAIH,gBACR,gBACE;IAAO;QAAyB,cAAc,QAAQ;OAEhD;IACV,eAAe;IACf;IACA,UAAU;IACV,eAAe,WAAW;IAC1B,gBAAgB;IAChB,YAAY,YAAY;;IAExB;;OAGU;IACV,eAAe;IACf;IACA,UAAU;IACV;IACA,QACI,gCACO,yBAAyB,QAAQ;IAC5C,iBAAiB,aAAa,kCAAkC;IAChE,gBAAgB;IAChB,YAAY,YAAY;;IAExB"}
1
+ {"version":3,"file":"statewire.d.ts","names":[],"sources":["../src/statewire.ts"],"mappings":";;;;cAgCa,eACX,QACA,kBAAkB,UAAU,WAAW,UAAU,UAEjD,SAAS,gBAAgB,QAAQ,QAAQ,eACxC,gBAAgB,QAAQ,QAAQ;cA6DtB,oBACX,QACA,kBAAkB,UAAU,WAAW,UAAU,UAEjD,SAAS,gBAAgB,QAAQ,QAAQ,eACxC,gBAAgB,gBAAgB,QAAQ,QAAQ;cAGtC,gBACX,QACA,kBAAkB,UAAU,WAAW,UAAU;mBAEhC;UACT;EAEI,YAAA,SAAS,gBAAgB,QAAQ,QAAQ;MAKjD,SAAS;MAIT,cAAc,gBAAgB;MAI9B,YAAY,UAAU,cAAc;MAIpC;EAIJ,WAAW,OAAO;MAId,mBAAmB,gBAAgB;EAIvC,YAAY,OAAO,gBAAgB,gBAAgB;EAInD,cAAc,OAAO,gBAAgB;EAIrC,UAAU;EAIV;;kBAOe;OACH,QACV,QACA,kBAAkB,UAAU,WAAW,UAAU;IAEjD,WAAW,gBAAgB,UAAU,QAAQ;;IAE7C;MACM,UAAU,gBAAgB;;;IAGhC,eAAe;IACf,aAAa,WAAW,YAAY,SAAS;IAC7C,cAAc,YAAY,YAAY;IACtC,iBACE,OAAO,YAAY,SACnB;MAAO,SAAS,UAAU;;IAE5B,mBACE,QAAQ,UAAU,cAAc,YAChC;MAAO,OAAO,YAAY;;IAE5B,sBAAsB,YAAY;;IAElC,kBACE,OAAO,YAAY,SACnB,OAAO;;OAIC,QACV,QACA,kBAAkB,UAAU,WAAW,UAAU;;IAGjD,OAAO;;IAEP,gBAAgB;IAChB,YAAY;IACZ,UAAU,UAAU,cAAc;;IAElC;;IAEA,aAAa,OAAO;;IAEpB,iBAAiB;;IAEjB,cAAc,OAAO,kBAAkB;;IAEvC,gBAAgB,OAAO;;;OAIb;IAEN;IACA;IACA;IACA;;IAGA;;IAEA;IACA;IACA;IACA;IACA;;IAEA;;OACM,aAAa;IACvB;;IAEA;;OAEU,mBAAmB;;;;;OAMnB,WACV,QACA,kBAAkB,UAAU,WAAW,UAAU,aAEjD,OAAO,QACP,SAAS,UAAU,QAAQ,YAC3B,KAAK;OAGK;IACV;IACA;IACA;;;;;;;OAQU,YAAY,WAAW,OAAO;;;;;;;;;;;;;OAc9B;IAEN;IACA;IACA;IACA;IACA;;IAEA;IAAgB;IAAiB;;IACjC;IAAiB;;IACjB;IAAiB;;IAEjB;IACA;IACA;;IAGA;IACA;;;OAIM,iBACV,SAAS;IACP;IACA;IACA;IACA;IACA;;;OAKQ;aACD;aACA;aACA;aACA,SAAS;aACT;aACA;;;OAIC;IACV;IACA;IACA;IACA;;;OAIU;IACV;IACA;IACA;IACA,mBAAmB;;IAEnB,oBAAoB;;IAEpB,kBAAkB;;;OAIR;IACV;IACA,cAAc;IACd;IACA;IACA;IACA;;;OAIU;IACV,YAAY;IACZ,OAAO,QAAQ;;IAEf,QAAQ,GAAG,UAAU,IAAI,QAAQ,OAAO,QAAQ;;IAEhD,aAAa;;;OAIH,gBACR,gBACE;IAAO;QAAyB,cAAc,QAAQ;OAEhD;IACV,eAAe;IACf;;IAEA;IACA,UAAU;IACV,eAAe,WAAW;IAC1B,gBAAgB;IAChB,YAAY,YAAY;;IAExB;;OAGU;IACV,eAAe;IACf;;IAEA;IACA,UAAU;IACV;IACA,QACI,gCACO,yBAAyB,QAAQ;IAC5C,iBAAiB,aAAa,kCAAkC;IAChE,gBAAgB;IAChB,YAAY,YAAY;;IAExB"}
package/dist/statewire.js CHANGED
@@ -1,4 +1,4 @@
1
- import { LIVE_CONNECTION, useStatewireCore } from "./client/core.js";
1
+ import { CONNECTED_CONNECTION, useStatewireCore } from "./client/core.js";
2
2
  import { SessionStorageContext } from "./client/sessionStore.js";
3
3
  import { useMemo, useRef, useState, useSyncExternalStore } from "@assistant-ui/tap/react-shim";
4
4
  import { createTapRoot, flushTapSync, resource, useContextProvider, useResource, useResources, withKey } from "@assistant-ui/tap";
@@ -18,7 +18,7 @@ const useStatewire = (options) => {
18
18
  const state = useSyncExternalStore(subscribe, core.getState, core.getState);
19
19
  const isBusy = useSyncExternalStore(subscribe, core.getBusy, core.getBusy);
20
20
  const failed = useSyncExternalStore(subscribe, core.getFailed, core.getFailed);
21
- const connection = value.connection ?? LIVE_CONNECTION;
21
+ const connection = value.connection ?? CONNECTED_CONNECTION;
22
22
  return useMemo(() => {
23
23
  const failures = () => {
24
24
  if (!value.failures) throw new Error("statewire: this transport has no failed-send lane");