statewire 0.17.0 → 0.17.2

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.
@@ -1,5 +1,6 @@
1
+ import { reviveDocumentValue } from "../document.js";
1
2
  import { negotiationHeaders, parseNegotiation, validateSelection } from "../wire/protocol.js";
2
- import { reviveOps, reviveValue } from "../wire/meta.js";
3
+ import { reviveOps } from "../wire/meta.js";
3
4
  import { backoff, timing } from "./timing.js";
4
5
  import { useEffect, useRef, useState } from "@assistant-ui/tap/react-shim";
5
6
  import { flushTapSync } from "@assistant-ui/tap";
@@ -192,7 +193,7 @@ const deliverEnvelope = (c, env) => {
192
193
  const settleFin = (c, fin) => {
193
194
  const finish = fin.meta === void 0 ? fin : {
194
195
  ...fin,
195
- payload: reviveValue(fin.payload, fin.meta)
196
+ payload: reviveDocumentValue(fin.payload, fin.meta)
196
197
  };
197
198
  releaseHeld(c);
198
199
  c.retryAt = Date.now() + (finish.retry ?? 0);
@@ -1 +1 @@
1
- {"version":3,"file":"connection.js","names":["negotiationHeaders","validateSelection","parseNegotiation","StatewireProtocol","useEffect","useRef","useState","flushTapSync","reviveOps","reviveValue","backoff","timing","ConnectionState","RemoteLink","StatewireFrame","StatewireRemoteProps","StatewireSubmitResult","StatewireClient","StatewireHost","Episode","cause","message","code","TERMINAL","const","StatewireCmd","seq","type","payload","meta","dur","StatewireSyn","version","protocols","Selection","ctxSeq","record","id","idle","retry","StatewireEnvelope","ops","cmd","next","syn","fin","Fin","Gate","latched","wake","newGate","undefined","takeGate","g","was","waitGate","timeoutMs","Promise","resolve","timer","setTimeout","clearTimeout","openGate","AttemptOutcome","Conn","negotiation","Options","connection","Connection","parked","lease","attempt","authDenials","authStale","liveAt","retryAt","error","ConnectionError","episode","awaitingHello","held","gate","abort","AbortController","lifetime","ctx","onError","onChange","attemptOnce","notify","reconnect","degradedOf","state","status","reason","sameState","a","b","nextRetryAt","lastError","setStatus","c","degraded","protocolError","Error","isObject","value","Record","Array","isArray","isNonnegativeSafeInteger","Number","isSafeInteger","isPositiveSafeInteger","validateOptionalString","field","validateSynScalars","validateRefusalSyn","validateCmd","validateFin","validateEnvelope","entry","releaseHeld","length","onCmds","cmdsOf","env","snapshotOf","helloSynOf","handleHello","onHello","onIdle","Date","now","warnedUnknownSynFact","warnUnknownSynFact","console","warn","deliverSyn","onRefusal","Object","keys","deliverEnvelope","onOps","cmds","push","settleFin","finish","denial","terminal","report","assign","onFinish","handleEnvelope","dialing","scheduleRetry","failure","immediate","backoffResetMs","delay","Math","max","reconnectConn","run","alive","outcome","signal","aborted","SyntaxError","test","onDetach","includes","unsupportedVersion","resolveHeaders","headers","HeadersOption","staleAuth","Headers","attachFrame","resolved","name","entries","has","set","lanes","takeAttachLanes","body","JSON","stringify","fromEntries","useLink","props","url","isNew","send","frame","latest","current","setConnection","conn","link","protocol","wireVersion","applicationProtocols","classify","timeout","AbortSignal"],"sources":["../../src/client/connection.ts"],"sourcesContent":["import {\n negotiationHeaders,\n validateSelection,\n parseNegotiation,\n} from \"../wire/protocol\";\nimport type { StatewireProtocol } from \"../wire/protocol\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { flushTapSync } from \"@assistant-ui/tap\";\nimport { reviveOps, reviveValue } from \"../wire/meta\";\nimport { backoff, timing } from \"./timing\";\nimport type {\n ConnectionState,\n RemoteLink,\n StatewireFrame,\n StatewireRemoteProps,\n StatewireSubmitResult,\n} from \"../transports/sse\";\nimport type { StatewireClient } from \"../statewire\";\nimport type { StatewireHost } from \"../host\";\n\nexport type Episode = {\n cause: \"dropped\" | \"reconnect\" | \"error\" | \"unauthorized\";\n message?: string;\n code?: string;\n};\n\n/** The terminal cmd verdict types; \"applied\" is the sole non-terminal type. */\nexport const TERMINAL = [\n \"result\",\n \"rejected\",\n \"failed\",\n \"crashed\",\n \"expired\",\n] as const;\n\nexport type StatewireCmd = {\n seq: number;\n type?: \"applied\" | (typeof TERMINAL)[number];\n code?: string;\n message?: string;\n payload?: unknown;\n meta?: unknown;\n /** Cumulative: resending through this seq will never be needed. */\n dur?: boolean;\n};\n\nexport type StatewireSyn = {\n version?: string;\n protocols?: StatewireProtocol.Selection[\"protocols\"];\n seq?: number;\n ctxSeq?: number;\n record?: \"ephemeral\";\n id?: string;\n idle?: boolean;\n retry?: number;\n};\n\nexport type StatewireEnvelope = {\n ops?: unknown[];\n cmd?: StatewireCmd[];\n next?: true;\n idle?: boolean;\n syn?: StatewireSyn;\n fin?: StatewireHost.Fin;\n};\n\nexport type Gate = { latched: boolean; wake: (() => void) | undefined };\n\nconst newGate = (): Gate => ({ latched: false, wake: undefined });\n\nconst takeGate = (g: Gate) => {\n const was = g.latched;\n g.latched = false;\n return was;\n};\n\nconst waitGate = (g: Gate, timeoutMs?: number) => {\n if (g.latched) {\n g.latched = false;\n return Promise.resolve();\n }\n return new Promise<void>((resolve) => {\n const timer =\n timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n g.wake = undefined;\n resolve();\n }, timeoutMs);\n g.wake = () => {\n clearTimeout(timer);\n g.wake = undefined;\n resolve();\n };\n });\n};\n\nconst openGate = (g: Gate) => {\n if (g.wake) g.wake();\n else g.latched = true;\n};\n\nexport type AttemptOutcome = \"stop\" | \"reattach\" | \"ended\" | \"idle\";\n\nexport type Conn = {\n negotiation?: StatewireProtocol.Options;\n connection: StatewireClient.Connection;\n parked: boolean;\n lease: string | null;\n attempt: number;\n authDenials: number;\n authStale: boolean;\n liveAt: number | null;\n retryAt: number;\n error: StatewireClient.ConnectionError | undefined;\n episode: Episode | null;\n awaitingHello: boolean;\n held: StatewireCmd[];\n gate: Gate;\n abort: AbortController | null;\n lifetime: AbortController | null;\n ctx: StatewireRemoteProps;\n onError: (error: StatewireClient.ConnectionError) => void;\n onChange: (connection: StatewireClient.Connection) => void;\n attemptOnce: (abort: AbortController) => Promise<AttemptOutcome>;\n notify: (connection: StatewireClient.Connection) => void;\n reconnect: () => void;\n};\n\nexport const degradedOf = (state: ConnectionState): boolean =>\n (state.status === \"connecting\" && state.attempt > 0) ||\n (state.status === \"disconnected\" &&\n state.reason !== \"idle\" &&\n state.reason !== \"deferred\");\n\nconst sameState = (a: ConnectionState, b: ConnectionState): boolean => {\n if (a.status !== b.status) return false;\n if (a.status === \"connecting\" && b.status === \"connecting\") {\n return (\n a.attempt === b.attempt &&\n a.cause === b.cause &&\n a.code === b.code &&\n a.nextRetryAt === b.nextRetryAt &&\n a.lastError === b.lastError\n );\n }\n if (a.status === \"disconnected\" && b.status === \"disconnected\") {\n return a.reason === b.reason;\n }\n return true;\n};\n\nconst setStatus = (c: Conn, next: ConnectionState) => {\n if (sameState(next, c.connection) && c.connection.error === c.error) return;\n c.connection = {\n ...next,\n ...(c.error === undefined ? {} : { error: c.error }),\n reconnect: c.reconnect,\n degraded: degradedOf(next),\n };\n c.notify(c.connection);\n c.onChange(c.connection);\n};\n\nconst protocolError = (message: string): never => {\n throw new Error(`statewire: protocol error: ${message}`);\n};\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isNonnegativeSafeInteger = (value: unknown): value is number =>\n Number.isSafeInteger(value) && (value as number) >= 0;\n\nconst isPositiveSafeInteger = (value: unknown): value is number =>\n Number.isSafeInteger(value) && (value as number) > 0;\n\nconst validateOptionalString = (value: unknown, field: string): void => {\n if (value !== undefined && typeof value !== \"string\") {\n protocolError(`${field} must be a string`);\n }\n};\n\nconst validateSynScalars = (syn: Record<string, unknown>) => {\n if (syn[\"seq\"] !== undefined && !isNonnegativeSafeInteger(syn[\"seq\"])) {\n protocolError(\"syn.seq must be a nonnegative safe integer\");\n }\n if (syn[\"ctxSeq\"] !== undefined && !isNonnegativeSafeInteger(syn[\"ctxSeq\"])) {\n protocolError(\"syn.ctxSeq must be a nonnegative safe integer\");\n }\n if (syn[\"retry\"] !== undefined && !isNonnegativeSafeInteger(syn[\"retry\"])) {\n protocolError(\"syn.retry must be a nonnegative safe integer\");\n }\n validateOptionalString(syn[\"id\"], \"syn.id\");\n if (syn[\"idle\"] !== undefined && typeof syn[\"idle\"] !== \"boolean\") {\n protocolError(\"syn.idle must be a boolean\");\n }\n validateOptionalString(syn[\"record\"], \"syn.record\");\n};\n\nexport const validateRefusalSyn = (value: unknown): StatewireSyn => {\n if (!isObject(value)) return protocolError(\"syn must be an object\");\n validateSynScalars(value);\n if (\n value[\"id\"] !== undefined ||\n value[\"idle\"] !== undefined ||\n value[\"record\"] !== undefined\n ) {\n protocolError(\"invalid refusal syn\");\n }\n if (\n value[\"seq\"] === undefined &&\n value[\"ctxSeq\"] === undefined &&\n value[\"retry\"] === undefined\n ) {\n protocolError(\"refusal syn has no watermarks or retry\");\n }\n return value as StatewireSyn;\n};\n\nconst validateCmd = (value: unknown): value is StatewireCmd => {\n if (!isObject(value)) return protocolError(\"cmd entry must be an object\");\n if (!isPositiveSafeInteger(value[\"seq\"])) {\n protocolError(\"cmd.seq must be a positive safe integer\");\n }\n validateOptionalString(value[\"type\"], \"cmd.type\");\n validateOptionalString(value[\"code\"], \"cmd.code\");\n validateOptionalString(value[\"message\"], \"cmd.message\");\n if (value[\"dur\"] !== undefined && value[\"dur\"] !== true) {\n protocolError(\"cmd.dur must be true\");\n }\n return true;\n};\n\nconst validateFin = (value: unknown): value is StatewireHost.Fin => {\n if (!isObject(value)) return protocolError(\"fin must be an object\");\n if (typeof value[\"reason\"] !== \"string\") {\n protocolError(\"fin.reason must be a string\");\n }\n validateOptionalString(value[\"message\"], \"fin.message\");\n validateOptionalString(value[\"code\"], \"fin.code\");\n if (\n value[\"status\"] !== undefined &&\n !isNonnegativeSafeInteger(value[\"status\"])\n )\n protocolError(\"fin.status must be a nonnegative safe integer\");\n if (value[\"retry\"] !== undefined && !isNonnegativeSafeInteger(value[\"retry\"]))\n protocolError(\"fin.retry must be a nonnegative safe integer\");\n return true;\n};\n\nconst validateEnvelope = (value: unknown): StatewireEnvelope => {\n if (!isObject(value)) return protocolError(\"packet must be an object\");\n if (value[\"ops\"] !== undefined && !Array.isArray(value[\"ops\"])) {\n protocolError(\"ops must be an array\");\n }\n if (value[\"cmd\"] !== undefined) {\n const cmd = value[\"cmd\"];\n if (!Array.isArray(cmd)) return protocolError(\"cmd must be an array\");\n for (const entry of cmd) validateCmd(entry);\n }\n if (value[\"idle\"] !== undefined && typeof value[\"idle\"] !== \"boolean\") {\n protocolError(\"idle must be a boolean\");\n }\n if (value[\"next\"] !== undefined) {\n if (value[\"next\"] !== true) protocolError(\"next must be true\");\n if (\n value[\"cmd\"] === undefined ||\n value[\"ops\"] !== undefined ||\n value[\"fin\"] !== undefined\n ) {\n protocolError(\"next must ride a cmd-only packet\");\n }\n }\n if (value[\"fin\"] !== undefined) validateFin(value[\"fin\"]);\n return value as StatewireEnvelope;\n};\n\n// A hold's release delivers, never settles: fin and bare close both drain it.\nconst releaseHeld = (c: Conn) => {\n if (c.held.length === 0) return;\n const held = c.held;\n c.held = [];\n c.ctx.onCmds(held);\n};\n\nconst cmdsOf = (env: StatewireEnvelope): StatewireCmd[] => {\n if (env.cmd === undefined) return [];\n return env.cmd;\n};\n\nconst snapshotOf = (env: StatewireEnvelope): unknown[] => {\n const ops = env.ops;\n if (ops === undefined) return protocolError(\"hello missing snapshot\");\n return reviveOps(ops);\n};\n\nconst helloSynOf = (env: StatewireEnvelope): StatewireSyn => {\n if (!isObject(env.syn)) return protocolError(\"expected hello\");\n validateSynScalars(env.syn);\n if (env.syn[\"retry\"] !== undefined) {\n protocolError(\"hello syn cannot carry retry\");\n }\n return env.syn as StatewireSyn;\n};\n\nconst handleHello = (c: Conn, env: StatewireEnvelope) => {\n const syn = helloSynOf(env);\n if (c.negotiation !== undefined) validateSelection(syn, c.negotiation);\n const ops = snapshotOf(env);\n c.ctx.onHello({\n ops,\n syn,\n });\n c.ctx.onIdle(syn.idle ?? false);\n c.awaitingHello = false;\n c.error = undefined;\n c.liveAt = Date.now();\n c.authDenials = 0;\n c.episode = null;\n setStatus(c, { status: \"connected\" });\n};\n\nlet warnedUnknownSynFact = false;\n\nconst warnUnknownSynFact = () => {\n if (warnedUnknownSynFact) return;\n warnedUnknownSynFact = true;\n console.warn(\"statewire: ignoring unknown syn fact\");\n};\n\nconst deliverSyn = (c: Conn, value: unknown) => {\n if (!isObject(value)) return protocolError(\"syn must be an object\");\n validateSynScalars(value);\n if (\n value[\"version\"] !== undefined ||\n value[\"protocols\"] !== undefined ||\n value[\"record\"] !== undefined ||\n value[\"idle\"] !== undefined\n ) {\n protocolError(\"invalid mid-stream syn\");\n }\n if (\n value[\"seq\"] !== undefined ||\n value[\"ctxSeq\"] !== undefined ||\n value[\"retry\"] !== undefined\n ) {\n c.ctx.onRefusal(validateRefusalSyn(value));\n return;\n }\n if (value[\"id\"] !== undefined) return;\n if (Object.keys(value).length === 0) {\n protocolError(\"invalid mid-stream syn\");\n }\n warnUnknownSynFact();\n};\n\nconst deliverEnvelope = (c: Conn, env: StatewireEnvelope) => {\n if (env.syn !== undefined) deliverSyn(c, env.syn);\n if (env.ops !== undefined) {\n const held = c.held;\n c.held = [];\n c.ctx.onOps({\n ops: reviveOps(env.ops),\n cmds: [...held, ...cmdsOf(env)],\n });\n } else if (env.cmd !== undefined) {\n const cmds = cmdsOf(env);\n if (env.next === true) c.held.push(...cmds);\n else c.ctx.onCmds(cmds);\n }\n if (typeof env.idle === \"boolean\") c.ctx.onIdle(env.idle);\n};\n\nexport const settleFin = (c: Conn, fin: StatewireHost.Fin): AttemptOutcome => {\n const finish =\n fin.meta === undefined\n ? fin\n : { ...fin, payload: reviveValue(fin.payload, fin.meta) };\n releaseHeld(c);\n c.retryAt = Date.now() + (finish.retry ?? 0);\n if (finish.reason === \"idle\") {\n c.ctx.onIdle(true);\n c.attempt = 0;\n c.episode = null;\n c.error = undefined;\n setStatus(c, { status: \"disconnected\", reason: \"idle\" });\n return \"idle\";\n }\n const denial = finish.reason === \"unauthorized\";\n const terminal =\n finish.reason === \"gone\" ||\n finish.reason === \"forbidden\" ||\n finish.reason === \"protocol-error\" ||\n (denial && c.authDenials > 0);\n if (denial) {\n c.authDenials += 1;\n c.authStale = true;\n }\n const report =\n finish.reason !== \"reconnect\" &&\n finish.reason !== \"gone\" &&\n (!denial || terminal);\n c.error = report\n ? Object.assign(new Error(finish.message ?? finish.reason), { fin: finish })\n : undefined;\n if (c.error) c.onError(c.error);\n if (!terminal) {\n c.episode = {\n cause:\n finish.reason === \"reconnect\"\n ? \"reconnect\"\n : denial\n ? \"unauthorized\"\n : \"error\",\n ...(finish.message !== undefined && { message: finish.message }),\n ...(finish.code !== undefined && { code: finish.code }),\n };\n if (denial) openGate(c.gate);\n return \"reattach\";\n }\n c.ctx.onFinish(finish);\n setStatus(c, {\n status: \"disconnected\",\n reason: denial\n ? \"unauthorized\"\n : finish.reason === \"forbidden\"\n ? \"forbidden\"\n : finish.reason === \"protocol-error\"\n ? \"protocol-error\"\n : \"gone\",\n ...(finish.message !== undefined && { message: finish.message }),\n ...(finish.payload !== undefined && { payload: finish.payload }),\n });\n return \"stop\";\n};\n\nexport const handleEnvelope = (\n c: Conn,\n value: unknown,\n): AttemptOutcome | null => {\n const env = validateEnvelope(value);\n if (c.awaitingHello) {\n if (env.fin !== undefined) return settleFin(c, env.fin);\n handleHello(c, env);\n return null;\n }\n deliverEnvelope(c, env);\n if (env.fin !== undefined) return settleFin(c, env.fin);\n if (c.connection.status !== \"connected\") {\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"connected\" });\n }\n return null;\n};\n\nconst dialing = (c: Conn) =>\n setStatus(c, { status: \"connecting\", attempt: c.attempt });\n\nconst scheduleRetry = (\n c: Conn,\n failure: string | undefined,\n immediate: boolean,\n) => {\n if (c.liveAt !== null && Date.now() - c.liveAt >= timing.backoffResetMs) {\n c.attempt = 0;\n }\n c.liveAt = null;\n c.attempt += 1;\n c.episode ??= { cause: \"dropped\" };\n const delay = Math.max(\n immediate ? 0 : backoff(c.attempt),\n c.retryAt - Date.now(),\n );\n setStatus(c, {\n status: \"connecting\",\n attempt: c.attempt,\n ...c.episode,\n nextRetryAt: Date.now() + delay,\n ...(failure !== undefined && { lastError: failure }),\n });\n return delay;\n};\n\nconst reconnectConn = (c: Conn) => {\n if (!c.lifetime) return;\n if (c.connection.status === \"disconnected\") {\n // A reconnect out of a park starts a fresh episode: first dial, attempt 0.\n c.attempt = 0;\n c.authDenials = 0;\n c.episode = null;\n flushTapSync(() => dialing(c));\n }\n openGate(c.gate);\n c.abort?.abort();\n};\n\nconst run = async (c: Conn, lifetime: AbortController, gate: Gate) => {\n const alive = () => c.lifetime === lifetime;\n if (c.parked) {\n await waitGate(gate);\n if (!alive()) return;\n c.parked = false;\n }\n while (alive()) {\n if (c.retryAt > Date.now()) {\n await waitGate(gate, c.retryAt - Date.now());\n continue;\n }\n // The dial is in flight: attempt alone, no backoff fields.\n flushTapSync(() => dialing(c));\n const abort = new AbortController();\n c.abort = abort;\n c.awaitingHello = true;\n c.held = [];\n let outcome: AttemptOutcome | undefined;\n let failure: string | undefined;\n try {\n outcome = await c.attemptOnce(abort);\n } catch (error) {\n if (!abort.signal.aborted) {\n if (\n error instanceof SyntaxError ||\n (error instanceof Error &&\n /^(statewire: protocol error:|Statewire cannot apply)/.test(\n error.message,\n ))\n ) {\n outcome = flushTapSync(() =>\n settleFin(c, { reason: \"protocol-error\", message: error.message }),\n );\n } else if (c.authStale) {\n outcome = flushTapSync(() =>\n settleFin(c, {\n reason: \"unauthorized\",\n message:\n error instanceof Error\n ? error.message\n : \"credential refresh failed\",\n }),\n );\n }\n failure =\n error instanceof Error && error.message ? error.message : \"network\";\n }\n }\n abort.abort();\n if (!alive()) return;\n flushTapSync(() => {\n releaseHeld(c);\n c.ctx.onDetach();\n });\n if (!alive()) return;\n if (\n c.connection.status === \"disconnected\" &&\n ![\"deferred\", \"idle\"].includes(c.connection.reason)\n )\n outcome = \"stop\";\n if (outcome === \"stop\" || outcome === \"idle\") {\n await waitGate(gate);\n continue;\n }\n const immediate = takeGate(gate);\n const delay = flushTapSync(() => scheduleRetry(c, failure, immediate));\n if (delay === 0) continue;\n await waitGate(gate, delay);\n }\n};\n\nexport const unsupportedVersion = (c: Conn, version: string): AttemptOutcome =>\n flushTapSync(() =>\n handleEnvelope(c, {\n fin: {\n reason: \"protocol-error\",\n message: `unsupported protocol version: ${version || '\"\"'}`,\n },\n }),\n ) ?? \"stop\";\n\nexport const resolveHeaders = async (\n headers: StatewireClient.HeadersOption | undefined,\n staleAuth: boolean,\n): Promise<Headers> =>\n new Headers(\n typeof headers === \"function\" ? await headers({ staleAuth }) : headers,\n );\n\n// The stale flag clears only once the resolver returns: a throwing refresh keeps it for the next attempt.\nexport const attachFrame = async (\n c: Conn,\n headers: StatewireClient.HeadersOption | undefined,\n) => {\n const resolved = await resolveHeaders(headers, c.authStale);\n for (const [name, value] of Object.entries(\n negotiationHeaders(c.negotiation ?? {}),\n )) {\n if (!resolved.has(name)) resolved.set(name, value);\n }\n c.negotiation = parseNegotiation(resolved);\n c.authStale = false;\n const lanes = flushTapSync(() => c.ctx.takeAttachLanes());\n return {\n headers: resolved,\n body: JSON.stringify({\n headers: Object.fromEntries(resolved),\n ...(lanes ?? {}),\n }),\n };\n};\n\nexport const useLink = (\n props: StatewireProtocol.Options & {\n url: string;\n isNew?: boolean | undefined;\n onChange?: ((connection: StatewireClient.Connection) => void) | undefined;\n onError?: ((error: StatewireClient.ConnectionError) => void) | undefined;\n ctx: StatewireRemoteProps;\n attemptOnce: (c: Conn, abort: AbortController) => Promise<AttemptOutcome>;\n send: (c: Conn, frame: StatewireFrame) => Promise<StatewireSubmitResult>;\n },\n): RemoteLink => {\n const latest = useRef(props);\n latest.current = props;\n const [, setConnection] = useState<StatewireClient.Connection | null>(null);\n const [c] = useState((): Conn => {\n const conn: Conn = {\n parked: props.isNew ?? false,\n lease: null,\n attempt: 0,\n authDenials: 0,\n authStale: false,\n liveAt: null,\n retryAt: 0,\n error: undefined,\n episode: null,\n awaitingHello: true,\n held: [],\n abort: null,\n gate: newGate(),\n lifetime: null,\n get ctx() {\n return latest.current.ctx;\n },\n onError: (error) => latest.current.onError?.(error),\n onChange: (connection) => latest.current.onChange?.(connection),\n attemptOnce: (abort) => {\n conn.negotiation = latest.current;\n return latest.current.attemptOnce(conn, abort);\n },\n notify: setConnection,\n reconnect: () => reconnectConn(conn),\n connection: {\n ...((props.isNew ?? false)\n ? { status: \"disconnected\", reason: \"deferred\" }\n : { status: \"connecting\", attempt: 0 }),\n degraded: false,\n reconnect: () => conn.reconnect(),\n },\n };\n return conn;\n });\n const [link] = useState(\n (): RemoteLink => ({\n get connection() {\n return c.connection;\n },\n get parked() {\n return c.parked;\n },\n send: (frame) => latest.current.send(c, frame),\n }),\n );\n\n const negotiation = JSON.stringify([\n props.protocol,\n props.wireVersion,\n props.applicationProtocols,\n ]);\n useEffect(() => {\n c.lease = null;\n c.attempt = 0;\n c.authDenials = 0;\n c.authStale = false;\n c.liveAt = null;\n c.retryAt = 0;\n c.episode = null;\n setStatus(\n c,\n c.parked\n ? { status: \"disconnected\", reason: \"deferred\" }\n : { status: \"connecting\", attempt: 0 },\n );\n const lifetime = new AbortController();\n c.lifetime = lifetime;\n c.gate = newGate();\n void run(c, lifetime, c.gate);\n return () => {\n c.abort?.abort();\n lifetime.abort();\n if (c.lifetime === lifetime) c.lifetime = null;\n openGate(c.gate);\n };\n }, [c, props.url, negotiation]);\n\n return link;\n};\n\nexport const classify = (timeout: AbortSignal) =>\n new Error(timeout.aborted ? \"timeout\" : \"network\");\n"],"mappings":"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"}
1
+ {"version":3,"file":"connection.js","names":["negotiationHeaders","validateSelection","parseNegotiation","StatewireProtocol","useEffect","useRef","useState","flushTapSync","reviveOps","reviveValue","backoff","timing","ConnectionState","RemoteLink","StatewireFrame","StatewireRemoteProps","StatewireSubmitResult","StatewireClient","StatewireHost","Episode","cause","message","code","TERMINAL","const","StatewireCmd","seq","type","payload","meta","dur","StatewireSyn","version","protocols","Selection","ctxSeq","record","id","idle","retry","StatewireEnvelope","ops","cmd","next","syn","fin","Fin","Gate","latched","wake","newGate","undefined","takeGate","g","was","waitGate","timeoutMs","Promise","resolve","timer","setTimeout","clearTimeout","openGate","AttemptOutcome","Conn","negotiation","Options","connection","Connection","parked","lease","attempt","authDenials","authStale","liveAt","retryAt","error","ConnectionError","episode","awaitingHello","held","gate","abort","AbortController","lifetime","ctx","onError","onChange","attemptOnce","notify","reconnect","degradedOf","state","status","reason","sameState","a","b","nextRetryAt","lastError","setStatus","c","degraded","protocolError","Error","isObject","value","Record","Array","isArray","isNonnegativeSafeInteger","Number","isSafeInteger","isPositiveSafeInteger","validateOptionalString","field","validateSynScalars","validateRefusalSyn","validateCmd","validateFin","validateEnvelope","entry","releaseHeld","length","onCmds","cmdsOf","env","snapshotOf","helloSynOf","handleHello","onHello","onIdle","Date","now","warnedUnknownSynFact","warnUnknownSynFact","console","warn","deliverSyn","onRefusal","Object","keys","deliverEnvelope","onOps","cmds","push","settleFin","finish","denial","terminal","report","assign","onFinish","handleEnvelope","dialing","scheduleRetry","failure","immediate","backoffResetMs","delay","Math","max","reconnectConn","run","alive","outcome","signal","aborted","SyntaxError","test","onDetach","includes","unsupportedVersion","resolveHeaders","headers","HeadersOption","staleAuth","Headers","attachFrame","resolved","name","entries","has","set","lanes","takeAttachLanes","body","JSON","stringify","fromEntries","useLink","props","url","isNew","send","frame","latest","current","setConnection","conn","link","protocol","wireVersion","applicationProtocols","classify","timeout","AbortSignal"],"sources":["../../src/client/connection.ts"],"sourcesContent":["import {\n negotiationHeaders,\n validateSelection,\n parseNegotiation,\n} from \"../wire/protocol\";\nimport type { StatewireProtocol } from \"../wire/protocol\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { flushTapSync } from \"@assistant-ui/tap\";\nimport { reviveOps, reviveValue } from \"../wire/meta\";\nimport { backoff, timing } from \"./timing\";\nimport type {\n ConnectionState,\n RemoteLink,\n StatewireFrame,\n StatewireRemoteProps,\n StatewireSubmitResult,\n} from \"../transports/sse\";\nimport type { StatewireClient } from \"../statewire\";\nimport type { StatewireHost } from \"../host\";\n\nexport type Episode = {\n cause: \"dropped\" | \"reconnect\" | \"error\" | \"unauthorized\";\n message?: string;\n code?: string;\n};\n\n/** The terminal cmd verdict types; \"applied\" is the sole non-terminal type. */\nexport const TERMINAL = [\n \"result\",\n \"rejected\",\n \"failed\",\n \"crashed\",\n \"expired\",\n] as const;\n\nexport type StatewireCmd = {\n seq: number;\n type?: \"applied\" | (typeof TERMINAL)[number];\n code?: string;\n message?: string;\n payload?: unknown;\n meta?: unknown;\n /** Cumulative: resending through this seq will never be needed. */\n dur?: boolean;\n};\n\nexport type StatewireSyn = {\n version?: string;\n protocols?: StatewireProtocol.Selection[\"protocols\"];\n seq?: number;\n ctxSeq?: number;\n record?: \"ephemeral\";\n id?: string;\n idle?: boolean;\n retry?: number;\n};\n\nexport type StatewireEnvelope = {\n ops?: unknown[];\n cmd?: StatewireCmd[];\n next?: true;\n idle?: boolean;\n syn?: StatewireSyn;\n fin?: StatewireHost.Fin;\n};\n\nexport type Gate = { latched: boolean; wake: (() => void) | undefined };\n\nconst newGate = (): Gate => ({ latched: false, wake: undefined });\n\nconst takeGate = (g: Gate) => {\n const was = g.latched;\n g.latched = false;\n return was;\n};\n\nconst waitGate = (g: Gate, timeoutMs?: number) => {\n if (g.latched) {\n g.latched = false;\n return Promise.resolve();\n }\n return new Promise<void>((resolve) => {\n const timer =\n timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n g.wake = undefined;\n resolve();\n }, timeoutMs);\n g.wake = () => {\n clearTimeout(timer);\n g.wake = undefined;\n resolve();\n };\n });\n};\n\nconst openGate = (g: Gate) => {\n if (g.wake) g.wake();\n else g.latched = true;\n};\n\nexport type AttemptOutcome = \"stop\" | \"reattach\" | \"ended\" | \"idle\";\n\nexport type Conn = {\n negotiation?: StatewireProtocol.Options;\n connection: StatewireClient.Connection;\n parked: boolean;\n lease: string | null;\n attempt: number;\n authDenials: number;\n authStale: boolean;\n liveAt: number | null;\n retryAt: number;\n error: StatewireClient.ConnectionError | undefined;\n episode: Episode | null;\n awaitingHello: boolean;\n held: StatewireCmd[];\n gate: Gate;\n abort: AbortController | null;\n lifetime: AbortController | null;\n ctx: StatewireRemoteProps;\n onError: (error: StatewireClient.ConnectionError) => void;\n onChange: (connection: StatewireClient.Connection) => void;\n attemptOnce: (abort: AbortController) => Promise<AttemptOutcome>;\n notify: (connection: StatewireClient.Connection) => void;\n reconnect: () => void;\n};\n\nexport const degradedOf = (state: ConnectionState): boolean =>\n (state.status === \"connecting\" && state.attempt > 0) ||\n (state.status === \"disconnected\" &&\n state.reason !== \"idle\" &&\n state.reason !== \"deferred\");\n\nconst sameState = (a: ConnectionState, b: ConnectionState): boolean => {\n if (a.status !== b.status) return false;\n if (a.status === \"connecting\" && b.status === \"connecting\") {\n return (\n a.attempt === b.attempt &&\n a.cause === b.cause &&\n a.code === b.code &&\n a.nextRetryAt === b.nextRetryAt &&\n a.lastError === b.lastError\n );\n }\n if (a.status === \"disconnected\" && b.status === \"disconnected\") {\n return a.reason === b.reason;\n }\n return true;\n};\n\nconst setStatus = (c: Conn, next: ConnectionState) => {\n if (sameState(next, c.connection) && c.connection.error === c.error) return;\n c.connection = {\n ...next,\n ...(c.error === undefined ? {} : { error: c.error }),\n reconnect: c.reconnect,\n degraded: degradedOf(next),\n };\n c.notify(c.connection);\n c.onChange(c.connection);\n};\n\nconst protocolError = (message: string): never => {\n throw new Error(`statewire: protocol error: ${message}`);\n};\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isNonnegativeSafeInteger = (value: unknown): value is number =>\n Number.isSafeInteger(value) && (value as number) >= 0;\n\nconst isPositiveSafeInteger = (value: unknown): value is number =>\n Number.isSafeInteger(value) && (value as number) > 0;\n\nconst validateOptionalString = (value: unknown, field: string): void => {\n if (value !== undefined && typeof value !== \"string\") {\n protocolError(`${field} must be a string`);\n }\n};\n\nconst validateSynScalars = (syn: Record<string, unknown>) => {\n if (syn[\"seq\"] !== undefined && !isNonnegativeSafeInteger(syn[\"seq\"])) {\n protocolError(\"syn.seq must be a nonnegative safe integer\");\n }\n if (syn[\"ctxSeq\"] !== undefined && !isNonnegativeSafeInteger(syn[\"ctxSeq\"])) {\n protocolError(\"syn.ctxSeq must be a nonnegative safe integer\");\n }\n if (syn[\"retry\"] !== undefined && !isNonnegativeSafeInteger(syn[\"retry\"])) {\n protocolError(\"syn.retry must be a nonnegative safe integer\");\n }\n validateOptionalString(syn[\"id\"], \"syn.id\");\n if (syn[\"idle\"] !== undefined && typeof syn[\"idle\"] !== \"boolean\") {\n protocolError(\"syn.idle must be a boolean\");\n }\n validateOptionalString(syn[\"record\"], \"syn.record\");\n};\n\nexport const validateRefusalSyn = (value: unknown): StatewireSyn => {\n if (!isObject(value)) return protocolError(\"syn must be an object\");\n validateSynScalars(value);\n if (\n value[\"id\"] !== undefined ||\n value[\"idle\"] !== undefined ||\n value[\"record\"] !== undefined\n ) {\n protocolError(\"invalid refusal syn\");\n }\n if (\n value[\"seq\"] === undefined &&\n value[\"ctxSeq\"] === undefined &&\n value[\"retry\"] === undefined\n ) {\n protocolError(\"refusal syn has no watermarks or retry\");\n }\n return value as StatewireSyn;\n};\n\nconst validateCmd = (value: unknown): value is StatewireCmd => {\n if (!isObject(value)) return protocolError(\"cmd entry must be an object\");\n if (!isPositiveSafeInteger(value[\"seq\"])) {\n protocolError(\"cmd.seq must be a positive safe integer\");\n }\n validateOptionalString(value[\"type\"], \"cmd.type\");\n validateOptionalString(value[\"code\"], \"cmd.code\");\n validateOptionalString(value[\"message\"], \"cmd.message\");\n if (value[\"dur\"] !== undefined && value[\"dur\"] !== true) {\n protocolError(\"cmd.dur must be true\");\n }\n return true;\n};\n\nconst validateFin = (value: unknown): value is StatewireHost.Fin => {\n if (!isObject(value)) return protocolError(\"fin must be an object\");\n if (typeof value[\"reason\"] !== \"string\") {\n protocolError(\"fin.reason must be a string\");\n }\n validateOptionalString(value[\"message\"], \"fin.message\");\n validateOptionalString(value[\"code\"], \"fin.code\");\n if (\n value[\"status\"] !== undefined &&\n !isNonnegativeSafeInteger(value[\"status\"])\n )\n protocolError(\"fin.status must be a nonnegative safe integer\");\n if (value[\"retry\"] !== undefined && !isNonnegativeSafeInteger(value[\"retry\"]))\n protocolError(\"fin.retry must be a nonnegative safe integer\");\n return true;\n};\n\nconst validateEnvelope = (value: unknown): StatewireEnvelope => {\n if (!isObject(value)) return protocolError(\"packet must be an object\");\n if (value[\"ops\"] !== undefined && !Array.isArray(value[\"ops\"])) {\n protocolError(\"ops must be an array\");\n }\n if (value[\"cmd\"] !== undefined) {\n const cmd = value[\"cmd\"];\n if (!Array.isArray(cmd)) return protocolError(\"cmd must be an array\");\n for (const entry of cmd) validateCmd(entry);\n }\n if (value[\"idle\"] !== undefined && typeof value[\"idle\"] !== \"boolean\") {\n protocolError(\"idle must be a boolean\");\n }\n if (value[\"next\"] !== undefined) {\n if (value[\"next\"] !== true) protocolError(\"next must be true\");\n if (\n value[\"cmd\"] === undefined ||\n value[\"ops\"] !== undefined ||\n value[\"fin\"] !== undefined\n ) {\n protocolError(\"next must ride a cmd-only packet\");\n }\n }\n if (value[\"fin\"] !== undefined) validateFin(value[\"fin\"]);\n return value as StatewireEnvelope;\n};\n\n// A hold's release delivers, never settles: fin and bare close both drain it.\nconst releaseHeld = (c: Conn) => {\n if (c.held.length === 0) return;\n const held = c.held;\n c.held = [];\n c.ctx.onCmds(held);\n};\n\nconst cmdsOf = (env: StatewireEnvelope): StatewireCmd[] => {\n if (env.cmd === undefined) return [];\n return env.cmd;\n};\n\nconst snapshotOf = (env: StatewireEnvelope): unknown[] => {\n const ops = env.ops;\n if (ops === undefined) return protocolError(\"hello missing snapshot\");\n return reviveOps(ops);\n};\n\nconst helloSynOf = (env: StatewireEnvelope): StatewireSyn => {\n if (!isObject(env.syn)) return protocolError(\"expected hello\");\n validateSynScalars(env.syn);\n if (env.syn[\"retry\"] !== undefined) {\n protocolError(\"hello syn cannot carry retry\");\n }\n return env.syn as StatewireSyn;\n};\n\nconst handleHello = (c: Conn, env: StatewireEnvelope) => {\n const syn = helloSynOf(env);\n if (c.negotiation !== undefined) validateSelection(syn, c.negotiation);\n const ops = snapshotOf(env);\n c.ctx.onHello({\n ops,\n syn,\n });\n c.ctx.onIdle(syn.idle ?? false);\n c.awaitingHello = false;\n c.error = undefined;\n c.liveAt = Date.now();\n c.authDenials = 0;\n c.episode = null;\n setStatus(c, { status: \"connected\" });\n};\n\nlet warnedUnknownSynFact = false;\n\nconst warnUnknownSynFact = () => {\n if (warnedUnknownSynFact) return;\n warnedUnknownSynFact = true;\n console.warn(\"statewire: ignoring unknown syn fact\");\n};\n\nconst deliverSyn = (c: Conn, value: unknown) => {\n if (!isObject(value)) return protocolError(\"syn must be an object\");\n validateSynScalars(value);\n if (\n value[\"version\"] !== undefined ||\n value[\"protocols\"] !== undefined ||\n value[\"record\"] !== undefined ||\n value[\"idle\"] !== undefined\n ) {\n protocolError(\"invalid mid-stream syn\");\n }\n if (\n value[\"seq\"] !== undefined ||\n value[\"ctxSeq\"] !== undefined ||\n value[\"retry\"] !== undefined\n ) {\n c.ctx.onRefusal(validateRefusalSyn(value));\n return;\n }\n if (value[\"id\"] !== undefined) return;\n if (Object.keys(value).length === 0) {\n protocolError(\"invalid mid-stream syn\");\n }\n warnUnknownSynFact();\n};\n\nconst deliverEnvelope = (c: Conn, env: StatewireEnvelope) => {\n if (env.syn !== undefined) deliverSyn(c, env.syn);\n if (env.ops !== undefined) {\n const held = c.held;\n c.held = [];\n c.ctx.onOps({\n ops: reviveOps(env.ops),\n cmds: [...held, ...cmdsOf(env)],\n });\n } else if (env.cmd !== undefined) {\n const cmds = cmdsOf(env);\n if (env.next === true) c.held.push(...cmds);\n else c.ctx.onCmds(cmds);\n }\n if (typeof env.idle === \"boolean\") c.ctx.onIdle(env.idle);\n};\n\nexport const settleFin = (c: Conn, fin: StatewireHost.Fin): AttemptOutcome => {\n const finish =\n fin.meta === undefined\n ? fin\n : { ...fin, payload: reviveValue(fin.payload, fin.meta) };\n releaseHeld(c);\n c.retryAt = Date.now() + (finish.retry ?? 0);\n if (finish.reason === \"idle\") {\n c.ctx.onIdle(true);\n c.attempt = 0;\n c.episode = null;\n c.error = undefined;\n setStatus(c, { status: \"disconnected\", reason: \"idle\" });\n return \"idle\";\n }\n const denial = finish.reason === \"unauthorized\";\n const terminal =\n finish.reason === \"gone\" ||\n finish.reason === \"forbidden\" ||\n finish.reason === \"protocol-error\" ||\n (denial && c.authDenials > 0);\n if (denial) {\n c.authDenials += 1;\n c.authStale = true;\n }\n const report =\n finish.reason !== \"reconnect\" &&\n finish.reason !== \"gone\" &&\n (!denial || terminal);\n c.error = report\n ? Object.assign(new Error(finish.message ?? finish.reason), { fin: finish })\n : undefined;\n if (c.error) c.onError(c.error);\n if (!terminal) {\n c.episode = {\n cause:\n finish.reason === \"reconnect\"\n ? \"reconnect\"\n : denial\n ? \"unauthorized\"\n : \"error\",\n ...(finish.message !== undefined && { message: finish.message }),\n ...(finish.code !== undefined && { code: finish.code }),\n };\n if (denial) openGate(c.gate);\n return \"reattach\";\n }\n c.ctx.onFinish(finish);\n setStatus(c, {\n status: \"disconnected\",\n reason: denial\n ? \"unauthorized\"\n : finish.reason === \"forbidden\"\n ? \"forbidden\"\n : finish.reason === \"protocol-error\"\n ? \"protocol-error\"\n : \"gone\",\n ...(finish.message !== undefined && { message: finish.message }),\n ...(finish.payload !== undefined && { payload: finish.payload }),\n });\n return \"stop\";\n};\n\nexport const handleEnvelope = (\n c: Conn,\n value: unknown,\n): AttemptOutcome | null => {\n const env = validateEnvelope(value);\n if (c.awaitingHello) {\n if (env.fin !== undefined) return settleFin(c, env.fin);\n handleHello(c, env);\n return null;\n }\n deliverEnvelope(c, env);\n if (env.fin !== undefined) return settleFin(c, env.fin);\n if (c.connection.status !== \"connected\") {\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"connected\" });\n }\n return null;\n};\n\nconst dialing = (c: Conn) =>\n setStatus(c, { status: \"connecting\", attempt: c.attempt });\n\nconst scheduleRetry = (\n c: Conn,\n failure: string | undefined,\n immediate: boolean,\n) => {\n if (c.liveAt !== null && Date.now() - c.liveAt >= timing.backoffResetMs) {\n c.attempt = 0;\n }\n c.liveAt = null;\n c.attempt += 1;\n c.episode ??= { cause: \"dropped\" };\n const delay = Math.max(\n immediate ? 0 : backoff(c.attempt),\n c.retryAt - Date.now(),\n );\n setStatus(c, {\n status: \"connecting\",\n attempt: c.attempt,\n ...c.episode,\n nextRetryAt: Date.now() + delay,\n ...(failure !== undefined && { lastError: failure }),\n });\n return delay;\n};\n\nconst reconnectConn = (c: Conn) => {\n if (!c.lifetime) return;\n if (c.connection.status === \"disconnected\") {\n // A reconnect out of a park starts a fresh episode: first dial, attempt 0.\n c.attempt = 0;\n c.authDenials = 0;\n c.episode = null;\n flushTapSync(() => dialing(c));\n }\n openGate(c.gate);\n c.abort?.abort();\n};\n\nconst run = async (c: Conn, lifetime: AbortController, gate: Gate) => {\n const alive = () => c.lifetime === lifetime;\n if (c.parked) {\n await waitGate(gate);\n if (!alive()) return;\n c.parked = false;\n }\n while (alive()) {\n if (c.retryAt > Date.now()) {\n await waitGate(gate, c.retryAt - Date.now());\n continue;\n }\n // The dial is in flight: attempt alone, no backoff fields.\n flushTapSync(() => dialing(c));\n const abort = new AbortController();\n c.abort = abort;\n c.awaitingHello = true;\n c.held = [];\n let outcome: AttemptOutcome | undefined;\n let failure: string | undefined;\n try {\n outcome = await c.attemptOnce(abort);\n } catch (error) {\n if (!abort.signal.aborted) {\n if (\n error instanceof SyntaxError ||\n (error instanceof Error &&\n /^(statewire: protocol error:|Statewire cannot apply)/.test(\n error.message,\n ))\n ) {\n outcome = flushTapSync(() =>\n settleFin(c, { reason: \"protocol-error\", message: error.message }),\n );\n } else if (c.authStale) {\n outcome = flushTapSync(() =>\n settleFin(c, {\n reason: \"unauthorized\",\n message:\n error instanceof Error\n ? error.message\n : \"credential refresh failed\",\n }),\n );\n }\n failure =\n error instanceof Error && error.message ? error.message : \"network\";\n }\n }\n abort.abort();\n if (!alive()) return;\n flushTapSync(() => {\n releaseHeld(c);\n c.ctx.onDetach();\n });\n if (!alive()) return;\n if (\n c.connection.status === \"disconnected\" &&\n ![\"deferred\", \"idle\"].includes(c.connection.reason)\n )\n outcome = \"stop\";\n if (outcome === \"stop\" || outcome === \"idle\") {\n await waitGate(gate);\n continue;\n }\n const immediate = takeGate(gate);\n const delay = flushTapSync(() => scheduleRetry(c, failure, immediate));\n if (delay === 0) continue;\n await waitGate(gate, delay);\n }\n};\n\nexport const unsupportedVersion = (c: Conn, version: string): AttemptOutcome =>\n flushTapSync(() =>\n handleEnvelope(c, {\n fin: {\n reason: \"protocol-error\",\n message: `unsupported protocol version: ${version || '\"\"'}`,\n },\n }),\n ) ?? \"stop\";\n\nexport const resolveHeaders = async (\n headers: StatewireClient.HeadersOption | undefined,\n staleAuth: boolean,\n): Promise<Headers> =>\n new Headers(\n typeof headers === \"function\" ? await headers({ staleAuth }) : headers,\n );\n\n// The stale flag clears only once the resolver returns: a throwing refresh keeps it for the next attempt.\nexport const attachFrame = async (\n c: Conn,\n headers: StatewireClient.HeadersOption | undefined,\n) => {\n const resolved = await resolveHeaders(headers, c.authStale);\n for (const [name, value] of Object.entries(\n negotiationHeaders(c.negotiation ?? {}),\n )) {\n if (!resolved.has(name)) resolved.set(name, value);\n }\n c.negotiation = parseNegotiation(resolved);\n c.authStale = false;\n const lanes = flushTapSync(() => c.ctx.takeAttachLanes());\n return {\n headers: resolved,\n body: JSON.stringify({\n headers: Object.fromEntries(resolved),\n ...(lanes ?? {}),\n }),\n };\n};\n\nexport const useLink = (\n props: StatewireProtocol.Options & {\n url: string;\n isNew?: boolean | undefined;\n onChange?: ((connection: StatewireClient.Connection) => void) | undefined;\n onError?: ((error: StatewireClient.ConnectionError) => void) | undefined;\n ctx: StatewireRemoteProps;\n attemptOnce: (c: Conn, abort: AbortController) => Promise<AttemptOutcome>;\n send: (c: Conn, frame: StatewireFrame) => Promise<StatewireSubmitResult>;\n },\n): RemoteLink => {\n const latest = useRef(props);\n latest.current = props;\n const [, setConnection] = useState<StatewireClient.Connection | null>(null);\n const [c] = useState((): Conn => {\n const conn: Conn = {\n parked: props.isNew ?? false,\n lease: null,\n attempt: 0,\n authDenials: 0,\n authStale: false,\n liveAt: null,\n retryAt: 0,\n error: undefined,\n episode: null,\n awaitingHello: true,\n held: [],\n abort: null,\n gate: newGate(),\n lifetime: null,\n get ctx() {\n return latest.current.ctx;\n },\n onError: (error) => latest.current.onError?.(error),\n onChange: (connection) => latest.current.onChange?.(connection),\n attemptOnce: (abort) => {\n conn.negotiation = latest.current;\n return latest.current.attemptOnce(conn, abort);\n },\n notify: setConnection,\n reconnect: () => reconnectConn(conn),\n connection: {\n ...((props.isNew ?? false)\n ? { status: \"disconnected\", reason: \"deferred\" }\n : { status: \"connecting\", attempt: 0 }),\n degraded: false,\n reconnect: () => conn.reconnect(),\n },\n };\n return conn;\n });\n const [link] = useState(\n (): RemoteLink => ({\n get connection() {\n return c.connection;\n },\n get parked() {\n return c.parked;\n },\n send: (frame) => latest.current.send(c, frame),\n }),\n );\n\n const negotiation = JSON.stringify([\n props.protocol,\n props.wireVersion,\n props.applicationProtocols,\n ]);\n useEffect(() => {\n c.lease = null;\n c.attempt = 0;\n c.authDenials = 0;\n c.authStale = false;\n c.liveAt = null;\n c.retryAt = 0;\n c.episode = null;\n setStatus(\n c,\n c.parked\n ? { status: \"disconnected\", reason: \"deferred\" }\n : { status: \"connecting\", attempt: 0 },\n );\n const lifetime = new AbortController();\n c.lifetime = lifetime;\n c.gate = newGate();\n void run(c, lifetime, c.gate);\n return () => {\n c.abort?.abort();\n lifetime.abort();\n if (c.lifetime === lifetime) c.lifetime = null;\n openGate(c.gate);\n };\n }, [c, props.url, negotiation]);\n\n return link;\n};\n\nexport const classify = (timeout: AbortSignal) =>\n new Error(timeout.aborted ? \"timeout\" : \"network\");\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","names":[],"sources":["../../src/client/session.ts"],"mappings":";;;;;;;;KA6CK;EACH;EACA,WAAW,YAAY,gBAAgB;EACvC;EACA;EACA;;KAGG;WACM;WACA,SAAS;WACT,KAAK;;EAEd;;EAEA;;EAEA;EACA,UAAU;EACV,SAAS,OAAO;;KAGb;WACM;WACA;EACT;;KAeG;KAEO,0BAA0B,kBAAkB;EACtD,eAAe,gBAAgB;EAC/B,gBAAgB,gBAAgB;EAChC;;KAGG;EACH,KAAK;EACL,QAAQ,gBAAgB;EACxB;;KAGG;EACH,SAAS;EACT,WAAW,kBAAkB;EAC7B,kBAAkB,mBAAmB;EACrC,QAAQ,gBAAgB;EACxB,KAAK;EACL;EACA,OAAO,gBAAgB;EACvB,eAAe,mBAAmB;EAClC,QAAQ;EACR;;EAEA;EACA;EACA;EACA;EACA;EACA,eAAe,gBAAgB;EAC/B;EACA;EACA,YAAY;EACZ;EACA,0BAA0B,qBAAqB;EAC/C;EACA,SAAS;EACT;EACA,mBAAmB;EACnB,WAAW,mBAAmB;EAC9B;EACA,SAAS;EACT,QAAQ,UAAU;EAClB,QAAQ;EACR;EACA;EACA;EACA,WAAW;EACX;EACA,WAAW;EACX;EACA,UAAU,mBAAmB,sBAAsB;;cAsIxC,iBACX,GAAG,qBACO,gBAAgB;cAuoBtB,eAAgB,GAAG,SAAS,WAAW;cAuKhC,gBACX,GAAG,SACH,OAAO,gBAAgB;cAYZ,cACX,GAAG,SACH,OAAO,gBAAgB,kBACtB;cA4IU,gBAAiB,GAAG,SAAS;cAGpC,aACJ,GAAG,SACH,OAAO,yBACP;cAuBW,iBAAkB,GAAG,YAAU,mBAAmB;cA+BlD,iBACX,GAAG,SACH,kBACA,gBACA,+BAA0B;cAyBf,sBACX,SAAS,4BACR"}
1
+ {"version":3,"file":"session.d.ts","names":[],"sources":["../../src/client/session.ts"],"mappings":";;;;;;;;KAyCK;EACH;EACA,WAAW,YAAY,gBAAgB;EACvC;EACA;EACA;;KAGG;WACM;WACA,SAAS;WACT,KAAK;;EAEd;;EAEA;;EAEA;EACA,UAAU;EACV,SAAS,OAAO;;KAGb;WACM;WACA;EACT;;KAeG;KAEO,0BAA0B,kBAAkB;EACtD,eAAe,gBAAgB;EAC/B,gBAAgB,gBAAgB;EAChC;;KAGG;EACH,KAAK;EACL,QAAQ,gBAAgB;EACxB;;KAGG;EACH,SAAS;EACT,WAAW,kBAAkB;EAC7B,kBAAkB,mBAAmB;EACrC,QAAQ,gBAAgB;EACxB,KAAK;EACL;EACA,OAAO,gBAAgB;EACvB,eAAe,mBAAmB;EAClC,QAAQ;EACR;;EAEA;EACA;EACA;EACA;EACA;EACA,eAAe,gBAAgB;EAC/B;EACA;EACA,YAAY;EACZ;EACA,0BAA0B,qBAAqB;EAC/C;EACA,SAAS;EACT;EACA,mBAAmB;EACnB,WAAW,mBAAmB;EAC9B;EACA,SAAS;EACT,QAAQ,UAAU;EAClB,QAAQ;EACR;EACA;EACA;EACA,WAAW;EACX;EACA,WAAW;EACX;EACA,UAAU,mBAAmB,sBAAsB;;cAsIxC,iBACX,GAAG,qBACO,gBAAgB;cAkqBtB,eAAgB,GAAG,SAAS,WAAW;cAuKhC,gBACX,GAAG,SACH,OAAO,gBAAgB;cAYZ,cACX,GAAG,SACH,OAAO,gBAAgB,kBACtB;cA+IU,gBAAiB,GAAG,SAAS;cAGpC,aACJ,GAAG,SACH,OAAO,yBACP;cAuBW,iBAAkB,GAAG,YAAU,mBAAmB;cA+BlD,iBACX,GAAG,SACH,kBACA,gBACA,+BAA0B;cAyBf,sBACX,SAAS,4BACR"}
@@ -1,5 +1,6 @@
1
+ import { encodeDocument, reviveDocumentValue } from "../document.js";
1
2
  import { inRange, protocolOffers } from "../wire/protocol.js";
2
- import { encodeParams, encodeValue, reviveResponse, reviveValue } from "../wire/meta.js";
3
+ import { encodeParams, reviveResponse } from "../wire/meta.js";
3
4
  import { applyDocumentOps, findDocument, mainDocument, resolveDocumentKey } from "../wire/documents.js";
4
5
  import { createMethodProxy } from "../util/methodProxy.js";
5
6
  import { StatewireSendError } from "../types.js";
@@ -369,6 +370,36 @@ const publishIngested = (s) => {
369
370
  wake(s);
370
371
  };
371
372
  const snapCtxClock = (s, ctxWm) => {
373
+ if (s.record.context?.recover === "version-1") {
374
+ const document = s.contextDocuments.documents.get(0);
375
+ if (s.contextDocuments.documents.size !== 1 || !document?.main) throw new Error("statewire: version-1 context recovery requires one main document at doc 0");
376
+ const encoded = encodeDocument(document.value);
377
+ const ops = [{
378
+ ...ctxWm === 0 ? {
379
+ op: "mount",
380
+ protocol: document.protocol,
381
+ main: true
382
+ } : {
383
+ op: "replace",
384
+ path: []
385
+ },
386
+ ...encoded
387
+ }];
388
+ s.ctxPending = [{
389
+ seq: ctxWm + 1,
390
+ ops,
391
+ posted: false
392
+ }];
393
+ setRecord(s, {
394
+ ...s.record,
395
+ ctxNextSeq: ctxWm + 2,
396
+ context: {
397
+ ops: contextSnapshot(s.contextDocuments),
398
+ pending: s.ctxPending
399
+ }
400
+ });
401
+ return;
402
+ }
372
403
  if (!(s.ctxPending.every((c, i) => c.seq === ctxWm + 1 + i) && s.record.ctxNextSeq === ctxWm + s.ctxPending.length + 1)) {
373
404
  if (ctxWm > 0) throw new Error("statewire: context history is missing; use a new client id");
374
405
  setRecord(s, {
@@ -528,7 +559,7 @@ const takeAttachLanes = (s) => {
528
559
  s.attachLaneSeqs = [/* @__PURE__ */ new Set(), /* @__PURE__ */ new Set()];
529
560
  const wanted = s.lanesOnAttach;
530
561
  s.lanesOnAttach = false;
531
- if (!wanted || !s.sessionKnown) return null;
562
+ if (!wanted || !s.sessionKnown || s.record.context?.recover !== void 0) return null;
532
563
  const lanes = buildLanes(s);
533
564
  if (!lanes) return null;
534
565
  s.attachLaneSeqs = [new Set(lanes.cmdEntries.map((p) => p.seq)), new Set(lanes.ctxEntries.map((c) => c.seq))];
@@ -693,7 +724,7 @@ const adoptStored = (s) => {
693
724
  for (const { seq, ...command } of stored) {
694
725
  const offers = protocolOffers(s.options);
695
726
  if (offers !== "*" && !offers.some((offer) => offer.name === command.protocol)) continue;
696
- const params = command.meta === void 0 ? command.params : reviveValue([...command.params], command.meta);
727
+ const params = command.meta === void 0 ? command.params : reviveDocumentValue([...command.params], command.meta);
697
728
  const entry = {
698
729
  seq,
699
730
  command,
@@ -775,7 +806,7 @@ const retryFailed = (s, entry) => {
775
806
  });
776
807
  const found = findFailed(s, entry);
777
808
  if (found === void 0) throw unknownFailed(entry);
778
- const params = found.meta === void 0 ? found.params : reviveValue([...found.params], found.meta);
809
+ const params = found.meta === void 0 ? found.params : reviveDocumentValue([...found.params], found.meta);
779
810
  const result = new Promise((resolve, reject) => {
780
811
  const retry = () => {
781
812
  if (!s.running) {
@@ -821,7 +852,7 @@ const retryFailed = (s, entry) => {
821
852
  return result;
822
853
  };
823
854
  const contextSnapshot = (documents) => [...documents.documents].map(([doc, d]) => {
824
- const encoded = encodeValue(d.value);
855
+ const encoded = encodeDocument(d.value);
825
856
  return {
826
857
  op: "mount",
827
858
  ...doc === 0 ? {} : { doc },
@@ -839,6 +870,7 @@ const persistContext = (s) => {
839
870
  ...s.record,
840
871
  context: {
841
872
  ops,
873
+ ...s.record.context?.recover === void 0 ? {} : { recover: s.record.context.recover },
842
874
  pending: s.ctxPending.map(({ seq, ops }) => ({
843
875
  seq,
844
876
  ops
@@ -888,7 +920,7 @@ const changeContext = (s, build) => {
888
920
  const updateContext = (s, operations) => changeContext(s, () => operations);
889
921
  const setContext = (s, value, protocol = s.options.protocol ?? "default") => {
890
922
  if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("statewire: context must be a plain object");
891
- const encoded = encodeValue(value);
923
+ const encoded = encodeDocument(value);
892
924
  changeContext(s, (documents) => {
893
925
  const found = [...documents.documents].find(([, d]) => d.protocol === protocol && d.main);
894
926
  const doc = found?.[0] ?? Math.max(-1, ...documents.documents.keys()) + 1;